• 【网络容灾失败案例】三种HTTP请求重试导致重复提交


    使用一些类库进行http请求时,比如使用Apache HttpComponents 库。默认的, HttpClient 尝试自动从 I/O 异常恢复。这种自动恢复机制仅限于一些被认为是安全的异常,比如套接字被重置或者套接字被关闭。但是有些场景重试会造成重复请求风险。

    一般来讲,重复请求比网络异常直接返回失败对用户是更差的体验。因为重复请求,实际造成了影响,但是给上游返回是成功,这样实际结果和给上游的返回结果不一致,自身系统从准确性上来说是不准确的。如果网络异常就返回失败,上游有自主处理的权利,某些场景他们可以自己发起重试,有些可以通过查询、核对等手段获取正确的结果。

    以下三种场景重试会导致重复提交。

    场景一:读超时 Read timeout

    在发HTTP请求时,建立连接后:请求方会先进行请求数据写操作,对方才能收到请求;对方处理完成之后会返回结果,请求方要读取请求结果,这时候是读操作。

    所以如果遇到网络数据读超时,会重复提交。

    场景二:套接字异常 Unexpected end of file from server

    这个异常说明数据已经发送成功。有可能服务端是防火墙的原因,没有处理客户端发来的数据。也有可能是客户端的数据不符合要求,服务端没有做出响应。数据不符合要求可能是传送的数据含有奇怪的字符。也有可能是两边编码不一致导致。客户端将字符串变成字节数据传送时需要指定编码格式,如str.getBytes(“UTF-8”);如不指定,可能导致上面的错误。当URL过长时也会发生此错误。

    返回数据为空或者499的HTTP状态码与上面情况产生原因类似,也很有可能数据已经发送成功,重试需谨慎。

    场景三:连接被重置

    在Java的httpClient组件中,默认是会对套接字被重置做重试的。可是我就实际遇到过套接字被重置,实际上是数据已经发送成功的场景。详见:《connection reset案例的穿越之旅》。简而言之,就是A调用B,B系统前面有一层网络设备。实际上A是和B的网络设备建立长连接。一旦B系统出现错误抛出异常,前面那层网络设备作为客户端感知到了B系统的异常,主动断开连接关闭了自己与A系统的异常。A得到的结果就是连接被重置。所以httpClient等常用组件的默认重试策略也并不可靠。

    编程一生

    因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。

    想知道自己错过了哪些更新,可参考我不定期更新的《系列文章分类汇总》。

  • 相关阅读:
    grid 布局 grid-column-gap 使用后内容超出网格
    SpringBoot学习笔记(一)——初识别SpringBoot与框架整合
    网络安全笔记 -- 文件操作(文件下载读取)
    服务器配置宝塔(Linux 服务器运维管理软件)
    版本控制系统git:一文了解git,以及它在生活中的应用,网站维护git代码,图导,自动化部署代码
    什么是物联网
    大厂秋招真题【前缀和】美团20230826秋招T5-平均数为k的最长连续子数组
    java毕业生设计校园社团管理系统计算机源码+系统+mysql+调试部署+lw
    数字IC笔试千题解--单选题篇(二)
    有关使用HttpServletRequest的Cookie的设置和获取
  • 原文地址:https://blog.csdn.net/xiexiaojing/article/details/126774949