sentinel服务器出现大量的连接问题【转载】

一、问题现象

  • redis服务端的sentinel模块存在大量的established状态的连接,并且这些连接一直不被释放,而客户端的连接数正常。

二、问题排查过程

1、根据连接状态进行推断

  • 服务端存在大量的连接的状态为established,而客户端连接数正常,这说明客户端连接是被非正常的方式关闭的,因为根据TCP关闭连接的四次握手协议来看,只要客户端正常发起了关闭动作,服务端的状态只可能为CLOSE_WAIT/LAST_ACK/CLOSED中的一种。
  • 非正常关闭连接的情况有断电、断网后服务器重启等等,但这些场景出现的次数较少,不会造成这么多连接,究竟是怎样被正常关闭,到这一步还无法判断,只能先从其它方面入手。

2、检查业务系统的redis配置和程序逻辑

  • 检查redis配置,看是否有不规范的配置和不规范的使用redis的代码,经过排查,确定openapi有直接使用JedisSentinelPool类,但并未在spring中配置destroy-method=”destroy”,即在停止应用时释放连接。
  • 排查其它系统,未发现有不正常使用redis的情况,JedisSentinelPool造成的连接数增长也是有限的,即只在启动时才创建sentinel连接,此处暂时排查是业务代码使用redis不规范的问题。

3、从网络寻找线索

  • 通过百度搜索,找不到关于sentinel的该问题的文章。
  • 查看redis、jedis、spring-data-redis官方网站的issues及releaseNotes,均未发现有提及该问题。

4、重新思考产生连接的根源

  • 通过阅读jedis源码,发现连接sentinel的代码只有1处,即系统启动时会先建立一个短连接查询sentinel的主节点,然后开启3(业务系统配置了3个地址)个线程创建3个长连接与3个sentinel相连。短连接会立即释放,而长连接的创建放在循环中,问题可能出现在该处,以下是源码:

public void run() {

running.set(true);

while (running.get()) {

j = new Jedis(host, port);

try {

j.subscribe(new JedisPubSub() {

@Override

public void onMessage(String channel, String message) {

log.fine("Sentinel " + host + ":" + port + " published: " + message + ".");

String[] switchMasterMsg = message.split(" ");

if (switchMasterMsg.length > 3) {

if (masterName.equals(switchMasterMsg[0])) {

initPool(toHostAndPort(Arrays.asList(switchMasterMsg[3], switchMasterMsg[4])));

} else {

log.fine("Ignoring message on +switch-master for master name "

+ switchMasterMsg[0] + ", our master name is " + masterName);

}

} else {

log.severe("Invalid message received on Sentinel " + host + ":" + port

+ " on channel +switch-master: " + message);

}

}

}, "+switch-master");

} catch (JedisConnectionException e) {

if (running.get()) {

log.severe("Lost connection to Sentinel at " + host + ":" + port

+ ". Sleeping 5000ms and retrying.");

try {

Thread.sleep(subscribeRetryWaitTimeMillis);

} catch (InterruptedException e1) {

e1.printStackTrace();

}

} else {

log.fine("Unsubscribing from Sentinel at " + host + ":" + port);

}

}

}

}

正常情况下 j.subscribe会产生阻塞,而出现异常时会重新创建连接并且打印日志“Lost connection to Sentinel at……”

  • 在业务系统搜索“Lost connection to Sentinel at”日志,把所有业务日志都搜索一遍,没有找到该日志,最后终于在nohub日志中找到了(nohub日志在weblogic启动时会被清理,也导致找了几次才找到该日志),通过UltraEdit提取所有该内容的日志,发现了28条日志,将这些日志导出到excel比较,发现日志出现的时间间隔均为2小时11分15秒到2小时11分20秒左右,该日志出现的时间间隔非常有规律,这种规律一定与该问题存在某种联系。

一般在系统中设置时间间隔都会是个整数,2小时11分15秒显得有点怪异,然后将时间换算成秒,看是否为一个常用的或有规律的整数,2小时=7200秒,突然想到操作系统的keepalive设置中有一个7200秒,查一下操作系统默认的设置,参数如下:

net.ipv4.tcp_keepalive_time = 7200   默认 tcp空闲时间

net.ipv4.tcp_keepalive_intvl =75        默认心跳检测时间间隔

net.ipv4.tcp_keepalive_probes = 9     默认检测次数

如果完成9次心跳,仍然发现连接无效的时间为:7200+9*75=2小时11分15秒,由此,基本上可以判断,客户端的连接是被操作系统回收的,结合前面的分析,连接被回收时并未向服务端发送关闭的报文。

  • 通过在网络上搜索,长连接被阻断的原因,看到了防火墙的字样,进一步了解,发现防火墙基本上都有该项功能,即给长连接设置默认的超时时间。

5、与运维进行沟通防火墙问题

  • 刚开始问运行同事A时,同事A说防火墙用的是juniper,但绝对没有为长连接设置默认的超时时间。
  • 进一步搜索juniper的资料,确定是有默认30分钟的超时时间。
  • 与运维同事B沟通,确认有默认的超时时间。防火墙的策略是,当建立连接时,会在防火墙保存一条会话信息,记录了源IP、源端口、目的IP、目的端口。当在超时时间内,该会话代表的连接未有任何数据包时,就会清除该会话,此后若再有数据包过来,由于没有了会话,防火墙会直接丢弃该会话。
  • 要同事B将sentinel的端口26379配置一条永不超时的策略。

6、持续观察测试环境的日志

  • 发现在更改了防火墙超时策略后,仍然出现了一条“Lost connection to Sentinel at”日志,此后一直未出现,由此可见,防火墙确实对连接造成了影响。

7、初步结论

  • 防火墙每30分钟将该连接的会话信息清除,从而导致客户端操作系统检测到心跳失败,随后操作系统清除了客户端连接,使得客户端的连接数能正常释放,由于报文被防火墙丢弃,close信息也不会到达服务端,导致服务端的连接未被及时关闭。

8、继续思考服务断连接不被释放的问题

  • 按道理连接被防火墙阻断后,既然客户端的操作系统能正常回收连接,服务端应该也可以,但服务端的keepalive机制为什么没有发生作用?通过进一步阅读redis客户端-jedis的源码,发现jedis默认开启了keepalive,继续阅读redis的源码,发现redis默认关闭了keepalive,到此所有疑问已经解决。

以上因素使得防火墙每30分钟将该连接的会话信息清除,从而导致客户端操作系统检测到心跳失败,随后操作系统清除了客户端连接,使得客户端的连接数能正常释放,随后客户端的jedis收到异常后重新创建连接,而服务端的keepalive并未执行,以上过程不断循环,导致服务端established状态的连接不断增加并得不到释放。

时间: 2024-10-08 11:13:01

sentinel服务器出现大量的连接问题【转载】的相关文章

Redis集群~StackExchange.redis连接Sentinel服务器并订阅相关事件(原创)

回到目录 对于redis-sentinel我在之前的文章中已经说过,它是一个仲裁者,当主master挂了后,它将在所有slave服务器中进行选举,选举的原则当然可以看它的官方文章,这与我们使用者没有什么关系,而对于sentinel来说,它在进行主从切换时,会触发相关事件,这是和我们开发人员有关系的,如当+switch-master事件被触发时,说明当前Sentinal已经完成了一次主从的切换,并所有服务已经正常运转了. 下面是我这几天作的测试,对于Twemproxy代理和Sentinal哨兵都已

搭建一台VPN服务器实现外部网络连接内部网络

声明 作者:昨夜星辰 博客:http://yestreenstars.blog.51cto.com/ 本文由本人创作,如需转载,请注明出处,谢谢合作! 目的 搭建一台VPN服务器实现外部网络连接内部网络. 环境 服务端:CentOS 6.2 32 客户端:Windows XP 服务端配置 # 关闭SELinux sed -i '/^SELINUX\b/s/=.*/=disabled/' /etc/selinux/config setenforce 0 # 安装EPEL源(默认yum源没有open

用C3P0建立服务器与数据库的连接

1:在MyEclipse建立 Web Service Project 2:在工程中建立servlets包 3:在包中新建Servlet文件(采用new Servlet方法可省去配置web.xml步骤) 4:在工程的WebRoot / WEB_INF / lib 目录下导入c3p0.jar和mysql-connector.jar包,并build path 5:在工程src目录下新建c3p0-config.cml文件 6:在servlet中实例化连接  DataSource dataSource =

Mac搭建本地svn服务器,并用Cornerstone连接服务器

Mac默认已经安装了svn,我们只需要进行配置并开启就可以了 首先我们可以验证一下是否安装了svn,打开终端,输入命令 svnserve --version 这里可以看到目前svn的版本号,说明已经安装好了svn 下面正式开始配置svn 1.创建代码库 我们来创建一个代码库用于保存代码 在终端输入命令 sudo mkdir -p /Users/apple(根据自己的用户名修改)/svn/mycode    //创建了一个文件夹,这个文件夹路径可以自己随意设定 sudo svnadmin crea

几种常见的Windows 服务器无法联网/无法连接远程桌面等故障解决方案

SEO优化扫我一.服务器无法连接远程桌面 1.Ping不通IP,网站打不开,不可以远程连接.可能是服务器死机了,或者网络有问题,请尝试Web重启服务器或联系服务商确认. 2.Ping正常,网站可以打开,远程桌面无法连接,请尝试Web重启服务器或者联系服务商确认.另外你是否修改了远程桌面端口,而没有在防火墙例外该端口. 3.终端服务器超出了最大允许连接数,Windows 2003 系统默认可以同时登陆2个用户,如果第3个人登陆会有此提示.所以,每次使用完毕请在开始菜单注销你当前的登陆线程.出现此问

Mysql权限控制 - 允许用户远程连接(转载)

Mysql为了安全性,在默认情况下用户只允许在本地登录,可是在有此情况下,还是需要使用用户进行远程连接,因此为了使其可以远程需要进行如下操作: 一.允许root用户在任何地方进行远程登录,并具有所有库任何操作权限, 具体操作如下: 在本机先使用root用户登录mysql: mysql -u root -p"youpassword" 进行授权操作: mysql>GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'youp

WebSocket 是什么原理?为什么可以实现持久连接?(转载)

本文转载自知乎,来源如下: 作者:Ovear链接:https://www.zhihu.com/question/20215561/answer/40316953来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 一.WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算)首先HTTP有1.1和1.0之说,也就是所谓的keep-alive,把多个HTTP请求合并为一个,但是Webs

TCP同步与异步,长连接与短连接【转载】

原文地址:TCP同步与异步,长连接与短连接作者:1984346023 [转载说明:http://zjj1211.blog.51cto.com/1812544/373896   这是今天看到的一篇讲到TCP同步与异步,长连接与短连接编程的文章,内容不多,却把概念将的比较清晰.] 标签:TCP 线程 异步 模式 阻塞 首先我简单介绍一下同步TCP编程 与异步TCP编程. 在服务端我们通常用一个TcpListener来监听一个IP和端口.客户端来一个请求的连接,在服务端可以用同步的方式来接收,也可以用

服务器安全部署文档(转载)

转载链接http://www.cnblogs.com/EmptyFS/p/3547796.html 年前一直在赶项目,到最后几日才拿到新服务器新添加的硬盘,重做阵列配置生产环境,还要编写部署文档做好安全策略,交给测试部门与相关部门做上线前最后测试,然后将部署文档交给相关部门同事,让他根据部署文档再做一次系统,以保证以后其他同事能自己正常部署服务器,最后终于赶在放假前最后一天匆忙搞定测试后,简单的指导同事按部署文档将服务器重新部署了一次就先跑路回家了,剩下的就留给加班的同事负责将服务器托管到机房了