一个TCP连接池的自我修养-如mysql-client、http-client、redis-client
2017-10-10 13:42
267 查看
问题:单服单天过亿请求中,出现0.0001%的500怎么回事?
日志中不定时出现mysql gone away,
connect timeout,
reset by beer等错,原因不明。
access-log同样不定时出现5xx错。
感觉MySQL运行正常,没压力,没慢查,sql使用主键查询–不知道问题在哪?
连接MySQL的代码使用keepalive。
这个时候,你是否怀疑过是连接库的问题?
一个TCP连接池的自我修养
keepalive特性,idle-connection可设定。one retry 特性。
max-connection 设定。
read/write timeout 设定。
max-connection 特性是必需的
如果是mysql连接库,max-connection不设上限,要不就是造成后端的mysql连接过多,拖跨mysql。如果是http连接库,就会造成服务应用大量并发请求在等待,不论阻塞、非阻塞同样会。即使像go语言,这样原生性非阻塞、轻并发语言。大量的等等请求,一样会有耗尽内存的风险。换是python、php一个线程就以M为单位内存计算的,并发更低。
所以必需带有合理的
setMaxConnection()接口。
非常重要的容错
当连接池满载时,一个新线程请求一个新连接时,采用什么策略? 等待? 还是直接返回try-later?
read/write timeout 也是必需的
任何的TCP连接,都可能出现的读/写超时,对上层来说就是出错了,如果timeout很长,即直接阻塞了此线程或微线程。大量阻塞同样地引发内存风险,也不存在语言上的差别。所以,合理的timeout值,特别是read timeout,经常地出现一种,对方服务器处理慢,不能及时返回结果,而client端断开后,对方继续完成了工作,而client方以为没完成,而重发请求,如果没防重入,会造成数据不一致。 为什么重发?参考one-retry特性说明。keepalive+ idle-connection 作为可选特性
追求高性能,TCP的keepalive,连接重用是必需的。
而idle-connection作为闲时保持最低的连接数量,当上层业务要使用时马上可用。
还有一种做法是 connection-keep-timeout, 即每个连接闲下来后,多长时间后自动关闭。
MySQL中就可以使用
set timeout=n;显式设置每个连接的timeout值,否则使用服务端默认统一值。
one retry 特性,在keepalive打开时,必需加上
one-retry特性,并不是每个程序员都注意并知道的一个常规特性。而此特性正是解决 我们项目中
0.0001% 5xx 问题的关键。
一旦开启idle-connection特性后, TCP客端端会保持一定数量在连接在连接池中,上层要使用时返回一个连接。
而像MySQL的通信协议中是有Ping指令的,就是用于测试连接是否有效。所以当返回一个连接时,如果是MySQL,就可以用Ping测试一下,确保返回给上层的是可用连接。
原因是连接池中的连接不一定有效,即使你代码中监听了socket的close事件,但由于服务端可能使用了LVS这样的虚拟IP,很可能出现服务端单方面断开了TCP连接,客户端是没法感知(注:这里并不是说使用LVS就会有这种现象,只能用于举例说明,服务端可能使用了客户端无法感知的连接层)。除此以后,TCP断开时4次握手不完全,也是很正常的现象。
为了上层能获得一个可用连接池,没有ping协议的HTTP协议怎么办?
可以使用one-retry特性:
上层发送一个请求调用,由
连接池执行, 如出现
reset by beer或
mysql was gone away情况的,可以
新建一次连接,重发一次请求。我把这种行为称为
one-retry, 上层不必感知。若重试的请求,也出来同样的错误,就应该向上层返回或异常了–视语言而定。
原文来自
相关文章推荐
- 一个TCP连接池的自我修养-如mysql-client、http-client、redis-client
- 一个成年人的自我修养(有感而发,内容较少)
- Http请求连接池 - HttpClient 的 PoolingHttpClientConnectionManager
- HttpClient连接池原理及一次连接时序图
- C: Linux Socket Programming, TCP, a simple HTTP client - 安東尼隨手記 - Yahoo!奇摩部落格
- 一个增长黑客的自我修养
- 一个男生的自我修养
- 一个前端程序猿的Sublime Text3的自我修养
- 第五章 常用Lua开发库1-redis、mysql、http客户端
- SpringMvc+MyBatis+MySQL+Maven+Redis搭建一个基础的web项目
- 自我总结httpclient
- PhpMyAdmin的简单安装和一个mysql到Redis迁移的简单例子
- 转一个很详细的httpclient入门
- 一个SEMer的自我修养
- 如何用java代码访问远程web服务器(手写一个自己的httpClient)
- 稳扎稳打Silverlight(53) - 4.0通信之对WCF NetTcpBinding的支持, 在Socket通信中通过HTTP检索策略文件, HTTP请求中的ClientHttp和BrowserHttp
- 稳扎稳打Silverlight(53) - 4.0通信之对WCF NetTcpBinding的支持, 在Socket通信中通过HTTP检索策略文件, HTTP请求中的ClientHttp和BrowserHttp
- 稳扎稳打Silverlight(53) - 4.0通信之对WCF NetTcpBinding的支持, 在Socket通信中通过HTTP检索策略文件, HTTP请求中的ClientHttp和BrowserHttp
- xPool - 基于mysqlclient的mysql的c++连接池 - xnhcx的个人空间 - 开源中国社区
- 一个职业黑的自我修养