事件驱动编程是一种编程范式,这里程序的执行流由外部事件来决定。它的特点是包含一个事件循环,当外部事件发生时使用回调机制来触发相应的处理。多线程是另一种常用编程范式,并且更容易理解。
高性能通用型C++网络框架 Nebula 是基于事件驱动的多进程网络框架(适用于即时通讯、数据采集、实时计算、消息推送等应用场景),已有即时通讯、埋点数据采集及实时分析的生产应用案例。经常有人问Nebula的每个进程里是单线程还是多线程的?又问为什么不用多线程?不用多线程又怎么处理并发问题?
最近 Nebula 将会用于一个新的生产项目——推荐引擎,在此之前团队已有使用某知名度较高的RPC框架多线程版推荐引擎(业界许多推荐引擎都用了目前比较知名的开源RPC框架来开发)。本文不做Nebula与各知名RPC框架的比较,也无意说明哪个框架更适合做推荐引擎,只说明Nebula可以用于推荐引擎,且有信心效果会很好。最终结果如何,等推荐引擎研发出来,拭目以待。
为什么是事件驱动而不是多线程?事件驱动无须多线程。我们先来回顾一下服务器编程范式。
1. 服务器程序设计范式
《UNIX网络编程》卷一里介绍了9种服务器设计范式:
九种服务器设计范式并不是全都有实用价值,在《UNIX网络编程》卷一最后一节里给出了几种TCP服务器设计范式代码示例:
- TCP并发服务器程序,每个客户一个子进程
- TCP预先派生子进程服务器程序
- TCP预先派生子进程服务器程序,传递描述符
- TCP并发服务器程序,每个客户一个线程
- TCP预先创建线程服务器程序,每个线程各自accept
- TCP预先创建线程服务器程序,主线程统一accept
Nginx采用的是九种服务器设计范式里的第5种“预先派生子进程,使用互斥锁上锁方式保护accept”,Nebula采用的是九种服务器设计范式里的第6种“预先派生子进程,由父进程向子进程传递套接字文件描述符”。