Nginx代理主备Mysql的目的
在需要Mysql高可用的场景下,可以通过使用Nginx代理主备Mysql的方式,使业务组件优先访问主Mysql,在主Mysql宕机后,使用备Mysql。当主Mysql恢复后,业务组件转为访问主Mysql。
Nginx代理主备Mysql实践
实验拓扑图如下,通过java进程模拟mysql client。
准备工作:java程序(数据库连接池设置连接数为50),在mysql1、2进行sql建库建表;
1、mysql1 insert 数据value=1;
2、mysql2 insert 数据value=2;
3、nginx配置主备mysql1(主)mysql2(备);
4、java进程,get value 10000次并打印get结果。
4.1在get期间关闭主mysql1,(/etc/init.d/mysqld stop)
4.2等待10s,
4.3再启动主,( /etc/init.d/mysqld start)
4.4再reload(不修改配置文件),( ./nginx -s reload)
观察日志打印;
观察1:关闭主,日志是否异常,(预测日志由打印1变为打印2)
验证结果:预期正确
观察2:启动主,观察打印是1还是2,(预测打印2,因为2的连接还没断)、
验证结果:预期正确
观察3:reload,观察是否打印1,(预测打印1,reload会将之前的连接断开,之后新建的连接按配置文件连接到mysql主)
验证结果:预期错误,还是打印2
nginx的work没有立即退出,而是一直显示: nginx: worker process is shutting down(ps查看的结果)
分析:对于tcp连接,ngxin的旧work进程会等待没有数据传输之后才会断开连接,而实验中由于是每隔0.1s就会查询数据,导致nginx的旧work一直不能退出。
改进:配合worker_shutdown_timeout使用(配置文件增加worker_shutdown_timeout 60s;)
- 实验核心代码:
@RequestMapping(value = "/get-for-test-mysql", method = RequestMethod.POST)
public void get(@RequestBody LockInput lockInput) throws InterruptedException {
for(int i =0;i<10000;i++) {
List<TestMysqlEntity> entities = testMysqlDao.getTestMysql(null);
//0.1秒
if(entities == null){
log.info("get from mysql, value is null");
} else {
if(entities.isEmpty()){
log.info("get from mysql, list is empty");
} else {
log.info("get from mysql, value is {} ", entities.get(0).getId());
}
}
Thread.sleep(100);
}
}
实验截图
Nginx配置文件
#user nobody;
worker_processes 4;
worker_shutdown_timeout 60s;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
pid /usr/local/nginx/logs/nginx.pid;
events {
worker_connections 1024;
}
stream {
upstream mysql-test{
server 55.241.105.109:3306 weight=1 max_fails=3 fail_timeout=1s;
server 55.241.105.119:3306 weight=1 max_fails=3 fail_timeout=1s backup;
}
server {
listen 3307 so_keepalive=on;
proxy_connect_timeout 3s;
proxy_timeout 3s;
proxy_pass mysql-test;
}
}
小节
nginx可以优雅实现代理mysql主备;当mysql主挂掉后,nginx会将请求导向mysql备,并在mysql主恢复后,通过监控平台或脚本执行reload,nginx可以在指定时间后将连接切回到mysql主,并且在该时间内mysql主可以完成与备的数据同步,保证切回主后的数据一致性;备注:需要nginx配置文件增加worker_shutdown_timeout 60s;(此处为60s,可依据实际情况修改)