背景
- 技术栈基于finagle,scala与java混合编程。
- 历史遗留问题,目前http接口调rpc默认走zk随机选择节点网络通信,本来本地的代码本地调用就行,现在通过zk中转了一层。所以需改成本地调用方式,由于rpc处理层耦合代码太多,不好下沉到service层。折中且最快的方式是:走zk改成本地网络。
- 每次重新部署监控报一堆500问题,异常皆是Connect reset by peer:Socket write error。
网络超时
解决重启报500问题,产生了新的问题,频繁报超时:



定位问题过程
1.尝试既监听localhost,也监听对外ip,uc http接口调rpc直连localhost。
在staging环境尝试监听所有接口:


指定0.0.0.0 启动之后注册到zk的是一个域名,不是ip。

部署上去未见其他异常
灰度了2小时监控未见相关异常。
但是证券事业部的同事反馈rc的服务启动不起来,依赖uc的rpc客户端连接报Endpint is marked down.
回滚之后比较下注册到zk上的节点信息:
回滚前注册的是一个域名。
回滚后恢复正常,zk上注册的是一个docker对外ip。

2.尝试改写注册逻辑
原始代码:

现有代码:
改写注册到zk的ip地址,启动监听在0.0.0.0,上报给zk的是docker对外ip。

在staging环境部署了下,注册到zk不再是一个域名。
2019-09-05 16:20 上线,持续观察一周看下效果。
直连localhost还是报超时问题。

超时的问题周末曾出现,只在周末的时候出现。
3.修改内核参数

抛一个问题:走虚拟网卡127.0.0.1:7950报连接超时问题可能会是什么原因导致,会是syn队列配置过小问题吗?127.0.0.1:7950和docker对外ip:7950会共用syn连接队列和accept队列吗?
联系运维,在物理机37.15修改内核参数:

实验失败:37.15又出了超时,咨询sre,docker网络堆栈隔离,物理机做的修改无法作用于docker。
4.抓包分析
2019-09-12 早上10点多抓包,抓包节点: 54.54/54.58/20.205/21.83/21.84
16:54分,21.83节点发生超时现象。


发syn包过1秒才重传syn包,跟抛异常的时间窗口比较接近,刚好finagle rpc客户端连接超时时间设置的是1秒。
抓包看到的效果,这段时间端内有3条连接有重传,第二次重传都成功建立连接。netty3默认的连接超时时间是10秒,finagle给改成了1秒,考虑改成2秒试试。
建立TCP链接时的参数
net.ipv4.tcp_syn_retries#syn包重传多少次后放弃,重传间隔是2的n次方(1s,2s,4s..)默认第一次重试间隔1秒,之后2秒...
net.ipv4.tcp_synack_retries#syn ack包重传多少次后放弃
net.ipv4.tcp_max_syn_backlog#syn包队列
5.排查结论
finagle rpc client直连和走zk区别在哪里,确认下走zk会不会有连接失败重试策略?
区别:走zk选择节点建连失败会尝试其他节点。走本地只有一个节点,建连失败只能依赖tcp重传。
6.解决
尝试把超时时间改成2秒看下超时情况。

走zk,选择一个节点建连失败会尝试另一个节点,配置至少两个ip模拟走zk的效果,第一次建连失败尝试其他节点大概率都会成功。

2019-09-18:16:00:00全部上到线上,从这个时间点开始观察超时情况。
2019-09-19:全天未见超时异常。
2019-09-20:全天未见超时异常。
2019-09-21:全天未见超时异常。
2019-09-22:全天未见超时异常。
2019-09-23:全天未见超时异常。
2019-09-24:全天未见超时异常。
2019-09-25:全天未见超时异常。
2019-09-26:全天未见超时异常。
2019-09-27:全天未见超时异常。

网友评论