上一回咱们主要讲解了 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
固然它也带来了一些问题:
参考连接