介绍Zookeeper集群中部分节点的连接数瞬间降为零,导致很多服务重连,影响业务(吓)。本文对发生的现象进行了分析和梳理。1.ZK监控状态ZK集群重连部分节点服务和集群CPU抖动ZK日志主要是Socket关闭等,likelyclienthasclosedsocketatorg.apache.zookeeper.server.NIOServerCnxn.doIO(NIOServerCnxn.java:239)atorg.apache.zookeeper。server.NIOServerCnxnFactory.run(NIOServerCnxnFactory.java:203)atjava.lang.Thread.run(Thread.java:745)总结:zk节点不稳定,导致服务重新注册。2.ZK系统日志节点x.x.x.15系统日志在“2021-09-26T19:16:50”和“2021-09-26T19:17:50”出现SYN泛洪。x.x.x.89系统日志中的“2021-09-26T19:16:50”和“2021-09-26T19:17:50”都发生了SYN泛洪。x.x.x.45系统日志如下“2021-09-26T19:17:50”发生SYN泛洪。总结:在问题发生的时间段内,系统错误日志中“2021-09-26T19:17:50”前后三个节点均出现SYN泛洪。另外,这三个节点“2021-09-26T12:54:03”都有SYN泛洪错误日志,但是没有发现ZK节点连接断开。是因为zk抖动客户端重连触发了SYN泛洪吗?还是因为SYN泛洪先发生导致客户端zk的client.可以确定的是,大量请求发送到zk节点,节点无法处理。三、解决方案SYNflood维基解释SYNflood或SYNflood,SYNflood是攻击者向目标系统发送一系列SYN(TCP握手)请求而引起的拒绝服务攻击。SYNflood攻击目前有两种方式,但都与服务器收不到ACK有关。恶意用户可以跳过发送最后的ACK报文;或在SYN中欺骗源IP地址,使服务器向假IP地址发送SYN-ACK,因此永远不可能收到ACK。在这两种情况下,服务器都会花费一些时间等待接收通知,因此简单的网络拥塞可能是由于没有ACK。即客户端发送大量TCP连接,TCP等待队列已满,导致CPU内存等资源不足,无法提供服务。关于TCP三次握手的详细内容,可以看之前的文章《HTTP/2协议之连接前言【原理笔记】》进行回顾。本文通过抓包分析三次握手过程。第一步:客户端向服务器发送[SYN]消息。Client进入SYN_SENT状态,等待Server响应。[SYN]消息序号Seq=x《备注:截图中Seq=0》步骤2:Server收到[SYN,ACK]消息后发送给Client,ACK为x+1(注:截图中ACK=1);[SYN,ACK]报文序号为y(备注:截图中的Seq=0),服务器进入SYN_RECV状态第三步:客户端收到后,向服务器发送[ACK]报文,该数据包序号Seq=x+1,ACK=y+1,Server收到后,Client/Server进入ESTABLISHED状态。解决方法:参考下面文章增加tcp_max_syn_backlog(最大可以接受SYN同步包的客户端数)和somaxconn(服务端可以接受的最大客户端数,即进程数据)的参数。https://access.redhat.com/solutions/30453总结:通过调整系统参数,升级zk集群配置,目前4C8G配置太低,出现的系统错误日志一般无法处理资源。不升级可能会在未来某个时间对公司的所有服务造成无法估量和难以承受的损失。在比较低的高峰期升级也会影响所有的服务,但是是可控的,也是应急的,两害相权取其轻。4.ZK参数优化ZK配置调整#ZK中的一个时间单位tickTime=2000#Default10,Follower在启动时会同步Leader的所有最新数据,增加时间initLimit=30000#Default5,Leader和Flower的心跳检测,超过之后flower表示下线,稍微增加syncLimit=10#默认是60,单个clientIP级别和单个zk节点的连接数限制,调整为2000maxClientCnxns=2000#最大session超时时间,其实给客户端#默认session超时在2*tickTime~20*tickTime范围内maxSessionTimeout=60000000#两次事务快照之间可以执行事务的次数,默认配置值为100000snapCount=3000000#日志文件大小kb,切换快照生成日志preAllocSize=131072#自动清理快照和事务日志,清理频率,单位是小时=/data/zookeeper#事务日志输出目录dataLogDir=/data/zookeeper/logJvm参数在zookeeper/conf中创建一个java.env文件.log$JVMFLAGS"日志滚动conf/log4j.properties调整为滚动输出zookeeper.root.logger=INFO,ROLLINGFILzookeeper.log.dir=/data/zkout/logslog4j.appender。ROLLINGFILE=org.apache.log4j.DailyRollingFileAppender#log4j.appender.ROLLINGFILE.Threshold=${zookeeper.log.threshold}#log4j.appender.ROLLINGFILE.File=${zookeeper.log.dir}/${zookeeper.log.file}log4j.appender.ROLLINGFILE.DatePattern='.'yyyy-MM-ddlog4j.appender.ROLLINGFILE.MaxFileSize=100MBzkEnv.sh调整日志输出方式if["x${ZOO_LOG_DIR}"="x"]thenZOO_LOG_DIR="/data/zkout/logs/"fiif["x${ZOO_LOG4J_PROP}"="x"]then#ZOO_LOG4J_PROP="INFO,CONSOLE"ZOO_LOG4J_PROP="INFO,ROLLINGFILE"Fi系统参数调整limits.conf设置用户最多可以打开的文件数vim/etc/security/limits.conf#endoffilerootsoftnofile655360#根据部署用户roothardnofile655360*softnofile655360*hardnofile655360/etc/sysctl.conf调整vim/etc/sysctl.conf#表示启用SYNCookies。当SYN等待队列溢出时,启用cookie进行处理,可以防止少量的SYN攻击。默认为0,表示关闭;net.ipv4.tcp_syncookies=1#表示启用重用。允许TIME-WAITsockets被重新用于新的TCP连接,默认为0,表示关闭;1、opennet.ipv4.tcp_tw_reuse=1#表示开启TCP连接中TIME-WAITsockets的快速回收,默认为0,表示关闭;为1,表示开启;net.ipv4.tcp_tw_recycle=1#修改系统默认TIMEOUT时间net.ipv4.tcp_fin_timeout=5#内核的socketbackloglimitnet.core.somaxconn=65535#应用的socketlistenbacklognet.ipv4.tcp_max_syn_backlog=100000sysctl-p本文转自微信公众号“瓜农老粮”,可以通过以下二维码关注。转载本文请联系瓜农老梁公众号。
