当前位置: 首页 > news >正文

HTTP请求重发

HTTP 协议中,从语义上讲, GET 请求一般是获取服务器端的资源,不会对服务器数据造成副作用,可简单理解为一种“读”操作;而 POST 请求多用于更改(增、删、改)服务器上的资源,会产生一定的副作用。

所以,这样看起来,浏览器是不是就不会因为网络原因啥的自动重发 POST 请求吧?实际上是这样么?

起因

最近在对接地图的一个数据录入接口:前端向后端发送一个 CSV 文件,后端将 CSV 文件中的数据解析出来,然后将数据通过地图接口导入到地图数据库。由于地图提供的接口有点怪异,批量导入数据的接口有一些问题,只能使用单条导入接口,所以在这里, CSV 文件里面有多少条数据,就会访问多少次地图的接口。

虽然有点坑,不过问题究竟是解决了,于是就这样上线了。

天有不测风云,遇到一个客户,一下要导入上千条数据,后端这样串行地一条一条去导入,很轻易地就花了好几分钟。而且还遇到一个诡异的现象:每条数据都导入了两次!

分析

凭借多年的前端开发经验(不要脸了),立马大胆猜测,浏览器发送了两次请求。

于是先到谷歌开发者工具的 Network 标签页检查一下请求,发现此处只记录了一次请求,并且该请求没有响应,好像看不出来什么猫腻。再切换到 chrome://net-internals/ 中看看日志,发现一个 error code , google 了一下,并没有什么结果,看起来也验证不了猜想。

然后再去找后端同学看看接口日志,是不是访问了两次,后端同学似乎稍微有点不太想打日志重新部署(过程比较麻烦),所以先放弃用这种方式求证。

那用啥求证呢? Charles 吧。

在 Charles 中一看,发现发了四次请求,每次请求基本上都耗时六十多秒,每次都没有响应内容。

好了,看起来就是浏览器六十秒超时重发请求。

深入分析

可以转念一想,这对么?

  1. POST 请求就这样轻易地被浏览器超时重发,难道浏览器开发者没考虑过数据重复发送的问题吗?表单 POST 请求手动刷新浏览器的时候都会弹窗提醒用户要不要重复提交数据呢!

  2. 为啥是六十秒呢?时间这么短吗?想想平时本地断点调试服务器代码的时候,那可是会超时老长时间的,所以这六十秒算个啥呢?

搜一搜往上资料,发现 HTTP/1.1 的一处规范 :

If an HTTP/1.1 client sends a request which includes a request body, but which does not include an Expect request-header field with the "100-continue" expectation, and if the client is not directly connected to an HTTP/1.1 origin server, and if the client sees the connection close before receiving any status from the server, the client SHOULD retry the request.

大致意思就是说,如果发送一个请求到服务器端,该请求有请求体,但是请求头里面不包含“ 100-continue ”这种东西,并且客户端没有直接连接到原始的 HTTP/1.1 服务器,此时,如果客户端在接收到服务器发送的 HTTP 状态之前发现服务器主动关掉连接,那么客户端应该重试请求。

那看起来好像就是服务器端主动关掉了连接,导致浏览器重新发送请求了。

我们服务器端使用的是 Tomcat ,查一查资料,发现 Tomcat 默认的 connector 超时时间是六十秒,刚好吻合上了。

问题原因找到了,解决起来就轻松了,此处不赘述。

相关文章:

  • S2SH开发之-整合篇1
  • 基于DotNet构件技术的企业级敏捷软件开发平台 - AgileEAS.NET平台开发指南 - 报表系统集成说明...
  • 解决服务器连接错误Host ‘XXX’ is not allowed to connect to this MySQL server
  • object does not contain a definition for get_range
  • 【我的《冒号课堂》学习笔记】设计模式(3)行为模式
  • 一行时间的输出
  • android wifi SWOL低功耗模式
  • 3287 货车运输
  • Windows SQL2008数据库系列一数据的导入导出
  • dataTable 查询,重置
  • Jsoup学习总结
  • 工作步骤
  • linux分区,磁盘系统的管理,文件系统制作
  • H5上传图片前端预览显示
  • 大型企业网络配置系列课程详解(六) --PPP链路的配置与相关概念的理解
  • 【刷算法】求1+2+3+...+n
  • CNN 在图像分割中的简史:从 R-CNN 到 Mask R-CNN
  • IDEA 插件开发入门教程
  • java多线程
  • Java知识点总结(JDBC-连接步骤及CRUD)
  • Redis的resp协议
  • spring boot 整合mybatis 无法输出sql的问题
  • 从0到1:PostCSS 插件开发最佳实践
  • 对JS继承的一点思考
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 开源SQL-on-Hadoop系统一览
  • 前端技术周刊 2018-12-10:前端自动化测试
  • 深入体验bash on windows,在windows上搭建原生的linux开发环境,酷!
  • 使用common-codec进行md5加密
  • 小程序测试方案初探
  • No resource identifier found for attribute,RxJava之zip操作符
  • Spring Batch JSON 支持
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • (2009.11版)《网络管理员考试 考前冲刺预测卷及考点解析》复习重点
  • (2022 CVPR) Unbiased Teacher v2
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (经验分享)作为一名普通本科计算机专业学生,我大学四年到底走了多少弯路
  • (力扣题库)跳跃游戏II(c++)
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • (转)ORM
  • ./configure,make,make install的作用(转)
  • .bat批处理(一):@echo off
  • .net core 连接数据库,通过数据库生成Modell
  • .NET(C#、VB)APP开发——Smobiler平台控件介绍:Bluetooth组件
  • .NET框架设计—常被忽视的C#设计技巧
  • @FeignClient 调用另一个服务的test环境,实际上却调用了另一个环境testone的接口,这其中牵扯到k8s容器外容器内的问题,注册到eureka上的是容器外的旧版本...
  • @JSONField或@JsonProperty注解使用
  • [ 2222 ]http://e.eqxiu.com/s/wJMf15Ku
  • [ C++ ] STL priority_queue(优先级队列)使用及其底层模拟实现,容器适配器,deque(双端队列)原理了解
  • [ vulhub漏洞复现篇 ] Apache Flink目录遍历(CVE-2020-17519)
  • [.NET 即时通信SignalR] 认识SignalR (一)
  • [AMQP Connection 127.0.0.1:5672] An unexpected connection driver error occured
  • [Android学习笔记]ScrollView的使用
  • [Angular 基础] - 数据绑定(databinding)