感谢您的解答
选择这个方式的一个原因是不希望到redis的连接太多,担心影响了redis的性能。因为任务的种类非常多,每一类任务对应了redis中的一个队列。
对于同一类任务,timer只会被触发一次,然后在timer中启动一个或几个接收线程去接收任务,收到一个任务就会spawn一个work线程。
也就是说请求(任务)不是通过http方式到nginx的,而是在timer中的接收线程主动去redis中获取的,触发timer的请求相当于一个管理命令。
在我这种场景下,收任务一般会快于worker线程的处理。所以这么做的原因其实就是看中work线程可以非常多,而且是异步的。不会受限于其他语言中的进程数或者线程数。
当然work线程还是需要控制一下个数,让超出处理能力之外的任务堆积在redis中。
最终效果还要看一下获取任务的速度以及work的处理速度,还有发送响应的速度这几方面的匹配程度。
Thanks
On Wednesday, October 9, 2013 2:42:49 AM UTC+8, agentzh wrote:
Hello!
2013/10/8 shu chen:
> 我想在ngx.timer.at中使用ngx.thread.spawn产生一个"light
> thread"不停的从redis中获取消息,每获取一个消息就再产生一个"light thread"去处理消息,然后再把处理的结果push回redis中。
我建议你不要使用这种工作模型。因为你从 redis 拿任务的 light thread 的运行速度可能会超过或者低于你实际处理任务的
light thread,你几乎总是需要同步这两个轻线程之间的速度,否则很容易出现任务大量积压或者任务不足导致的处理消息的线程的饥饿;类似地,push
结果的 light thread 也存在速度不一致时的同步问题。
推荐的做法是创建有限个完全相同的 light thread 作为并行的 worker 线程,每个线程都顺序地(即同步地)从 redis
取任务,再处理消息,再推送结果。这样可以避免轻线程同步的麻烦,同时也可以提高轻线程的利用率(毕竟在线程 A 在等待线程 B 的时候线程 A
其实是在浪费资源)。
当然,你仍然需要考虑你的 timer 处理程序本身的轻线程和你的这些同质的 worker 轻线程之间的同步问题。如果你的 timer
触发的频率高于你实际干活的那些轻线程,则你的那些实际干活的轻线程也会出现大量积压的问题。
在优化 C10K 应用的时候,最重要的一条原则是减少系统资源的浪费,而不是一味地追求异步处理。其实异步处理经常会引入更多的开销和复杂度。
Best regards,
-agentzh