Docker容器中MySQL最大連接數被限制為214的解決方案
一、背景
話說筆者在上次的博客裏簡單的講了一下調整MySQL最大連接數的方法。在文章的最後筆者提到了還有一些特殊情況比如說Docker中,會導致MySQL的最大連接數被限制在一個值上。今天筆者就要來講一下為什麽在Docker環境中會出現這個問題。
這次的問題也是在公司實習的時候碰到的。當時導師要筆者去部署一個LAMP環境(不要問筆者為什麽用docker還要把apache+PHP和MySQL塞在一起,這個問題您得問筆者導師),然後要調整一下Apache和MySQL的最大連接數。在調整結束之後筆者就想著要不進去看看有沒有設置成功,就進入Docker容器的MySQL控制臺,查看MySQL的最大連接數,結果是筆者之前設置的最大連接數並沒有生效,MySQL的最大連接數被限制在了214。
?
二、解決方案
今天就先講一下解決方案吧,因為當時遇到這個問題的時候真的是沒有一點思路。去百度搜索了很久都沒有找到什麽靠譜的結果。最後抱著賭一賭的決心去Google上用英文搜了一下,結果在第一頁就搜到了有人在stackoverflow提出的類似問題《Increasing mysql max_connections to 1024 in a docker container》,裏面提出了一個解決方案:
在啟動容器時加入參數:
--ulimit nofile=65536:65536
好的,那讓我們試驗一下行不行,在啟動容器的時候加入--ulimit參數:
?
用docker exec命令進入容器,檢查MySQL的max_connections變量值:
?
成功了!
?
三、思考
問題是解決了,但到底是為什麽呢?
我們來看一下Docker官方對ulimit這個參數是怎麽解釋吧。
ulimit這個參數最初出現於Docker 1.6版本,在官方博客《Docker 1.6: Engine & Orchestration Updates, Registry 2.0, & Windows Client Preview》裏,他們對ulimit參數的是這麽解釋的:
Ulimits
Up until now, containers inherit the ulimit settings from the docker daemon. This tends to be extremely high to account for production workloads, but is not ideal inside the container.? Ulimits allow you to limit the resources of a given process (you may be familiar with the command line tool ulimit). With this new feature, you can now specify the default ulimit settings for all containers, when configuring the daemon. For example:
?
docker -d --default-ulimit nproc=1024:2048
?
This will set a soft limit of 1,024 and a hard limit of 2,048 child processes for all containers. You can set this option multiple times for different ulimit values:?--default-ulimit nproc=1024:2408 --default-ulimit nofile=100:200
?
These settings can be overwritten when creating a container as such:
?
docker run -d --ulimit nproc=2048:4096 httpd
?
This will overwrite the default nproc value passed into the daemon.
Thanks to?Brian Goff?for this patch. If you are interested in the original pull request you can view it?here.
?
個人渣翻:
Ulimits
直至當前,容器通過從docker守護進程繼承ulimit設置,這對於生產工作量來說往往是非常高的,但在容器的內部卻並不理想。Ulimits將允許您去限制給予進程的資源(您可能熟悉命令行工具ulimit)。通過這個新功能,您現在可以在設置守護程序時向所有的容器指定默認的ulimit設置。例如:
?
docker -d --default-ulimit nproc = 1024:2048
?
這將為所有容器設置1024個軟限制和2048個硬限制的子進程限制。您可以對不同的ulimit值多次設置此選項:--default-ulimit nproc=1024:2408 --default-ulimit nofile=100:200
?
這些設置可以在創建容器本身時被重寫:
?
docker run -d --ulimit nproc=2048:4096 httpd
?
這將重寫之前傳入守護程序中的默認nproc值。
?
感謝Brian Goff提供的補丁。如果您對原始的pull request感興趣,您可以去這裏查看。
?
簡單的說呢就是,在Docker容器將繼承Docker守護進程的ulimit設置,我們通過在啟動容器的時候加上--ulimit nofile=65536:65536參數,重寫了容器內部的nofile限制值。
?
四、其他修改默認設置方法
由於筆者要部署的容器都需要提高MySQL的最大連接數,每次啟動的時候都要設置ulimit參數會變的非常繁瑣。如果使用文檔中提到的docker -d --ulimit這種方式如果以後突然要返回默認值就比較麻煩了。有沒有什麽一勞永逸且設置方便取消也方便的方法呢?答案當然是有的——修改docker守護進程ulimit設置。
?
由於這裏用的系統是CentOS 6.9,所以不存在docker.service文件。但我們可以通過修改服務啟動腳本來實現:
vim /etc/init.d/docker
在文件的開始部分加入以下代碼:
ulimit -u 65536 -HSn 65536
?
保存後退出vim。
現在我們回到容器中,這次我們不添加--ulimit參數,看看能不能解除MySQL最大連接數214的限制。
?
和剛剛一樣,用docker exec進入lamp容器內部,檢查MySQL當前max_connections變量值:
?
可以看到,現在就算沒有加入--ulimit參數,MySQL最大連接數也可以突破214的限制了。
?
五、寫在最後
為什麽在第四章筆者給出了一種修改服務配置文件的方式而不是通過官方提供的docker -d --ulimit方法去調整docker守護進程的ulimit值呢?主要的原因大概就是docker官方在後面的更新中,也是使用修改服務配置文件的方式設置了默認的ulimit設置。
在寫本文時,筆者因為需要截圖,所以打算在自己的筆記本中搭建環境,但一開始用的是CentOS 7系統,在實際的操作過程中就算沒有加--ulimit參數,容器內的MySQL也可以突破最大連接數為214的限制,Ubuntu 16.04也是如此。只有CentOS 6才出現了這個問題。通過查看CentOS 7和Ubuntu 16.04的docker.service文件後,筆者發現在docker.service中,已經默認加入了LimitNOFILE和LimitNPROC這兩項設置並默認給予了一個非常大的數值,所以這個問題就不會出現在CentOS 7和Ubuntu 16.04上了。
CentOS 7 docker.service文件部分截圖:
?
Ubuntu16.04 docker.service文件部分截圖:
?
所以筆者個人覺得通過修改docker守護進程的配置文件來設置ulimit值的方法更為妥善。
Docker容器中MySQL最大連接數被限制為214的解決方案