一、背景

  假如应用服务器A上有若干模块连接某数据库服务机器B,当B异常假死,需要将B的请求切换到备份系统,这样已经建立的连接就遗留了下来。如果A上hang住的连接占用的服务线程较多,就可能造成业务系统受到影响,因此需要即时清理掉hang住的连接。

二、问题分析

  出现问题时需要快速释放hang住的连接,我们可能用那些方式来解决呢?

  1,重启假死的机器:受限于响应速度、需要承担重启机器的风险

  2,重启程序:能快速中断hang住的连接,但是

  多类模块(php、java、C、script等)连接数据库,重启方式各异;

  部分模块需要加载数据,启动时间长;

  如果模块同时重启,服务可能会受影响;

  部分模块重启后cache失效,对性能有影响;

  3,网络层清理

  根据netstat命令或/proc/net/tcp找到所有与B有关的连接,通过iptables封禁。由于iptables需要包驱动,B假死时iptables不能正常工作,同时A--->B除了TCP重传和心跳检测外,应用层一般为同步读写模式,不保证有包交互;同时长短连接并存,以短连接为主,tcp_keeplive心跳检测特性不能利用。

  4,总结

  hang住的连接主要处于连接建立和ESTABLISHED阶段,建立连接时程序可以配置连接超时,处于连接建立阶段B--->A的包如果没有收到A会重传,这样主要解决机器A上处于阻塞读的连接即可。除了重启程序还有以下方案:

  a,配置读写超时,libmysqlclient默认为1年,应用上有业务需要执行几秒到几百秒,由于系统性能波动,偶尔会有sql执行时间较长,应用不好配置这个值,时间配置太大没有意义。

  b,外部构造RST包关闭连接,由于安全原因RST包需要携带正确的seq,因此需要先记录包序。

  c,使用iptables等工具需要有A ---> B的包驱动

  d,内核API

  问题抽象为:在机器B假死时,如何产生一个A ---> B的数据包

三、实现方案

  1,如果是SYN_SEND状态

  tcp本身有重传,线上重传参数有优化;复用重传数据包中的seq 构造一个 [R.] seq=0 ack=seq+1的包就可以关闭连接;其它方式(配置较小的连接超时,handoff对新连接会自动转向)

  2,如果是ESTABLISHED状态,大部分连接处在这种状态

  在 RFC793(TCP/IP协议)里找到这么一段:

If an incoming segment is not acceptable,an acknowledgment should be sent in reply (unless the RST bit is set, if so drop the segment and return).

内核代码net/ipv4/tcp_input.c中,有具体实现:

static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,

struct tcphdr *th, int syn_inerr)

{ …

省略…

/* Step 1: check sequence number */

if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq)) {

/* RFC793, page 37: "In all states except SYN-SENT, all reset

* (RST) segments are validated by checking their SEQ-fields."

* And page 69: "If an incoming segment is not acceptable,

* an acknowledgment should be sent in reply (unless the RST

* bit is set, if so drop the segment and return)".

*/

if (!th->rst)

tcp_send_dupack(sk, skb);

goto discard;

}

…省略…

}

  因此,可以在A机器上模拟B给A发送一个不带RST标识、seq错误的数据包, A在接收到数据包后会回复一个用于ACK包,此时可以用iptables或其它方式捕获包上正确的seq,发送RST关闭连接,示例图如下:

  3,其它状态暂未处理(强制关闭连接的影响、非syn_send,established状态的处理)

四、具体实现

  环境机器A:192.168.1.4;

  环境机器B:192.168.1.13 ;

  端口3306

  方案1:使用iptables回复reset

  1,通过/proc/net/tcp(或netstat –nat|grep ESTABLISHED)获取所有A ---> B的连接

  2,添加iptables规则iptables -A OUTPUT -p tcp -d 192.168.2.13 --dport 3306 -j REJECT --reject-with tcp-reset

  3,对每一个连接,伪造B ---> A数据包hping3 --numeric --spoof 192.168.2.13 --destport <lport> --baseport 3306 --fin 192.168.2.4 #sendip -p ipv4 -is 192.168.2.13 -p tcp -ts 3306 -td <lport> -tff 1 -tfs 0 -tn 0 192.168.2.4

  4,删除iptables规则iptables -D OUTPUT -p tcp -d 192.168.2.13 --dport 3306 -j REJECT --reject-with tcp-reset

  方案2:

  1,通过/proc/net/tcp获取所有A ---> B的SYN_SENT或ESTABLISHED连接

  2,通过libpcap获取B交互的数据包副本,对匹配A ---> B包,回复RST,关闭连接;发送A--->B的fake FIN包,如果B协议栈还能工作,会回复ack;由于A的端口已被关闭,A上的协议栈会回复RST,关闭B--->A的半连接,包示例

10:08:06.338131 IP 192.168.2.10.43376 > 192.168.2.1.80: Flags [S], seq 1586426180, win 14600, options [mss 1460,sackOK,TS val 51262745 ecr 0,nop,wscale 5], length 0

10:08:06.338500 IP 192.168.2.1.80 > 192.168.2.10.43376: Flags [S.], seq 1103847096, ack 1586426181, win 8192, options [mss 1460,nop,wscale 8,sackOK,TS val 31578197 ecr 51262745], length 0

10:08:06.338614 IP 192.168.2.10.43376 > 192.168.2.1.80: Flags [.], ack 1, win 457, options [nop,nop,TS val 51262745 ecr 31578197], length 0

10:08:13.450742 IP 192.168.2.1.80 > 192.168.2.10.43376: Flags [F], seq 0, win 512, length 0

10:08:13.450766 IP 192.168.2.10.43376 > 192.168.2.1.80: Flags [.], ack 1, win 457, options [nop,nop,TS val 51264523 ecr 31578197,nop,nop,sack 1 {3191120200:3191120201}], length 0

10:08:13.452394 IP 192.168.2.1.80 > 192.168.2.10.43376: Flags [R], seq 1103847097, win 512, length 0 10:08:13.453823 IP 192.168.2.10.43376 > 192.168.2.1.80: Flags [F], seq 0, win 512, length 0

10:08:13.454021 IP 192.168.2.1.80 > 192.168.2.10.43376: Flags [.], ack 1, win 260, options [nop,nop,TS val 31578908 ecr 51264523], length 0

10:08:13.454039 IP 192.168.2.10.43376 > 192.168.2.1.80: Flags [R], seq 1586426181, win 0, length 0

  对1的每一个连接,模拟B给A发送数据包,驱动2执行。

【本文首发于:百度运维空间】http://hi.baidu.com/ops_bd/blog/item/2e049de0422ad637bb382061.html
【关注百度技术沙龙】

转载于:https://blog.51cto.com/baidutech/748596

一种在网络层清理机器假死时TCP连接的方案介绍相关推荐

  1. tomcat假死排查-数据连接池耗尽

    问题背景:测试环境最近隔几周就会出现请求服务没有响应,查看服务进程正产,查看后台日志没有任何报错的日志,查看tomcat下的localhost_access_log.log日志中也没有请求记录. 排查 ...

  2. 混沌系列 | 其实制造“假死”很容易

    点击上方"朱小厮的博客",选择"设为星标" 回复"1024"获取独家整理的学习资料 欢迎跳转到本文的原文链接:https://honeypp ...

  3. [Linux] 假死分析

    所谓假死,就是能ping通,但是ssh不上去:任何其他操作也都没反应,包括上面部署的apache也打不开页面. 作为一个多任务操作系统,要把系统忙死,忙到ssh都连不上去,也不是那么容易的.尤其是现在 ...

  4. qt开启线程界面假死问题解决

    一.前言 在 使用qt高速读取传感器数据时,如果想要将数据实时刷新在界面,就需要开启一个线程单独去跑读取数据函数,并反馈给主程序,否则在主程序中读取和刷新界面会很卡很卡,但是在开启多线程,无外接鼠标键 ...

  5. Tomcat假死的原因及解决方案

    假死:Linux服务器没有崩,浏览器访问页面,出现无法访问的情况但是并没有报4xx或5xx错误,重启tomcat后,恢复正常. 原因:tomcat默认最大连接数(线程数)200个,默认每一个连接的生命 ...

  6. win10记事本编写html没反应,Win10记事本编辑时无响应假死怎么办

    不管是哪一个系统,记事本都是Windows中自带的一个小工具,我们可以进行简单的文字编辑,而很多人升级到win10系统之后,反映说打开记事本编辑的时候遇到无响应假死的情况,如果有编辑了很多文字的话,要 ...

  7. win10记事本编写html没反应,Win10记事本编辑时无响应假死解决方法(图)

    原标题:"Win10记事本编辑时无响应假死怎么办"相关电脑问题教程分享. - 来源:191路由网. 不管是哪一个系统,记事本都是Windows中自带的一个小工具,我们可以进行简单的 ...

  8. mysql假死_win7系统假死的5种情况和处理方法

    情景一:开机假死 开机就假死一般情况是在进入桌面之后,鼠标就变成圆圈状,一直在忙碌状态,会持续很长一段时间,要结束的话只有强制关机. 出现这一类问题的原因比较多,可以从几个方面来看.首先,最好不要安装 ...

  9. 五种Windows 7假死的情景与处理方法

    自己的笔记本经常假死,但又舍不得重装,当然,这种想法也是不对的,我们应该学会解决问题,而不是逃避,这里记录一下解决问题的方法. ------------------------我是分割线------- ...

最新文章

  1. 如何在ToolBar中显示文字和图标,自定义图标大小,并和MenuItem关联
  2. sqlite php 函数大全,SQLite 表达式
  3. Linux:nice函数
  4. python时间序列动图_python中如何用matlibplot画时间序列图?
  5. Kettle使用_21 分组与分析窗口函数
  6. Unity-Animator深入系列---控制IK
  7. FastReport4.6程序员手册_翻译
  8. python手绘效果图_2020高校邦《马克笔手绘效果图》判断题答案2020高校邦《网络数据采集与Python爬虫(山东大学定制班级)》见面课测试答案...
  9. Java将一个对象的属性值copy给另一个相同的对象
  10. [Database] 不知道表名和字段查找值=1234的数据.
  11. Atitit 提现功能安全条例 目录 1. 防余额篡改 1 2. 大额 频繁交易预警系统 1 3. 增加审核 流程 1 4. 增加审计 1 5. 财务出款核对 1 6. Other 2 6.1. 数
  12. 针对我国——国产数据库进行分析
  13. Ovito教程:高清大图渲染方法
  14. acer软件保护卡怎么解除_Acer软件保护卡使用说明全解.doc
  15. 时间片,从多任务系统说起
  16. 云计算服务包括哪三种服务?怎么定义?
  17. Scary Movie 4
  18. android+特殊符号过滤,android 特殊符号过滤
  19. 痞子衡嵌入式:深扒i.MXRTxxx系列ROM中集成的串行NOR Flash启动SW Reset功能及其应用场合...
  20. chatgpt+机器人控制器融合(一)

热门文章

  1. 2014第12周二学习记
  2. nyoj116 士兵杀敌(二)树状数组 插点问线
  3. windows网络负载平衡
  4. Python基本语法_异常处理详解
  5. 编程进阶,学会使用_I、_O、_IO,以及volatile const的意义
  6. web前端性能优化总结
  7. 修改react-native项目名称
  8. 科普云计算知识,迎接云计算大会
  9. [20160513]Restrict Session与静态监听.txt
  10. Linux命令——mv