引子
刚才下班回家路上,无意中听到大街上放的歌,歌词有这么一句:“毡房外又有驼铃声声响起,我知道那一定不是你”。这一句我似乎听懂了歌者的魂牵梦绕和绝望,如果在十年前我大概只能感受出悠扬的声调里溢出的悲凉吧。
在工作上,我们有十年的时间来把思考能力上升一个等级。对于一个问题,需要在很短的时间反复思考,深层次地弄懂。懂得,有三个初级境界,对应三个方法:
1>字面理解-what、why、how
2>前因后果-5why
3>选择最优-SMART
回到主线:为什么是初级境界?我自己也不知道更高级别的境界是有什么,因为自己境界没有达到。但是至少有:刻入骨髓 这一境界。
举个例子:十二年前,有次在大街上走,我走过一个【北京银行】的大门,银行二楼的玻璃哗啦啦掉下来。我知道身后有危险,有很多玻璃落到了距离我身后不到十公分的地方。我当时很镇定的继续向前走。等过了危险区,我很想神经质的大叫。因为走路时再多犹豫2秒,可能脑袋上被扎的全是玻璃。所以走路时时时刻刻都会想着离楼房远一些,并且好像感受到了自己脑袋被玻璃扎。我理解这可以算作把楼房玻璃很危险的理解刻入骨髓。
字面理解
今天举的这个例子纯粹是技术问题,终于不需要用蹩脚的比喻把事情描述的更难理解来达到脱敏的效果。
what
我们采用的是dubbo服务,这是个稳定成熟的RPC框架。但是我们在某些应用中会发现,只要这个应用一发布(或者重启),就会出现请求超时的问题,如下图所示:
而且都是第一笔请求会报错,之后就再也没有问题了。
(上图来源于网络,下面有参考文章。如果可以,我想把这些字调的再小一些)
why
我当时很快就定位了问题,因为在内网wiki上、技术博客上,很多人都写了这个坑。所以不讲排查思路了,直接讲结论:
在server端连接数过多, linux系统有个连接队列溢出了。溢出的连接被丢弃,但是client端不知道,仍然给此server发送消息。连接没有建立自然发送不成功。client发第一笔消息超时,相当于探活失败,client端于是重新建立连接。连接成功建立后开始正常的通信,所以后面都成功了。
how
怎么来解决这个问题呢?四个思路。
第一个是队列溢出了,那就说明队列太小。可以把队列值改大。dubbo使用的是一个写死的默认值:50。可以修改dubbo源码把值改大或者干脆动态获取队列值。
第二个是队列数不变,实际连接数减少。减少server端的连接方,比如有些client端其实没有实际业务调用这个server端了,就双方聊聊把无用的依赖去掉。
第三个是可以让服务端在丢弃连接的同时给client端通知一下,linux有个系统参数
/proc/sys/net/ipv4/tcp_abort_on_overflow,默认为0。不会给client端发通知,但是设置为1时会给server端发一个reset请求,客户端收到会重连。
第四个是让client端定时心跳探测。探测发现超时了马上重连,超时的那笔只是探测请求,不影响业务。