非阻塞 HTTP 服务器,Java NIO,Python Tornado Eventlet
你好,
我想弄明白基于tornado/eventlet的HTTP服务器是否比线程型服务器更好。在网上查资料时,我发现这些服务器是单线程的事件驱动服务器,它们在套接字上使用select/poll/epoll来运行一个处理函数。
- 我第一个问题是,tornado/eventlet是不是和Java里的nio库类似?Java的nio服务器是非阻塞的,速度快吗?
- 我第二个问题是,既然这个基于事件的服务器是单线程的,如果有一个连接在文件输入输出上阻塞或者客户端很慢,会不会导致整个服务器都挂掉?
- 我第三个问题是,既然非阻塞服务器速度快,为什么它没有比Apache更常见呢?
这些问题是相关的,我希望能得到一些帮助,因为我对这些问题的理解还不太清楚。
谢谢!
1 个回答
4
非阻塞服务器是一个不错的选择,前提是你使用的所有库都支持非阻塞的接口。正如你第二个问题提到的,如果某个库是阻塞的(比如数据库库进行阻塞调用),那么整个进程或线程都会被阻塞,系统就会卡住。并不是所有的库都是异步的,这让我们在使用tornado或eventlet时会遇到一些麻烦。此外,在多核的机器上,需要启动多个非阻塞服务器实例,才能充分利用机器的性能。
Tornado和Eventlet服务器的工作方式类似于基于Java NIO的服务器。它们之间有一个概念上的区别:Tornado采用的是反应器模式,单个进程会等待IO(比如socket)事件,并将这些事件分发给合适的处理程序。如果这些处理程序是非阻塞的,性能会更好。通常,为这些框架编写的代码会包含一系列的回调,这让代码的可读性比同步服务器稍差。Java NIO服务器也属于这一类。
Eventlet完成相同的任务,但界面更简洁。你可以像写同步服务器那样编写代码,而不需要使用回调。当遇到IO操作时,eventlet会调度另一个用户空间的进程(虽然这个说法不太准确)。
Apache的网络应用程序比这些更受欢迎,原因有几个:
- 编写同步代码相对简单
- 并不是所有需要的库都是异步的。
但是,如果你想写一个处理大量连接的聊天应用程序,使用多线程服务器是无法扩展的。你必须使用像twisted、event或Java NIO这样的异步框架。