docker部署中遇到的mysql坑

前几天在用docker部署游戏服务器组,方便运维和开服合服操作,我自己制作的docker镜像包括 1) mysql镜像 2) redis镜像 3)认证服务器镜像 4) 网关服务器镜像 5) 游戏逻辑服务器镜像,镜像做完把它们部署到外网测试服务器(这里表达一下对docker开发人员的感谢, 真的是解放了我的双手,整个外网测试服务器组在几分钟内部署调试完毕,这在以前是不能想象的), 服务器部署完毕在使用过程中没有发现任何问题。过了几天因为有新的需求需要在本地调试服务器代码,以前我是直接在本机环境开n多进程调试的,其实写2个脚本脚本start server 和stop server也停放便的,由于前几天刚刚做完docker镜像,自己按耐不住对docker的冲动,啪啪啪,干脆直接在本地测试也用docker得了,好,说干就干,啪啪啪几个命令敲完,本地测试环境搭建完毕,开始进行开发了测试,现在问题来了,在开发调试阶段突然发现整个服务器组响应很慢很慢,这对于我这个性子比较急的coder来说当然是不能忍受的,开始啪啪啪查问题,首先要定位问题,刚开始我怀疑是服务部署的问题(经排查没有问题),然后又怀疑是网络环境的问题(经验证容器网络环境也没有任何问题)……..(中间省略n久的查错和排错过程), 最好通过开启游戏逻辑服务器的sql打印才发现是访问数据库慢,难道是数据库容器有问题,可是外网测试环境也是用的相同的容器呀!!!!!,真是日了狗了,后来在网上查到(一下引用自网络):

mysql优化之–skip-name-resolve

mysql优化之–skip-name-resolve

同一IDC ,IDC内部有DNS服务器,对各服务器的IP做了反向解析,
但未对内网IP做反向解析,所以使用skip-name-resolve以后用内网地址向mysqlslap请求响应快了一半

附录: 7.5.6. MySQL如何使用DNS

涉及参数 –skip-name-resolve ,–skip-host-cache ,–skip-networking

当新的客户连接mysqld时,mysqld创建一个新的线程来处理请求。该线程先检查是否主机名在主机名缓存中。如果不在,线程试图解析主机名:

·         如果操作系统支持线程安全gethostbyaddr_r ()和gethostbyname_r()调用,线程使用它们来执行主机名解析。

·         如果操作系统不支持线程安全调用,线程锁定一个互斥体并调用gethostbyaddr()和gethostbyname()。在这种情况下,在第1个线程解锁互斥体前,没有其它线程可以解析不在主机名缓存中的主机名。

你可以用–skip-name-resolve选项启动mysqld来禁用DNS主机名查找。然而,在这种情况下,你只可以使用MySQL中的授权表中的IP号。

如果你有一个很慢的DNS和许多主机,你可以通过用–skip-name-resolve禁用DNS查找或增加HOST_CACHE_SIZE定义(默认值:128)并重新编译mysqld来提高性能。

你可以用–skip-host-cache选项启动服务器来禁用主机名缓存。要想清除主机名缓存,执行FLUSH HOSTS语句或执行mysqladmin flush-hosts命令。

如果你想要完全禁止TCP/IP连接,用–skip-networking选项启动mysqld。

附录.抓包数据 待补全

连接mysql时,都会向DNS做反向地址查询
只有等超时失败后,mysql才会响应客户端
等待解析的mysql进程都是 login状态

访问mysql之所以会慢是因为mysql服务器反向地址查询,docker容器启动的时候如果本机没有配置nameserver 那么默认会用 8.8.8.8 和8.8.4.4这两个域名解析服务器相信大家一看就知道问题了吧。

接觉得办法是在运行docker的时候加–dns 127.0.1.1(这里代表自己指定的dns server)。

sudo docker run -p 3308:3306 –dns 10.202.72.118 –dns 10.202.72.116 -d centos_mysql:1.0.0 sh /root/run.sh

发表评论

电子邮件地址不会被公开。 必填项已用*标注