在AWS上使用CherryPy扩展Python网络服务器的并发请求
出于好奇,我写了一个简单的CherryPy服务器,代码如下,它会暂停5秒(模拟处理延迟),然后返回一个简单的“你好”。
import cherrypy
import time
class server_runner(object):
@cherrypy.expose
def api(self, url):
time.sleep(5)
return "hello"
if __name__ == '__main__':
cherrypy.server.socket_host = '0.0.0.0'
cherrypy.quickstart(server_runner())
我进行了一个简单的负载测试(结果在这里 https://i.stack.imgur.com/Aqw1F.png),应用的响应时间(蓝线)在27个活跃用户之前保持稳定(绿色线表示活跃用户数量),但在27个用户时,响应时间迅速上升。我有点困惑,为什么CherryPy会被称为“生产就绪”的服务器,如果27个用户都无法处理而没有明显的延迟。我的实现或理解上有什么问题吗?这个是在一个C3大型的Ec2实例上运行的。
1 个回答
在简单的情况下,你只需要管理一下 server.thread_pool
这个配置参数,就像问题评论中提到的那样。
但在实际情况中,这要考虑很多因素。不过我可以肯定的是,CherryPy是一个多线程的服务器,但由于Python的 全局解释器锁(GIL),一次只能运行一个线程。对于以输入输出为主的工作负载,这可能不是大问题,不过你还是可以利用你的CPU核心,运行多个相同应用的CherryPy进程。这可能会影响一些设计决策,比如避免在进程内缓存,以及一般遵循“无共享”架构,这样你的进程就可以互换使用。
有很多应用实例会让维护变得更复杂,所以你需要考虑一下利弊。好了,下面是一个例子,可以给你一些启发。
mp.py -- CherryPy应用
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import cherrypy
class App:
@cherrypy.expose
def index(self):
'''Make some traffic'''
return ('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean quis laoreet urna. '
'Integer vitae volutpat neque, et tempor quam. Sed eu massa non libero pretium tempus. '
'Quisque volutpat aliquam lacinia. Class aptent taciti sociosqu ad litora torquent per '
'conubia nostra, per inceptos himenaeos. Quisque scelerisque pellentesque purus id '
'vulputate. Suspendisse potenti. Vestibulum rutrum vehicula magna et varius. Sed in leo'
' sit amet massa fringilla aliquet in vitae enim. Donec justo dolor, vestibulum vitae '
'rhoncus vel, dictum eu neque. Fusce ac ultrices nibh. Mauris accumsan augue vitae justo '
'tempor, non ullamcorper tortor semper. ')
cherrypy.tree.mount(App(), '/')
srv8080.ini -- 第一个实例的配置
[global]
server.socket_host = '127.0.0.1'
server.socket_port = 8080
server.thread_pool = 32
srv8081.ini -- 第二个实例的配置
[global]
server.socket_host = '127.0.0.1'
server.socket_port = 8081
server.thread_pool = 32
proxy.conf -- nginx的配置
upstream app {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
把 mp.py
和 *.ini
文件放在一个目录下。将 *.conf
文件添加到nginx的 sites-enabled
中,然后重新加载它。在两个终端中打开包含 mp.py
的目录。然后在第一个终端运行 cherryd -e production -i mp -c ./srv8080.ini
,在第二个终端运行 cherryd -e production -i mp -c ./srv8081.ini
。
现在你可以开始玩了。我在我的开发机器上(Linux Mint 15,Core i5双核 + 超线程)运行了以下命令。
ab -c 1 -n 12800 -k http://127.0.0.1:8080/ # ~1600 rps
ab -c 16 -n 12800 http://127.0.0.1:8080/ # ~400 rps
ab -c 32 -n 12800 http://127.0.0.1/ # ~1500 rps