在AWS上使用CherryPy扩展Python网络服务器的并发请求

4 投票
1 回答
1606 浏览
提问于 2025-04-18 12:52

出于好奇,我写了一个简单的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 个回答

3

在简单的情况下,你只需要管理一下 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  

撰写回答