ZK SYN Flood与参数优化

开发 前端
Zookeeper集群部分节点连接数量瞬时跌零,导致不少服务发生重连,对业务造成了影响(惊吓),本文就发生的现象进行分析和整理。

[[426460]]

引言

Zookeeper集群部分节点连接数量瞬时跌零,导致不少服务发生重连,对业务造成了影响(惊吓),本文就发生的现象进行分析和整理。

一、ZK监控情况

zk集群部分节点服务发生重连

伴随着集群CPU也发生抖动

ZK日志主要为Socket关闭等

  1. [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2182:NIOServerCnxn@368] - caught end of stream exception 
  2. ndOfStreamException: Unable to read additional data from client sessionid 0x0, likely client has closed socket 
  3. at org.apache.zookeeper.server.NIOServerCnxn.doIO(NIOServerCnxn.java:239) 
  4. at org.apache.zookeeper.server.NIOServerCnxnFactory.run(NIOServerCnxnFactory.java:203) 
  5. at java.lang.Thread.run(Thread.java:745) 

小结: zk节点不稳定,导致服务发生重新注册。

二、ZK系统日志

节点x.x.x.15 系统日志在「2021-09-26T19:16:50」「2021-09-26T19:17:50」均发生SYN flooding。

x.x.x.89 系统日志在「2021-09-26T19:16:50」和 「2021-09-26T19:17:50」均发生SYN flooding。

x.x.x.45 系统日志如下「2021-09-26T19:17:50」发生SYN flooding。

小结: 在问题发生时间段三个节点均在「2021-09-26T19:17:50」附近有系统错误日志发生SYN flooding。另外,这三个节点「2021-09-26T12:54:03」均有SYN flooding错误日志,但是未发现ZK节点连接断开情况。那是由于zk抖动客户端重连触发了SYN flooding ? 还是由于先发生SYN flooding导致客户端zk的客户端。

可以确定的是发送了大量请求到zk节点,节点处理不过来了。

三、解决方式

SYN flood维基释意

  1. SYN flood或称SYN洪水、SYN洪泛是一种拒绝服务攻击,起因于攻击者发送一系列的SYN(TCP握手)请求到目标系统。 
  2. SYN flood攻击目前有两种方法,不过都与服务端没收到ACK有关。恶意用户可以跳过发送最后的ACK信息;或者在SYN里透过欺骗来源IP地址,这让服务器送SYN-ACK到假造的IP地址,因此永不可能收到ACK。这两个案例服务器会花点时间等抄收通知,故一个简单的网络壅塞可能是由于没有ACK造成的。 

也就是客户端发送大量TCP连接,TCP的等待队列被塞满,导致CPU内存等资源不足,无法提供服务。关于TCP三次握手详见以前文章《HTTP/2协议之连接前言【原理笔记】》有回顾,文中通过抓报文分析了三次握手过程。

第一步:Client发送[SYN]报文到Server。Client进入SYN_SENT状态,等待Server响应。[SYN]报文序号Seq=x《备注:截图中Seq=0》

第二步:Server收到后发送[SYN,ACK]报文给Client,ACK为x+1(备注:截图中ACK=1); [SYN,ACK]报文序号为y(备注:截图中Seq=0),Server进入SYN_RECV状态

第三步:Client收到后,发送[ACK]报文到Server,包序号Seq=x+1,ACK=y+1。Server收到后Client/Server进入ESTABLISHED状态。

解决方式:

参考下面文章主要对tcp_max_syn_backlog(能接受SYN同步包的最大客户端数)和somaxconn(服务端所能accept即处理数据的最大客户端数量)参数做了调大处理。

  1. https://access.redhat.com/solutions/30453 

小结: 通过调整系统参数和升级zk集群配置来应对,当前的4C8G配置过低,出现的该系统错误日志总体来说是资源处理不过来了。不升级可能在未来某个时间对公司所有服务造成不可计量和不可承受的损失,在相对低峰期升级,同样会对全部服务影响,但是可控可应急,两害相权取其轻。

四、ZK参数优化

ZK配置调整

  1. # ZK中的一个时间单元 
  2. tickTime=2000 
  3.   
  4. # 默认10,Follower在启动过程中,会从Leader同步所有最新数据,将时间调大些 
  5. initLimit=30000 
  6.  
  7. # 默认5,Leader与flower的心跳检测,超过后flower表示下线,略微调大一些    
  8. syncLimit=10 
  9.  
  10. # 默认60,单客户端IP级别与单zk节点的连接数限制,调整为2000     
  11. maxClientCnxns=2000 
  12.  
  13. # 最大的会话超时时间,其实交给客户端了 
  14. # 默认的Session超时时间是在2 * tickTime ~ 20 * tickTime这个范围     
  15. maxSessionTimeout=60000000     
  16.      
  17. # 两次事务快照之间可执行事务的次数,默认的配置值为100000 
  18. snapCount=3000000 
  19.  
  20. # 日志文件大小kb,切换快照生成日志 
  21. preAllocSize=131072     
  22.  
  23. # 自动清理snapshot和事务日志,清理频率,单位是小时     
  24. autopurge.purgeInterval=6   
  25.  
  26. # 保留的文件数目,默认3个     
  27. autopurge.snapRetainCount=10 
  28.  
  29. # 存储快照文件snapshot的目录     
  30. dataDir=/data/zookeeper 
  31.  
  32. # 事务日志输出目录 
  33. dataLogDir=/data/zookeeper/log     

Jvm参数

在zookeeper/conf创建java.env文件

  1. export JVMFLAGS="-Xms10G -Xmx10G -Xmn4G -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/data/zkout/gc/gc-%t.log $JVMFLAGS" 

日志滚动

conf/log4j.properties调整为滚动输出

  1. zookeeper.root.logger=INFO, ROLLINGFIL 
  2.  
  3. zookeeper.log.dir=/data/zkout/logs 
  4.  
  5. log4j.appender.ROLLINGFILE=org.apache.log4j.DailyRollingFileAppender 
  6. #log4j.appender.ROLLINGFILE.Threshold=${zookeeper.log.threshold} 
  7. #log4j.appender.ROLLINGFILE.File=${zookeeper.log.dir}/${zookeeper.log.file} 
  8. log4j.appender.ROLLINGFILE.DatePattern='.'yyyy-MM-dd 
  9.  
  10. log4j.appender.ROLLINGFILE.MaxFileSize=100MB 

zkEnv.sh调整日志输出方式

  1. if [ "x${ZOO_LOG_DIR}" = "x" ] 
  2. then 
  3.     ZOO_LOG_DIR="/data/zkout/logs/" 
  4. fi 
  5.  
  6. if [ "x${ZOO_LOG4J_PROP}" = "x" ] 
  7.      
  8. then 
  9.     # ZOO_LOG4J_PROP="INFO,CONSOLE" 
  10.     ZOO_LOG4J_PROP="INFO,ROLLINGFILE" 
  11. fi 

系统参数调整

limits.conf 设置用户能打开的最大文件数

  1. vim /etc/security/limits.conf 
  2. End of file 
  3. root soft nofile 655360  #根据部署用户 
  4. root hard nofile 655360 
  5. * soft nofile 655360 
  6. * hard nofile 655360 

/etc/sysctl.conf调整

  1. vim /etc/sysctl.conf 
  2.  
  3. # 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭; 
  4. net.ipv4.tcp_syncookies = 1 
  5.  
  6. # 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;为1,开启     
  7. net.ipv4.tcp_tw_reuse = 1 
  8.  
  9. # 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭;为1,开启;     
  10. net.ipv4.tcp_tw_recycle = 1   
  11.   
  12. # 修改系統默认的 TIMEOUT 时间     
  13. net.ipv4.tcp_fin_timeout = 5     
  14.  
  15. # the kernel's socket backlog limit     
  16. net.core.somaxconn = 65535 
  17.  
  18. # the application's socket listen backlog     
  19. net.ipv4.tcp_max_syn_backlog = 100000 
  20.   
  21. sysctl -p     

本文转载自微信公众号「瓜农老梁」,可以通过以下二维码关注。转载本文请联系瓜农老梁公众号。

 

责任编辑:武晓燕 来源: 瓜农老梁
相关推荐

2010-02-23 13:24:33

2010-09-17 15:36:21

2010-09-30 11:02:33

2010-09-30 10:01:38

2010-09-13 10:26:48

2010-08-24 11:24:35

2010-03-10 14:18:09

2010-04-22 18:43:49

Aix系统

2009-08-20 16:45:32

2010-09-13 10:45:04

2019-11-17 22:11:11

TCPSYN队列Accept队列

2010-11-25 10:12:02

MySQL查询优化

2010-05-12 14:14:41

MySQL性能优化

2010-06-13 15:42:37

MySQL性能优化

2010-03-29 16:31:48

2009-04-28 09:25:15

Oracle系统参数优化

2020-12-21 10:00:49

算法模型优化

2024-10-18 09:05:42

2024-10-09 23:32:50

2012-07-06 09:51:34

点赞
收藏

51CTO技术栈公众号