2

我们在 Linux 3.8 上使用 Apache 2.2 和 mod_wsgi 配置来测试它在大量并发流量下的行为。我们使用 ApacheBench (v2.3) 从同一台机器创建流量。

我们的设置在 1000 个线程(10 个进程和 100 个线程)下运行良好,但在尝试从那里扩展时遇到了问题。对于 10000 个线程(10 个进程 1000 个线程),服务器实际上变得更慢,并且在相同数量的并发请求下开始执行非常糟糕。

大量 Apache 线程的性能限制因素是什么?为什么 10000 个线程的性能比 1000 个线程差?到底是什么限制了线程的数量?我们意识到,在通常的 Web 服务上,10000 个并发连接不是日常业务,但我们正试图更好地了解 Web 服务器的可伸缩性和不同类型的 Web 服务器。

这是我们为 1000 个线程设置的 mpm 工作线程,效果非常好。

<IfModule mpm_worker_module>
    StartServers           10
    MinSpareThreads      1000
    MaxSpareThreads      1000
    ThreadLimit          1000
    ThreadsPerChild       100
    MaxClients           1000
    MaxRequestsPerChild     0
</IfModule>

Mpm worker 设置为 10000 个线程。这个设置慢了 5 倍。

<IfModule mpm_worker_module>
    StartServers           10
    MinSpareThreads     10000
    MaxSpareThreads     10000
    ThreadLimit         10000
    ThreadsPerChild      1000
    MaxClients          10000
    MaxRequestsPerChild     0
</IfModule>
4

1 回答 1

4

I am not even sure where to start as to why using that many threads in Apache is a bad idea. I would suggest you as a start go watch my PyCon talks:

The short answer is that if you have a real need to handle large numbers of truly concurrent long running requests on a single server, you probably should not be using Apache. You should be using an event based (async) system for those specific requests that have those non standard requirements. In other words, you don't need to switch your whole application to the async model, instead vertically partition your application and subset out the URLs that have the requirement which is different to the rest of your application. That way you can tailor the hosting to the requirements of each and not force your whole application to run under the constraints imposed by a small part of your application.

Now in reality though, most of the time when people think they need to be able to handle such insane number of concurrent requests on one server, they don't. For requests with a short response time, to handle 10000 requests per second, you do not need 10000 threads. This is because in each 1 second time slot, you can handle more than 1 request.

The one thing that can screw this up though is slow clients and keep alive. This is the killer for Apache. So, go stick nginx in front of it as a proxy and turn off keep alive in Apache, but leave keep alive on in nginx. Using nginx as a proxy will isolate Apache from slow clients and allow it to perform better with less resources. This is because a request is only handed off to Apache when it would generally have all the information in the request so as to allow it to handle the request immediately. Thus is isn't tied up and wasting resources waiting on a slow client.

If you do have that requirement for very long running requests (long polling), for a subset of requests, then have nginx proxy just those URLs to a separate async based server. That way you don't have to deal with the pain of using async systems in the rest of your otherwise normal web application.

This all said, also remember that the web server is not usually going to be your bottleneck. Who cares if the server can handle 10000+ requests per second if your actual web application stack, including database, can only handle 10 requests per second. That is going to be your real problem and if you don't improve your web application performance, tweaking the web server is going to make no difference at all. The only solution would be to horizontally scale and have more than one host and load balance across them.

In order to find the real bottlenecks you are going to need performance monitoring on your real world application, with real traffic from real users. You can see more about performance monitoring in my talks.

于 2013-07-28T23:14:19.870 回答