Hello!
2015-08-27 11:25 GMT+08:00 Jinhua Luo:
> 这里我再澄清一下,我知道繁忙的worker能接受的连接数同比会降低,在连接层面,我觉得是worker间是能均衡的。但是我这里指的是长连接进入某个worker后,连接内的请求被处理的不均匀,而请求无法在worker之间迁移。
连接在不同 worker 进程之间的动态迁移无疑极大地增加了实现的复杂度,且即使实现,开销也不会小,导致没有多少实际价值。如果你偶尔有一些计算密度非常高的任务,或许将这些任务委托给
nginx 新引入的线程池来执行更合适一些。比如 ngx_lua 模块未来会暴露线程池的 Lua API.
> 反观golang的goroutine设计,每个goroutine可以用来表示一个请求的处理,而goroutine可以在多个线程(对应多个CPU核)之间迁移,使得每个CPU核都能够被充分利用,这样的模型会不会比nginx要好呢?
>
最一般的多线程模型确实在理论上更为灵活,但其工程代价也是高昂的。确保线程安全通常会耗费大量的开发者时间,也极易引入 bug. 我很高兴我在
nginx 的上下文中几乎不用考虑线程同步和线程安全的问题。
是采用多进程模型还是一般的多线程模型本身就是一种工程上的折衷。较新的 nginx 发布引入内部线程池也是一种折衷。
> 我还有一点困惑,nginx使用的是进程模型,每个进程的地址空间是独立的,那么进程间需要共享数据的时候就要用到共享内存。但进程间对共享内存的操作绝大多数都不是原子操作,例如nginx的slab,分配一块内存的操作分为很多个步骤,要对共享内存中不同的位置进行写。假设进程在执行操作期间崩溃了,
在 nginx worker 进程持有共享内存的锁的期间发生内存错误的可能性是极小的,同时这里的锁同步方式也足够简单。因为这样的代码本身就很少。而一般的多线程模型,则任意一处内存问题都会导致整个服务进程崩溃。
当然了,作为服务进程,本身就不应有任何内存问题。一旦发现,就应第一时间修复 :)
> 那么崩溃后,这个锁没法被重置,导致其他等待该锁的进程被锁死。
事实上,nginx 的 master 进程对此有保护,会在持有锁的 worker 进程导常退出后清理它持有的
mutex,所以并不会导致锁死。见 nginx 核心中的 ngx_process_get_status() 函数。
Regards,
-agentzh