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