V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
gamesover
V2EX  ›  Ruby on Rails

后端收到两次重复 api 请求,如何判断第二次是重复的?

  •  1
     
  •   gamesover · 2022-03-13 00:02:08 +08:00 · 7758 次点击
    这是一个创建于 1024 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我们有个比较古老的 app ,前端是 ember ,后端是 rails

    以前一直都好好,最近遇到 2 次,后端收到貌似重复的 api post 请求

    除了请求的发送的时间不同,数据传过来是一模一样的

    后端有没有办法判断出是 chrome 自动把 api request 重复发送了一遍,有这种可能吗

    还是说用户又点了一次提交按钮

    但照理,提交按钮点一次后就 disable 了啊,实在不懂为什么会出现这种情况

    30 条回复    2022-03-14 16:33:11 +08:00
    waterlaw
        1
    waterlaw  
       2022-03-13 00:09:21 +08:00 via Android
    有可能卡住了还没 disabled ,用户又点了一次, 我们的做法是 {token}+url 做分布式锁的 key, 锁 1 秒后释放,否则提示请求过于频繁。
    waterlaw
        2
    waterlaw  
       2022-03-13 00:13:34 +08:00 via Android
    用户输入不可靠,你怎么判断是浏览器问题还是被爬虫了呢?
    SwinBlackSea
        3
    SwinBlackSea  
       2022-03-13 00:30:37 +08:00
    前端可以做个防抖优化下
    wellsc
        4
    wellsc  
       2022-03-13 00:32:05 +08:00 via Android   ❤️ 1
    保证接口幂等呗
    codehz
        5
    codehz  
       2022-03-13 00:45:19 +08:00 via Android
    加一个 seq 参数,前端 js 确保每次主动调用的时候都是+1 的,后端过滤掉同会话下重复的 seq id(再重复就是业务流程的问题了
    iseki
        6
    iseki  
       2022-03-13 02:54:27 +08:00 via Android   ❤️ 1
    api 加个 uuid 和时间戳,比较时间范围和 uuid 重复
    elfive
        7
    elfive  
       2022-03-13 06:18:52 +08:00 via iPhone   ❤️ 3
    关键字:幂等性
    IvanLi127
        8
    IvanLi127  
       2022-03-13 08:20:58 +08:00 via Android
    每次请求带一次性 token ,用过后就作废。
    xuanbg
        9
    xuanbg  
       2022-03-13 09:20:55 +08:00
    保证接口幂等就好了呀,前端是可以做防抖,但那只是对用户体验的优化,不能从根本上解决问题。
    ichou
        10
    ichou  
       2022-03-13 09:28:13 +08:00 via iPhone
    更大的可能性是 js 事件重复绑定,手抖会有时间差的
    Chism
        11
    Chism  
       2022-03-13 10:15:35 +08:00 via Android
    判断 ip ,header ,body 跟上一次一模一样,而且时间间隔很短,例如 5 秒内,都认为是重复请求。
    这个可能需要结合 redis 比较方便,ip ,header ,body 内容凑一起 md5 一下作为 key ,要返回的内容作为 value ,重复请求就从 redis 里返回上次的数据。
    我没这么做过,纯属想象
    ch2
        12
    ch2  
       2022-03-13 10:51:47 +08:00
    接口在前面做个限流,1 秒 1 次
    mostkia
        13
    mostkia  
       2022-03-13 10:54:27 +08:00
    前端回传的表单中,可以额外增加一个计数器参数。每次点击提交按钮进行自增,如果你后台只想要第一次的请求,可以读取这个 index 来进行判断。一般也不用额外操作,保存在某个变量里就行,页面关闭刷新后 rest ,如果需要适应刷新,可以存到 cookie 里面,浏览器关闭后释放
    paradoxs
        14
    paradoxs  
       2022-03-13 11:15:32 +08:00   ❤️ 1
    直接让前端改就行了啊。 隐藏一个 int i =0; 提交之后+1 , 第二次不让提交或者后端看到 i 不等于 0 就知道怎么处理了啊。
    haoliang
        15
    haoliang  
       2022-03-13 11:37:06 +08:00
    如果用户是不是通过正常手段发起的 post 请求,后端防不住啊。

    我比较实际,说到 post 幂等,我能想到的具体可操作步骤是:后端响应 html 的 form 中带个 xx 字段,提交时回传,后端插入数据时保证那个 xx 字段唯一。保证字段唯一,可以在数据库表中加字段&unique ,也可以放在 redis 的一个时间桶中,或者其他没想到的方式。
    wolfie
        16
    wolfie  
       2022-03-13 11:38:28 +08:00
    根据业务上幂等。
    RedBeanIce
        17
    RedBeanIce  
       2022-03-13 11:39:06 +08:00
    根据业务上幂等。
    zoyua
        18
    zoyua  
       2022-03-13 12:01:42 +08:00 via iPhone
    前段防抖或者后端针对用户做限流
    Jooooooooo
        19
    Jooooooooo  
       2022-03-13 12:11:42 +08:00
    你把什么叫重复先定义好.
    pengtdyd
        20
    pengtdyd  
       2022-03-13 12:43:26 +08:00
    为什么要判断?“除了请求的发送的时间不同,数据传过来是一模一样的” 上面说幂等的我想问一下,难道你们的接口在这种情况下多次请求的结果会不一样???
    lower
        21
    lower  
       2022-03-13 12:53:47 +08:00
    微信浏览器之前有这种相似的坑,微信浏览器客户端的请求会被微信服务器代理再发到 商户服务器……出现过莫名其妙的重复请求👿
    iseki
        22
    iseki  
       2022-03-13 13:02:47 +08:00
    @pengtdyd 比如说创建资源(订单)的接口,如果不增加额外的 限制,不幂等才正常吧
    Suddoo
        23
    Suddoo  
       2022-03-13 13:03:33 +08:00
    不同时间发过来的请求,入库之前先去表里查一下,已存在就直接返回前端,数据已存在
    同时发过来的请求,后端加锁,相当于拒绝其中一个请求
    sparky
        24
    sparky  
       2022-03-13 19:41:24 +08:00 via Android
    用 redis 记录下状态
    a852695
        25
    a852695  
       2022-03-13 22:18:01 +08:00
    用 seq 来标记,客户端发起协议时候带上 seq ,服务器回复 seq+1 ,客户端更新 seq
    jdOY
        26
    jdOY  
       2022-03-13 22:52:30 +08:00
    对请求参数做 md5 校验,可以用 redis 控制时效
    duduaba
        27
    duduaba  
       2022-03-14 09:55:13 +08:00
    让前端改的都是伪后端,前端改只是用户体验,解决了根本问题了吗?
    wd
        28
    wd  
       2022-03-14 10:04:08 +08:00
    很显然你需要先定义好什么是重复请求,然后我估计解决办法也就有了。
    libook
        29
    libook  
       2022-03-14 12:01:56 +08:00
    行业共识:前端去重仅用于用户体验优化目的,业务上要想防止多花还是得由后端去重。
    Jeyfang
        30
    Jeyfang  
       2022-03-14 16:33:11 +08:00
    请求头也一样吗
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1234 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 18:04 · PVG 02:04 · LAX 10:04 · JFK 13:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.