一般應用(比如mariadb)都會有乙個退出命令,使用者使用類似systemctl stop ****.service方法,停止其服務時,systemd會呼叫其配置檔案註冊的退出命令,該命令執行清理資源、退出集群、輸出必要日誌等操作後才殺死自己的程序;在系統shutdown的時候也會有類似的流程,最大程度的保證應用正常退出,下面我們稱之為「程序優雅退出」。
將應用docker化後,乙個突出的問題是,如何讓程序優雅的退出,而不是強行殺死程序。docker stop和docker kill分別實現了優雅退出和強行退出兩個操作:
docker stop:向容器內1號程序,傳送sigterm訊號,在10s之後(可通過引數指定)再傳送sigkill訊號。
docker kill:直接傳送sigkill訊號。
顯然docker已經考慮到應用優雅退出的問題,但在實際使用中,會遇到下面2個困難:
1. 只有1號程序才收到sigterm訊號,但docker中有很多1號程序為monitor或者為初始化指令碼的程序,並不是工作程序,且1號程序不能處理sigterm訊號,以mariadb為例,容器內的程序關係如下:
1 /bin/sh /usr/bin/mysqld_safe --wsrep-cluster-address=gcomm://其中2號程序為1號程序的子程序,雖然2號程序可以處理sigterm訊號但其收不到該訊號,而1號程序雖然能收到sigterm但並不能處理此訊號。2 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql/ ...
2. 即使1號程序能處理sigterm訊號,但若其有子程序為外部命令(非build in命令),且子程序為前台阻塞狀態,那麼1號程序在直到子程序退出前仍然不能收到sigterm訊號。如下bash是不會處理sigterm訊號的:
#!/bin/bash關於這一點需要了解程序處理訊號的限制:只有當程序阻塞在內建命令時才可以響應sig訊號,否則會一直等待子程序退出後再處理,如上面的bash,要等到10000秒之後才能處理sigterm。關於內建命令和外部命令,描述如下:trap 'exit 0' sigterm
sleep 10000
內部命令實際上是shell程式的一部分,shell不需要建立子程序,比如:exit,history,cd,echo,wait,trap等,linux系統載入執行時shell就被載入並駐留在系統記憶體中,一般不會fork子程序。綜上所述,對於多程序docker,我建議在容器中使用自定義bash指令碼作為容器入口,指令碼中使用後台方式執行具體應用的命令,然後使用內建wait阻塞,並通過trap指令監聽sigterm,執行應用退出操作,下面以容器化mariadb為例,描述其指令碼的大概實現:外部命令是linux系統中的實用程式部分,需要時才將其呼叫記憶體。一般會fork出子程序。
用type命令可以分辨內部命令與外部命令。
#!/bin/bash以上述指令碼為入口的maraidb容器內程序關係如下:trap 'mysqladmin -uroot -p123456 shutdown' sigterm
mysqld_safe --wsrep-cluster-address=gcomm: &
wait $!
mysql 1 0.0 0.0 11628 1352 ? ss+ 07:59 0:00 /bin/bash /usr/bin/test.sh當執行docker stop ***的時候,該容器會自動呼叫mysqladmin shutdown優雅退出。mysql 9 0.0 0.0 11764 1636 ? s+ 07:59 0:00 /bin/sh /usr/bin/mysqld_safe --wsrep-cluster-address=gcomm:
mysql 188 1.0 3.7 1087368 300168 ? sl+ 07:59 0:16 \_ /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/p
c語言使用預編譯指令的正確姿勢!
為什麼防止標頭檔案重複引用?標頭檔案重複引用會報錯嗎?其實標頭檔案的重複引用大多數情況下不會出現錯誤。那什麼情況會出錯呢?小二,直接上 好嘞,客官您慢用!5個檔案分別是a.h,a.c,b.h,b.c和hello.c。在hello中為了使用a.c和b.c分別加入a.h和b.h的標頭檔案。如下 int ...
ffmpeg使用指令實現推流實現直播流程
windows下用ffmpeg nginx rtmp搭建直播環境 實現推流 拉流 啟動nginx 進入nginx的目錄,執行其中rtmp檔案。執行下列 cd g studyprojects setupvideoservice nginx 1.7.11 3 gryphon nginx.exe c co...
正確地使用Redis的SETNX實現鎖機制
setnx,是set if not exists 的縮寫,也就是只有不存在的時候才設定,設定成功時返回 1 設定失敗時返回 0 可以利用它來實現鎖的效果,但是很多人在使用的過程中都有一些問題沒有考慮到。例如某個查詢資料庫的介面因為請求量比較大所以加了快取,並設定快取過期後重新整理。當併發量比較大並且...