Openresty的诞生,一直对外宣传是非阻塞(100% noblock)的。基于事件通知的Nginx给我们带来了足够强悍的高并发支持,但是也对我们的编码有特殊要求。这个特殊要求就是我们的代码,也必须是非阻塞的。如果你的服务端编程生涯一开始就是从异步框架开始的,恭喜你了。但如果你的编程生涯是从同步框架过来的,而且又是刚刚开始深入了解异步框架,那你就要小心了。
Nginx为了减少系统上下文切换,它的worker是用单进程单线程设计的,事实证明这种做法运行效率很高。Nginx要么是在等待网络讯号,要么就是在处理业务(请求数据解析、过滤、内容应答等),没有任何额外资源消耗。
异步编程,如果从零开始,难度是非常大的。一个完整的请求,由于网络传输的非连续性,这个请求要被多次挂起、恢复、运行,一旦网络有新数据到达,都需要立刻唤醒恢复原始请求处于运行状态。开发人员不仅仅要考虑异步api接口本身的使用规范,还要考虑业务会话的完整处理,稍有不慎,全盘皆输。
最最重要的噩梦是,我们好不容易搞定异步框架和业务会话完整性,但是却在我们的业务会话上使用了阻塞函数。一开始没有任何感知,只有做压力测试的时候才发现我们的并发量上不去,各种卡曼顿,甚至开始怀疑人生:异步世界也就这样。
官方有明确说明,Openresty的官方API绝对100% noblock,所以我们只能在她的外面寻找了。我这里大致归纳总结了一下,包含下面几种情况:
这些都应该是我们尽量要避免的。理想丰满,现实骨感,谁能保证我们的应用中不使用这些类型的API?没人保证,我们能做的就是把他们的调用数量、频率降低再降低,如果还是不能满足我们需要,那么就考虑把他们封装成独立服务,对外提供TCP/HTTP级别的接口调用,这样我们的Openresty就可以同时享受异步编程的好处又能达到我们的目的。