事情要从周五晚上说起,好学的朋友在群里问我有没有能够通过框架和项目能对IO有深入学习的。我当时正照例刷着电影解说,感受着逻辑的力量。等看到消息时,已经看到其他朋友热心得给出了神回复:

在我进行了仔细阅读之后,断线一秒钟,之后由衷感叹自己技术不精,没有弄懂问题和回答之间的逻辑关系。于是给出了自己的回复:

通信框架都需要IO知识,服务治理框架、redis和mysql等存储中间件、MQ都有很强的关联。但是一般很少有很强的动力研究的很深。我个人而言,排查生产问题会引出大量想学习的问题。

然后群里简短的介绍了一个案例:

A与B是两个公司的两个服务,A要调用B服务,他们之间可谓万水千山:

A---服务器--F5--交换机1--交换机2--F5--SSL(透传)--F5--交换机--山石防火墙--H3C交换机--思科路由器---专线--网联思科路由器--H3C交换机--思科防火墙--思科交换机--H3C交换机--思科防火墙--F5-SSL-服务器--F5--交换机1--交换机2--F5--SSL--F5--交换机--山石防火墙--H3C交换机--思科路由器---专线--网联思科路由器--H3C交换机--思科防火墙--思科交换机--H3C交换机--思科防火墙--F5--SSL(非透传)--B

咱们简化一下问题:

A请求B,B正常返回结果,但是A反馈收不到。后来B抓包发现在请求还在进行read数据时就收到了connection reset,连接断开。但是并非每笔请求都是如此。而是A有小于30%的概率收不到。而B对接的其他公司却都正常。

在排查日志时发现B收到的请求分成两种,一种是A可以正常收到的,连接是长连接,一种是A不能正常收到的,连接是短连接。但是长连接还是短连接并不是不能正常返回数据的理由。因为数据是分段传输的,每段之间可以灵活采用自己的连接方式,就像传信时,第一段是采用飞鸽传书,第二段是快递员拿到信用快马送到驿站交到仆人手中,第三段是仆人一路小跑将信递交到我手中。

我猛然一惊,这不是穿越剧,而是技术文章。所以放弃长短连接,看看还没有别的线索,终于发现A不能收到的与能收到的相比http header的 X-Forwarded-For 参数中都多出了2个值。

X-Forwarded-For(XFF)是用来识别通过 HTTP 代理或负载均衡方式连接到 Web 服务器的客户端最原始的 IP 地址的 HTTP 请求头字段。在传输过程中,每一个驿站都有可能通过这个字段打上自己的标记。

将 XFF 的值拿给专业人士验证,竟然有人在B服务前面的万水千山之上又加了一座秦岭。更准确的说是加了30%个秦岭。B服务前被加上了一层nginx,且已经灰度了30%的流量。这就对应了有接近30%的请求有问题。也解释了为什么会有短连接,因为nginx在默认不设置时采用短连接。但是还不能解释为什么只有A有问题。

在nginx的日志中发现了lua异常,对于一个lua完全不懂的人果断向百事通大师谷歌求助。但谷歌大师是西域来的,据说见他要翻墙。翻墙不是体力好就更翻得了的,要付费。看着手上唯一个「顺治通宝」,正犹豫之时,又听人说咱们有个国产美人「度娘」在情报方面也很厉害,甚至慢慢在赶超谷歌大师。

我连忙前去请教,得到答复:lua脚本一旦抛出异常,就会中断处理。这就解释了为什么会发生connection reset。nginx抛出异常中断了与上层SSL客户端的连接。SSL又作为服务端感知到了异常,主动发connection reset中断了自己与上层的连接。

这种异常场景最好能复现,但是不懂lua怎么复现,这次咱们要来个大手笔,找到真正的大师求助。于是问题上报到了「编程一生」用户交流群,立即得到了lua可以在线调试的重要线索,问题得到复现:

原来处理请求和响应的lua脚本,里面打印日志时for循环遍历请求和响应的数组,遍历时认为每一项都是一个字符串,A应用在传输过程中,将http header的 XFF 变成了一个数组,lua中数组(table)不能直接强转为字符串,被判断为异常触发reset。这也解释了为什么只有A有问题,因为只有他在传输过程中将原本的字符串转成了数组。

在nginx日志还有一个支线线索是:access日志中显示请求结果是200(正常返回结果),但是响应的 Content-Length 为0 !就是说响应为空。看到上面我们可以知道B返回了信息给nginx,nginx异常导致被处理后的响应丢失。出现这个问题的实际不是A一个,还有另外一家。本身B服务请求量很小,没有报出来也很正常。

从规律上来说:我怀疑可能是commons-httpclient-3.1-rc1版本以下会采用这种策略,因为从请求日志头中看到出现问题的只有两个httpclient版本过来的请求,另外一个是commons-httpclient-3.0-rc3 版本。这里再顺便介绍一下apache各个类型的版本。

Alpha:

Alpha是内部测试版,表示最初的版本,一般不向外部发布。Alpha版会有很多Bug,除非你想去测试最新的功能,否则一般不建议使用。

Beta:

该版本相对于Alpha版已有了很大的改进,消除了严重的错误,但还是存在着一缺陷,需要经过多次测试来进一步消除。这个阶段的版本会一直加入新的功能。`

RC:(Release Candidate)

Candidate是候选人的意思,用在软件上就是候选版本。Release.Candidate.就是发行候选版本。和Beta版最大的差别在于Beta阶段会一直加入新的功能,但是到了RC版本,几乎就不会加入新的功能了,而主要着重于除错! RC版本是最终发放给用户的最接近正式版的版本,发行后改正bug就是正式版了,就是正式版之前的最后一个测试版。`

GA:(general availability)

比如:Apache Struts 2 GA这是Apache Struts 2首次发行稳定的版本,GA意味着General Availability,也就是官方开始推荐广泛使用了。

Release:

该版本意味“最终版本”,在前面版本的一系列测试版之后,终归会有一个正式版本,是最终交付用户使用的一个版本。该版本有时也称为标准版。一般情况下,Release不会以单词形式出现在软件封面上,取而代之的是符号(R)。

从案例来看,用过老的或者不用稳定版本,当了别人的小白鼠,可以获得很多技术精进的机会。因为你会踩很多其他开发者没有踩过的坑。同时还可以获得头发护理的永久免费:

最后澄清一下,文章是原创,但是作者不是我,是咱们。有事群里常交流,你们说我来听~

编程一生

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

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

connection reset案例的穿越之旅相关推荐

  1. Tomcat:Connection reset by peer: socket write error

    Connection reset by peer: socket write error错误分析及解决 Connection reset by peer: socket write error错误分析 ...

  2. gradle build connection reset or protocol_version build failure

    为什么80%的码农都做不了架构师?>>>    gradle build connection reset or protocol_version build failure Mav ...

  3. connection reset by peer问题总结及解决方案

    找遍了 中英文网站,翻遍了能找的角落,发现了出现故障的原因和原理,及改如何处理,这里记录下,希望能帮助到有需要的小伙伴,少走点弯路, 以上就整理内容: connection reset by peer ...

  4. IO异常 java.net.SocketException: Connection reset

    IO异常 java.net.SocketException: Connection reset 参考文章: (1)IO异常 java.net.SocketException: Connection r ...

  5. Socket java.net.SocketException: Connection reset的解决方案

    Socket java.net.SocketException: Connection reset的解决方案 参考文章: (1)Socket java.net.SocketException: Con ...

  6. Connection reset by peer原理解析

    "Connection reset by peer"代表什么? "Connection reset by peer"表示当前服务器接受到了通信对端发送的TCP ...

  7. 【Nignx】 nginx启动http服务,报错 curl: (56) Recv failure: Connection reset by peer

    背景 docker 启动的nginx 服务,容器内端口80,映射到容器外8080,通过 curl -L -I http://xxxx:8080 报错 curl: (56) Recv failure: ...

  8. fatal: unable to access ‘‘: TCP connection reset by peer

    fatal: unable to access '': TCP connection reset by peer 3.20有用按照 只对github.com git config --global h ...

  9. 记录一次Socket异常:java.net.SocketException: Connection reset

    先贴异常信息 java.net.SocketException: Connection resetat java.net.SocketInputStream.read(SocketInputStrea ...

最新文章

  1. PHP面试MySQL数据库的索引
  2. 报名开启 | 李开复等AI大咖齐聚量子位MEET大会,邀你共探新形势下智能产业发展之路...
  3. java字符串逐个分解_改进JAVA字符串分解的方法
  4. 【arduino】最近在搞的项目,ESP32常用模块连接原理图连线图。TTGO-T8-ESP32arduino开发注意事项...
  5. c语言is stack empty,C语言实现栈的问题
  6. 一起读懂传说中的经典:受限玻尔兹曼机
  7. [设计模式-行为型]命令模式(Command)
  8. LeetCode 44.通配符匹配(动态规划)
  9. Aliplayer的各种坑
  10. Webots学习笔记—距离传感器的介绍和四轮小车的避障
  11. office:word在编辑内容时反应迟钝的解决办法
  12. UKF-MATLAB实现
  13. RC并联电路常见应用总结
  14. 【Pyecharts50例】日历图/自定义日历图样式/CalendarOpts
  15. win10c语言弹出框,win10系统启动程序时弹出异常代码c0000005的解决技巧
  16. 机器人教练SWOT分析_全球工业机器人市场四大家族SWOT分析
  17. Morn UI 学习总结
  18. 整体认知主要依靠周边视觉而非中央视觉
  19. 小狼毫自定义短语-Rime-双拼
  20. flstudio插件找不到_FLstudio如何安装插件?

热门文章

  1. python 四象限图_使用matplotlib绘制四象限图
  2. 北京理工大学2020年12月《保险学》作业考核试题
  3. c# 异步回调post请求http
  4. gather() 的函数功能
  5. React 版 sku商品规格选择器和sku生成器
  6. 您的计算机无法访问dota2,解决win7系统DOTA2无法连接至Steam网络的设置方法
  7. Rubymine 无法Debug的方法
  8. 2021最新版谷歌卫星地图已出炉,纯免费下载
  9. Unity3D项目三:牧师与魔鬼
  10. Android文字识别tess-two OCR