缘起:
毕业设计是做一个分布的元数据存储系统,并希望使用openresty与lua来完成 :)
权衡:
nginx的I/O阻塞是个比较麻烦的问题,如果涉及到大数据块的写入,经典的解法是使用cosocket将I/O任务分给另外独立的存储进程,自己则异步"等待",以此来优化全局request响应时间。
但是这种方法会带来以下的一些缺点:
1.部署、运维麻烦(要维护两组服务);
2.nginx要与后端的存储进程完成准确的状态同步:
0.nginx需要对进行存储初始化,确定何时;
1.存储崩溃时,nginx需要从其他节点成员处对其进行数据恢复;
2.严格的fsync语义,以防数据丢失。
所以,为了避开以上的若干问题,理想的方法是将繁重的I/O任务放到nginx里面去。
但是好像没见过有人这么玩,但是,WHY NOT?
解法:
归根结底,需要对nginx完成P0约束,才能这么玩:
P0:
让指定的某一些nginx workers永远不accept连接
P0的间接实现:(借助现有机制)
P0.1:
在每个worker的init_worker阶段,它们一起去抢若干把全局锁,只要成功地抢到一把,这个worker就是I/O worker(它接着就一直死循环(等待脏活任务、干脏活))。
如果连一把锁都没有抢到,那它就是正常的worker,accept新连接,处理之,如果有脏活了,就发给I/O worker,异步等待轮询结果,然后拿到结果,继续处理。
P0.11:
对于P0.1中所用的这若干把全局锁,如果锁的占有进程被杀了,内核必须能够为其立即进行锁回收(不能阻碍新I/O worker的重生)。
任务的发送与反馈:
normal worker
POST
{
src:dict.xx.content
desc:store
ret:dict.yy.unique_name
}
to msg-queue
then
I/O worker:
GET
store the content in src:dict.xx.content
set ret:dict.yy.unique_name
草图:
Classical Situation:
![]()
Solution when using I/O workers:
![]()
IPC when using I/O workers:
![]()
请大家看看这种玩法的弊端是什么呢?