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

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

  •  1
     
  •   gamesover · 152 天前 · 4854 次点击
    这是一个创建于 152 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

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

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

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