如果您在Tornado之上运行WSGI应用程序,那么Tornado和gunicorn之间没有太大区别,只要应用程序在特定进程中处理WSGI请求,就不会发生任何其他事情。对于 Gunicorn 来说,因为它只有一个线程处理请求,而对于 Tornado 来说,因为主事件循环在这段时间内永远不会运行来处理任何并发请求。
就龙卷风而言,其实也存在一个隐患。
对于gunicorn来说,由于只有一个请求线程,所以工作进程一次只会接受一个Web请求。如果有并发请求到达服务器,它们将由任何其他可用的工作进程处理,因为它们都共享相同的侦听器套接字。
不过,对于 Tornado,WSGI 应用程序下层的异步性质意味着一个进程可以同时接受多个请求。它们最初会在读取请求标头和内容时交错,Tornado 在调用 WSGI 应用程序之前将其预先读入内存。当整个请求内容被读取后,控制权将移交给 WSGI 应用程序来处理该请求。同时,在 WSGI 应用程序处理第一个请求期间,由同一进程处理且尚未读取请求标头和内容的并发请求将被阻塞。
现在,如果您只有一个 Tornado 进程,这并不是什么大问题,因为无论如何,请求都会被序列化,但如果您使用 Gunicorn 的 Tornado 工作模式,以便使多个 Tornado 工作进程共享相同的侦听器套接字,这可以是很糟糕。这是因为异步层产生的各个进程的贪婪本质意味着,当可能有另一个工作进程可以处理请求时,请求可能会在进程中被阻塞。
总之,对于单个 Tornado Web 服务器进程,您一次只能处理一个请求。在gunicorn中,您可以拥有多个工作进程以允许同时处理请求。不过,使用 Tornado 的多进程设置可能会导致请求被阻止。
因此,Tornado 对于非常小的自定义 WSGI 应用程序来说非常有用,在这些应用程序中,它们不执行太多操作,因此响应速度非常快,但如果您在阻塞 WSGI 应用程序下运行长时间运行的请求,则它可能会受到影响。因此,Gunicorn 会更好,因为它具有处理并发请求的适当能力。由于 Gunicorn 是单线程的,并且需要多个工作进程,因此它将使用更多的内存。
因此,它们都有权衡,在某些情况下,您最好使用通过多线程和多个工作进程提供并发性的 WSGI 服务器。这允许您处理并发请求,但不会因为需要许多工作进程而导致内存使用量激增。同时,您需要平衡每个进程的线程数和使用多个进程,以免在 CPU 密集型应用程序中过度受到 GIL 的影响。
具有多线程能力的 WSGI 服务器可以选择 mod_wsgi、uWSGI 和 waitress。对于女服务员,尽管您仅限于单个工作进程。
总而言之,哪个是最好的 WSGI 服务器实际上很大程度上取决于您的 Web 应用程序的具体情况。没有任何一个 WSGI 服务器在所有方面都是最好的。