使用sysbench 工具测试mysql实例故障后是否能恢复业务请求,预期是实例恢复后有业务请求到实例上面。测试实际结果是实例恢复后没有业务请求发生,与预期不符合。
测试过程
测试步骤简单描述如下:
1)拉起集群(实例2个以上), 为每个POD 创建一个Service,暴露serviceip.
2)启动sysbench ,使用多个serviceip 来测试多个实例
3)杀点某实例 进程 (或者delete pod)
4)观察实例是否恢复,恢复后进入实例,show processlist ,查看是否有业务请求
问题分析
查看sysbench 源码发现 重连频次过快,1毫秒一次,目测只需要几秒就耗光了端口。
修改了源码,把 usleep(1000) 改为 usleep(1000000) 后 来减低频率避免端口消耗过快,并尝试关闭mysql连接。
再次测试,连接数明显少了很多,但还是 ClOSE_WAIT 状态;
在processlist 看到有了新的连接过来的,但状态都是Receiving from client .
sysbench Debug日志没有打印 Reconnected 日志,说明重连循环一直没有退出,还在一直做连接重试。
仔细看mysql_drv_real_connect, 发现一直在复用con (MYSQL 对象) ,没有对con执行重置。
解决方案
改造sysbench 重连逻辑源码:每次重连失败都 关闭和重置MYSQL 对象,并减低重连频率。
static int mysql_drv_reconnect(db_conn_t *sb_con)
{
db_mysql_conn_t *db_mysql_con = (db_mysql_conn_t *) sb_con->ptr;
MYSQL *con = db_mysql_con->mysql;
。。。。。
while (mysql_drv_real_connect(db_mysql_con))
{
if (sb_globals.error)
return DB_ERROR_FATAL;
// close con and reinit it
mysql_close(db_mysql_con->mysql);
log_text(LOG_DEBUG, "Reconnect failed .try again ");
DEBUG("mysql_init(%p)", con);
mysql_init(con);
// sleep 1 second
usleep(1000000);
}
log_text(LOG_DEBUG, "Reconnected");
return DB_ERROR_IGNORABLE;
}
问题总结
sysbench 使用mysql客户端对象MYSQL不合理,重连前没有重置, 重连会失败,而且连接没有正常关闭,同时重连频率过高,会加剧端口消耗。最终体现就是客户端不能重新上实例来发起的业务 。