上一回咱們主要講解了 GitLab-workhorse 組件的智能代理功能,從這一回起將開始介紹最核心也最複雜的組件:Unicorn(GitLab Rails),上次也說了這個組件主要處理動態網頁和 api 接口html
此篇文章先介紹 Unicorn 的做用,光是這個就能講不少內容了java
Unicorn 是使用多進程模型的 Ruby web 服務器,遵循 Rack 協議。若是要類比 java web 開發技術棧的話,Rails 應用至關於 Spring MVC 框架應用,Unicorn web 服務器至關於 tomcatnginx
GitLab 的 Rails 應用程序(即 gitlab-ce)是在 Unicorn 服務器內運行的,使用 Unicorn 的緣由是: Unicorn 能爲 Rails 應用提供併發處理客戶端請求的能力,而且提供了更強的容錯處理git
Unicorn 的多進程模型能很好地利用服務器多核 CPU 的資源,以提供更好的併發能力。當 Unicorn 啓動時,Unicorn 的主進程,即 master 進程,會以 fork 的方式建立一系列 worker 進程。Unicorn 經過一個 master 進程來管理多個 worker 進程,其中 master 進程不負責處理客戶端的 HTTP 請求,多個 worker 進程監聽同一組套接字以處理客戶端請求github
實際上,worker 進程可能會掛掉或者超時(超時是指,若是 master 進程發現某個 worker 進程耗費太長時間在處理一個請求,master 進程將以發送信號(SIGKILL, kill -9)終止 worker 進程)web
# unicorn_stderr.log 日誌,如下表示id 爲 10 的 worker 的進程超時,master 進程殺掉後又重啓了新進程,重啓先後 pid 是不一致的
[2015-06-05T10:58:08.660325 #56227] ERROR -- : worker=10 PID:53009 timeout (61s > 60s), killing
[2015-06-05T10:58:08.699360 #56227] ERROR -- : reaped #<Process::Status: pid 53009 SIGKILL (signal 9)> worker=10
[2015-06-05T10:58:08.708141 #62538] INFO -- : worker=10 spawned pid=62538
[2015-06-05T10:58:08.708824 #62538] INFO -- : worker=10 ready
複製代碼
無論 worker 進程會以哪一種方式終止,master 進程總會建立全新的 worker 進程替代原 worker 進程,整個過程不會丟棄用戶的請求編程
gitlab-ce 自己是內存泄漏的應用。因爲 Unicorn 在運行過程會 fork 大量的 worker 進程,內存泄漏會顯如今長時間運行的進程中,如 worker 進程(master 進程由於不頻繁處理用戶請求而幾乎沒有內存泄漏的現象)。而 Unicorn 自己並無提供自動重啓 worker 進程的功能,爲解決這個問題就出現了 unicorn-worker-killer ,具體查看 github.com/kzk/unicorn…api
GitLab 使用了 unicorn-worker-killer 以讓這些進程的內存泄漏得以管控:Unicorn worker 進程在每處理 16 個請求後將進行內存自檢,若是 worker 進程佔用的內存大小超過了預設定的值,Unicorn master 進程將會自動將此 worker 進程替換掉,整個過程不會影響任何請求的處理tomcat
# unicorn_stderr.log 日誌,如下表示 worker 進程的當前佔有內存超過約 250M,因而對此 worker 進程執行重啓替換的操做
[2015-06-05T12:07:41.828374 #125918] WARN -- : #<Unicorn::HttpServer:0x00000002734770>: worker (pid: 125918) exceeds memory limit (256413696 bytes > 254802235 bytes)
[2015-06-05T12:07:41.828472 #125918] WARN -- : Unicorn::WorkerKiller send SIGQUIT (pid: 125918) alive: 23 sec (trial 1)
[2015-06-05T12:07:42.025916 #117565] INFO -- : reaped #<Process::Status: pid 125918 exit 0> worker=4
[2015-06-05T12:07:42.034527 #127549] INFO -- : worker=4 spawned pid=127549
[2015-06-05T12:07:42.035217 #127549] INFO -- : worker=4 ready
複製代碼
綜上所述,GitLab 使用 Unicorn 的目的:bash
固然它也帶來了一些問題:
參考連接