本期的“含英咀华”为大家带来的是社区技术论坛中的精选文章《》,希望能对大家的工作学习有所帮助。
为了提升数据库访问效率,一般应用都是通过长连接的方式访问数据库,以避免TCP连接建立与断开的系统开销。在分布式数据库环境下,应用通过LVS与DBProxy建立连接,实现负载均衡。
浙江公司在BSS 3.0一阶段上线过程中,发现应用与数据库之间的长连接,在业务低峰期(晚上)会被自动断开,第二天发起业务请求,会报数据库连接错误。
一、问题分析
检查发现客户端到数据库的连接数经过一段时间后会下降,也就是一部分连接被关闭了!通过排查,发现LVS中有关于TCP连接会话保持的参数设置,默认对TCP空连接的保持时间为900秒:

如果在900秒(15分钟)内该连接上没有任何数据流量(空连接),则该连接将被关闭,通过LVS连接表可以查看到当前客户端连接情况:
二、问题重现
为了加快问题重现的速度,我们把TCP超时时间设置为10秒钟,客户端连接数据库后,可以在LVS连接表中看到相应的TCP连接:

10秒钟倒计时后,该连接将被关闭,客户端发起查询将有报错:


而如果在10秒钟内客户端有发起数据库请求,那么这个倒计时将被重置为初始值(这里是10s)
三、解决方案
通过上述分析,为了保持该TCP连接,可以很容易想到两个解决方案:
1)设置更长的timeout时间,比如24小时;
2)应用定期在timeout时间内发起数据库连接心跳,比如udal show version;
不过这两种解决方案各自存在明显的缺点:
第一个方法在异常情况下将会增加系统连接资源开销(比如各种原因导致的客户端异常关闭),极端情况下将导致正常连接无法建立,而且这个值的设置也很难找到一个统一标准。
第二个方法将额外增加网络及数据库压力,特别在数据库压力较大、连接数较多的情况下,同时也将增加开发的复杂度及出错概率。
其实,操作系统层面也有TCP保持的参数设置,主要包括如下三个,默认值如下:

这三个参数含义如下:
tcp_keepalive_time:如果一个TCP连接在7200秒(默认值)内没有数据传输,将发起连接状态检测。如果期间有数据传输,这个值将被重置为初始值,而不会进行状态检测。
tcp_keepalive_intvl:如果第一次检测连接不通,两次进行检测的时间间隔,默认是9秒。
tcp_keepalive_probes:因连接检测不通再重复进行探测的最大次数,默认是9次。
通过操作系统层面这三个参数的设置,与LVS中TCP连接超时时间的匹配,即tcp_keepalive_time的值要小于LVS中的TCP timeout时间设置,如果在一段时间内,TCP连接中没有数据流量,到达tcp_keepalive_time时间后,操作系统将发起TCP连接状态检测,这个状态检测过程将触发LVS中的TCP timeout时间重置,这样就可以既简单又高效地实现长连接的会话保持,同时对异常连接及时地进行资源回收,还省去了应用额外的开发成本。
本期的“含英咀华”就到这里了,欢迎各位在公众号中留言你们想要阅读的文章类型,统计完成后我们会在之后的“含英咀华”中发布于此相关的文章和案例,希望在之后的时光中继续为大家带来实用的文章和案例。
最后,感谢各位的阅览。




