我正在使用 CherryPy 来通过 WSGI 为 python 应用程序提供服务。
我尝试对其进行基准测试,但 CherryPy 似乎只能处理 10 个请求/秒。不管我做什么。
构建了一个暂停 3 秒的简单应用程序,以便准确确定发生了什么……我可以确认 10 req/sec 与 python 脚本使用的资源无关。
__
有任何想法吗?
我正在使用 CherryPy 来通过 WSGI 为 python 应用程序提供服务。
我尝试对其进行基准测试,但 CherryPy 似乎只能处理 10 个请求/秒。不管我做什么。
构建了一个暂停 3 秒的简单应用程序,以便准确确定发生了什么……我可以确认 10 req/sec 与 python 脚本使用的资源无关。
__
有任何想法吗?
默认情况下,CherryPy 的内置 HTTP 服务器将使用 10 个线程的线程池。如果您仍在使用默认值,您可以尝试在配置文件中增加它。
[global]
server.thread_pool = 30
This was extremely confounding for me too. The documentation says that CherryPy will automatically scale its thread pool based on observed load. But my experience is that it will not. If you have tasks which might take a while and may also use hardly any CPU in the mean time, then you will need to estimate a thread_pool
size based on your expected load and target response time.
For instance, if the average request will take 1.5 seconds to process and you want to handle 50 requests per second, then you will need 75 threads in your thread_pool to handle your expectations.
In my case, I delegated the heavy lifting out to other processes via the multiprocessing
module. This leaves the main CherryPy process and threads at idle. However, the CherryPy threads will still be blocked awaiting output from the delegated multiprocessing
processes. For this reason, the server needs enough threads in the thread_pool
to have available threads for new requests.
My initial thinking is that the thread_pool
would not need to be larger than the multiprocessing
pool worker size. But this turns out also to be a misled assumption. Somehow, the CherryPy threads will remain blocked even where there is available capacity in the multiprocessing
pool.
Another misled assumption is that the blocking and poor performance have something to do with the Python GIL. It does not. In my case I was already farming out the work via multiprocessing
and still needed a thread_pool
sized on the average time and desired requests per second target. Raising the thread_pool size addressed the issue. Although it looks like and incorrect fix.
Simple fix for me:
cherrypy.config.update({
'server.thread_pool': 100
})
Your client needs to actually READ the server's response. Otherwise the socket/thread will stay open/running until timeout and garbage collected.
use a client that behaves correctly and you'll see that your server will behave too.