V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
twogoods
V2EX  ›  程序员

一秒内的重复请求如何处理

  •  
  •   twogoods · 2016-12-07 09:30:02 +08:00 · 12646 次点击
    这是一个创建于 2903 天前的主题,其中的信息可能已经有所发展或是发生改变。
    一个接口部署了三台机器, Nginx 做负载均衡,重复请求怎么处理,上 zookeeper , redis 吗?
    第 1 条附言  ·  2016-12-07 12:40:54 +08:00
    业务是 insert 一条数据比如说订单这样的,重复可能就是前端点得太快造成的,所以基本就是几秒钟时间左右的幂等
    30 条回复    2016-12-09 06:13:26 +08:00
    9hills
        1
    9hills  
       2016-12-07 09:46:23 +08:00 via iPhone
    简单但是有很大局限性的方法

    负载均衡改成源地址 Hash ,保证同一来源的请求落到一个后端

    其他的都需要有个
    9hills
        2
    9hills  
       2016-12-07 09:47:42 +08:00 via iPhone
    接上

    其他的基本都需要类锁服务,但是局限性也少了很多。 Redis 就不错,大部分场景也能 Hold 。
    moorlop
        3
    moorlop  
       2016-12-07 09:54:02 +08:00 via iPhone
    requestID
    xjp
        4
    xjp  
       2016-12-07 09:59:11 +08:00 via iPhone
    我们是用用 redis 做锁的 获取到锁的请求才正常处理 其他的请求直接返回错误
    lhbc
        5
    lhbc  
       2016-12-07 10:29:53 +08:00 via iPhone
    接口所有操作都是幂等的吗?
    幂等的话多次请求并没有关系。
    mengskysama
        6
    mengskysama  
       2016-12-07 10:45:20 +08:00 via iPhone   ❤️ 2
    我觉得 lz 没有表达清楚这个问题,这个请求业务逻辑是什么样的。

    如果是重复的 get 请求最高效的做法是在 nginx 上做合并回源,确保请求同一个资源只有一个请求打到后端,其他请求都要 pending 这个请求的结果
    sciooga
        7
    sciooga  
       2016-12-07 10:50:48 +08:00
    关键词 惊群问题
    twogoods
        8
    twogoods  
    OP
       2016-12-07 12:30:39 +08:00
    @lhbc 如果业务是 insert 一条数据,那幂等应该怎么处理?最直白就是一秒的相同请求只执行一个其他都丢弃
    phpman
        9
    phpman  
       2016-12-07 12:33:25 +08:00
    重复请求有问题么?一秒内重复请求和一分钟内重复请求有什么区别呢?楼主还是要把业务逻辑表述清楚
    ihuotui
        10
    ihuotui  
       2016-12-07 12:56:29 +08:00
    nginx session sticky 保持会话
    iphash 负载策略
    requestToken 过滤重复提交
    Infernalzero
        11
    Infernalzero  
       2016-12-07 13:00:59 +08:00
    session 里加 token
    具体可以搜 session 重复提交
    jwdstefanie
        12
    jwdstefanie  
       2016-12-07 13:55:27 +08:00
    重复提交 前台通过 ajax 提交的时候就可以过滤了 jquery 的 ajax 方法有个 gobal 属性建议看看
    honam
        13
    honam  
       2016-12-07 14:10:18 +08:00
    @xjp +1 ,锁的 key 根据请求参数来定,你有什么特别的实现相互交流交流
    twogoods
        14
    twogoods  
    OP
       2016-12-07 14:16:02 +08:00
    @ihuotui requestToken 过滤重复提交 能否给一个详细的思路
    tofishes
        15
    tofishes  
       2016-12-07 14:54:39 +08:00
    @jwdstefanie 数据完整性、安全性等不要依赖前端,必须后端解决。
    EthanLiao
        16
    EthanLiao  
       2016-12-07 17:28:07 +08:00
    @honam @xjp 具体的实现过程是怎样的,可否分享一下。
    tinyproxy
        17
    tinyproxy  
       2016-12-07 18:04:28 +08:00   ❤️ 3
    hoythan
        18
    hoythan  
       2016-12-07 18:22:11 +08:00
    requestID 年月日时分秒毫秒微妙纳秒+8 位随机数。
    frankerzeng
        19
    frankerzeng  
       2016-12-07 18:55:23 +08:00
    superrz
        20
    superrz  
       2016-12-07 18:59:13 +08:00
    从前端开始处理掉这个问题吧
    amey9270
        21
    amey9270  
       2016-12-07 19:08:17 +08:00
    这是一个 csrf 的问题啊
    iMouseWu
        22
    iMouseWu  
       2016-12-07 19:22:46 +08:00
    赞同 @phpman 观点,这个需要看业务场景。
    如果是重试的重复请求,可以通过一个业务 /逻辑唯一 Id 来避免重复提交
    还有一种是明显按钮已经灰显了,但是用户通过自己拼的 URL 来强行提交,就把它当做一次正常请求
    ihuotui
        23
    ihuotui  
       2016-12-07 20:42:05 +08:00 via Android
    @twogoods 先分析这个过程,因为网络原因,然后前端或者 app 的请求重复了,但是内容一样,所以在请求中增加一个唯一的请求码,然后后台对于记录这个用户的上一次请求码,然后对比,一样就抛弃。先分析原因,再思考解决,然后验证。
    rtx3
        24
    rtx3  
       2016-12-07 21:00:39 +08:00
    请求带有状态码?能将 session 独立出去在服务器端重新取得状态吗
    rtx3
        25
    rtx3  
       2016-12-07 21:02:24 +08:00
    弄错了 这个貌似要前段处理
    slixurd
        26
    slixurd  
       2016-12-07 21:29:44 +08:00   ❤️ 1
    这种不都是前端控制一下就完事的事情么...
    就拿创建订单来说,这个还能加锁?
    一个正常的流程就是:用户在购物车点击下单,那么前端应该就把按钮置灰,发送请求,如果请求超时 /失败,就重置按钮状态允许重新下单.
    没听说过要在后端做这个请求的去重的...
    也没办法判断这个请求是否重复....
    ElmerZhang
        27
    ElmerZhang  
       2016-12-08 09:47:17 +08:00
    前端在给后端 POST 数据之前,先到后端请求一个 uniqid , POST 数据时带上这个 uniqid ,后端对于 uniqid 相同的请求只处理一次。
    这个机制也可以用来防跨站、防刷
    KoleHank
        28
    KoleHank  
       2016-12-08 13:46:39 +08:00
    前端处理下就好了, underscore 都有类似的工具类方法提供,多长时间内的只执行一次的这种
    billowqiu
        29
    billowqiu  
       2016-12-08 23:31:50 +08:00
    避免重复请求,貌似只能通过请求 ID 来区分了。
    如果是前端的重复点击,那么就要保证前端每次传递同一个请求 ID ;
    如果用户不走前端页面请求,直接发 URL 改变对应的 ID ,那么只能从后端处理,后端必须验证该 ID 是否有效。
    总结:
    最保险的就是请求 ID 由后端产生,后端收到请求时验证一下 ID 是否合法,是否重复。
    hobbyliu
        30
    hobbyliu  
       2016-12-09 06:13:26 +08:00 via Android
    @ElmerZhang +1 ,我们做过一个开放平台,用户下单的流程是: 1 、请求获取订单 id 接口。 2 、带上第一步的订单 id,请求下单接口,
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5947 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 03:30 · PVG 11:30 · LAX 19:30 · JFK 22:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.