我正在使用nginx & uwsgi运行django应用程序。下面是我运行uwsgi的方式:
sudo uwsgi -b 25000 --chdir=/www/python/apps/pyapp --module=wsgi:application --env DJANGO_SETTINGS_MODULE=settings --socket=/tmp/pyapp.socket --cheaper=8 --processes=16 --harakiri=10 --max-requests=5000 --vacuum --master --pidfile=/tmp/pyapp-master.pid --uid=220 --gid=499
nginx配置:
server {
listen 80;
server_name test.com
root /www/python/apps/pyapp/;
access_log /var/log/nginx/test.com.access.log;
error_log /var/log/nginx/test.com.error.log;
# https://docs.djangoproject.com/en/dev/howto/static-files/#serving-static-files-in-production
location /static/ {
alias /www/python/apps/pyapp/static/;
expires 30d;
}
location /media/ {
alias /www/python/apps/pyapp/media/;
expires 30d;
}
location / {
uwsgi_pass unix:///tmp/pyapp.socket;
include uwsgi_params;
proxy_read_timeout 120;
}
# what to serve if upstream is not available or crashes
#error_page 500 502 503 504 /media/50x.html;
}
问题来了。在服务器上执行"ab“(ApacheBenchmark)时,我得到了以下结果:
nginx版本: nginx版本: nginx/1.2.6
uwsgi版本:1.4.5
Server Software: nginx/1.0.15
Server Hostname: pycms.com
Server Port: 80
Document Path: /api/nodes/mostviewed/8/?format=json
Document Length: 8696 bytes
Concurrency Level: 100
Time taken for tests: 41.232 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 8866000 bytes
HTML transferred: 8696000 bytes
Requests per second: 24.25 [#/sec] (mean)
Time per request: 4123.216 [ms] (mean)
Time per request: 41.232 [ms] (mean, across all concurrent requests)
Transfer rate: 209.99 [Kbytes/sec] received
在500并发级别上运行时
oncurrency Level: 500
Time taken for tests: 2.175 seconds
Complete requests: 1000
Failed requests: 50
(Connect: 0, Receive: 0, Length: 50, Exceptions: 0)
Write errors: 0
Non-2xx responses: 950
Total transferred: 629200 bytes
HTML transferred: 476300 bytes
Requests per second: 459.81 [#/sec] (mean)
Time per request: 1087.416 [ms] (mean)
Time per request: 2.175 [ms] (mean, across all concurrent requests)
Transfer rate: 282.53 [Kbytes/sec] received
如你所见..。服务器上的所有请求都会失败,并出现超时错误或“客户端过早断开”,或者:
writev(): Broken pipe [proto/uwsgi.c line 124] during GET /api/nodes/mostviewed/9/?format=json
下面是关于我的应用程序的更多信息:基本上,它是一个反映包含所有内容的MySQL表的模型集合。在前端,我有django-rest-framework,它为客户端提供json内容。
我已经安装了django-profiling & django debug工具栏来看看发生了什么。关于django-profiling,这是我在运行单个请求时得到的结果:
Instance wide RAM usage
Partition of a set of 147315 objects. Total size = 20779408 bytes.
Index Count % Size % Cumulative % Kind (class / dict of class)
0 63960 43 5726288 28 5726288 28 str
1 36887 25 3131112 15 8857400 43 tuple
2 2495 2 1500392 7 10357792 50 dict (no owner)
3 615 0 1397160 7 11754952 57 dict of module
4 1371 1 1236432 6 12991384 63 type
5 9974 7 1196880 6 14188264 68 function
6 8974 6 1076880 5 15265144 73 types.CodeType
7 1371 1 1014408 5 16279552 78 dict of type
8 2684 2 340640 2 16620192 80 list
9 382 0 328912 2 16949104 82 dict of class
<607 more rows. Type e.g. '_.more' to view.>
CPU Time for this request
11068 function calls (10158 primitive calls) in 0.064 CPU seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.064 0.064 /usr/lib/python2.6/site-packages/django/views/generic/base.py:44(view)
1 0.000 0.000 0.064 0.064 /usr/lib/python2.6/site-packages/django/views/decorators/csrf.py:76(wrapped_view)
1 0.000 0.000 0.064 0.064 /usr/lib/python2.6/site-packages/rest_framework/views.py:359(dispatch)
1 0.000 0.000 0.064 0.064 /usr/lib/python2.6/site-packages/rest_framework/generics.py:144(get)
1 0.000 0.000 0.064 0.064 /usr/lib/python2.6/site-packages/rest_framework/mixins.py:46(list)
1 0.000 0.000 0.038 0.038 /usr/lib/python2.6/site-packages/rest_framework/serializers.py:348(data)
21/1 0.000 0.000 0.038 0.038 /usr/lib/python2.6/site-packages/rest_framework/serializers.py:273(to_native)
21/1 0.000 0.000 0.038 0.038 /usr/lib/python2.6/site-packages/rest_framework/serializers.py:190(convert_object)
11/1 0.000 0.000 0.036 0.036 /usr/lib/python2.6/site-packages/rest_framework/serializers.py:303(field_to_native)
13/11 0.000 0.000 0.033 0.003 /usr/lib/python2.6/site-packages/django/db/models/query.py:92(__iter__)
3/1 0.000 0.000 0.033 0.033 /usr/lib/python2.6/site-packages/django/db/models/query.py:77(__len__)
4 0.000 0.000 0.030 0.008 /usr/lib/python2.6/site-packages/django/db/models/sql/compiler.py:794(execute_sql)
1 0.000 0.000 0.021 0.021 /usr/lib/python2.6/site-packages/django/views/generic/list.py:33(paginate_queryset)
1 0.000 0.000 0.021 0.021 /usr/lib/python2.6/site-packages/django/core/paginator.py:35(page)
1 0.000 0.000 0.020 0.020 /usr/lib/python2.6/site-packages/django/core/paginator.py:20(validate_number)
3 0.000 0.000 0.020 0.007 /usr/lib/python2.6/site-packages/django/core/paginator.py:57(_get_num_pages)
4 0.000 0.000 0.020 0.005 /usr/lib/python2.6/site-packages/django/core/paginator.py:44(_get_count)
1 0.000 0.000 0.020 0.020 /usr/lib/python2.6/site-packages/django/db/models/query.py:340(count)
1 0.000 0.000 0.020 0.020 /usr/lib/python2.6/site-packages/django/db/models/sql/query.py:394(get_count)
1 0.000 0.000 0.020 0.020 /usr/lib/python2.6/site-packages/django/db/models/query.py:568(_prefetch_related_objects)
1 0.000 0.000 0.020 0.020 /usr/lib/python2.6/site-packages/django/db/models/query.py:1596(prefetch_related_objects)
4 0.000 0.000 0.020 0.005 /usr/lib/python2.6/site-packages/django/db/backends/util.py:36(execute)
1 0.000 0.000 0.020 0.020 /usr/lib/python2.6/site-packages/django/db/models/sql/query.py:340(get_aggregation)
5 0.000 0.000 0.020 0.004 /usr/lib64/python2.6/site-packages/MySQLdb/cursors.py:136(execute)
2 0.000 0.000 0.020 0.010 /usr/lib/python2.6/site-packages/django/db/models/query.py:1748(prefetch_one_level)
4 0.000 0.000 0.020 0.005 /usr/lib/python2.6/site-packages/django/db/backends/mysql/base.py:112(execute)
5 0.000 0.000 0.019 0.004 /usr/lib64/python2.6/site-packages/MySQLdb/cursors.py:316(_query)
60 0.000 0.000 0.018 0.000 /usr/lib/python2.6/site-packages/django/db/models/query.py:231(iterator)
5 0.012 0.002 0.015 0.003 /usr/lib64/python2.6/site-packages/MySQLdb/cursors.py:278(_do_query)
60 0.000 0.000 0.013 0.000 /usr/lib/python2.6/site-packages/django/db/models/sql/compiler.py:751(results_iter)
30 0.000 0.000 0.010 0.000 /usr/lib/python2.6/site-packages/django/db/models/manager.py:115(all)
50 0.000 0.000 0.009 0.000 /usr/lib/python2.6/site-packages/django/db/models/query.py:870(_clone)
51 0.001 0.000 0.009 0.000 /usr/lib/python2.6/site-packages/django/db/models/sql/query.py:235(clone)
4 0.000 0.000 0.009 0.002 /usr/lib/python2.6/site-packages/django/db/backends/__init__.py:302(cursor)
4 0.000 0.000 0.008 0.002 /usr/lib/python2.6/site-packages/django/db/backends/mysql/base.py:361(_cursor)
1 0.000 0.000 0.008 0.008 /usr/lib64/python2.6/site-packages/MySQLdb/__init__.py:78(Connect)
910/208 0.003 0.000 0.008 0.000 /usr/lib64/python2.6/copy.py:144(deepcopy)
22 0.000 0.000 0.007 0.000 /usr/lib/python2.6/site-packages/django/db/models/query.py:619(filter)
22 0.000 0.000 0.007 0.000 /usr/lib/python2.6/site-packages/django/db/models/query.py:633(_filter_or_exclude)
20 0.000 0.000 0.005 0.000 /usr/lib/python2.6/site-packages/django/db/models/fields/related.py:560(get_query_set)
1 0.000 0.000 0.005 0.005 /usr/lib64/python2.6/site-packages/MySQLdb/connections.py:8()
..etc
但是,django-debug-toolbar显示以下内容:
Resource Usage
Resource Value
User CPU time 149.977 msec
System CPU time 119.982 msec
Total CPU time 269.959 msec
Elapsed time 326.291 msec
Context switches 11 voluntary, 40 involuntary
and 5 queries in 27.1 ms
问题是,"top“显示平均负载快速上升,而我在本地服务器和网络中的远程计算机上运行的apache基准测试表明,我每秒处理的请求并不多。有什么问题吗?这是我在分析代码时所能达到的最大限度,所以如果有人能指出我在这里做的事情,我将不胜感激。
编辑(2013年2月23日):根据Andrew Alcock的回答添加更多细节:需要我注意/回答的要点是(3)(3)我在MySQL上执行了"show global variables“,发现MySQL配置中有151个max_connections设置,这足以服务于我为uwsgi启动的工作人员。
(3)(4)(2)我分析的单个请求是最重的。它根据django-debug-toolbar执行4个查询。所有查询的运行时间分别为: 3.71、2.83、0.88、4.84ms。
(4)这里您指的是内存分页?如果是这样,我怎么知道呢?
(5)在16个工作线程上,100个并发率,1000个请求平均负载上升到~ 12我在不同数量的工作进程上运行了测试(并发级别为100):
<代码>H11816工作进程,平均负载~ 19,15请求/秒,每次请求时间: 6384.720,0非2xx
正如您所看到的,我们拥有的工作人员越多,系统上的负载就越大。我可以在uwsgi的守护进程日志中看到,当我增加工作进程的数量时,以毫秒为单位的响应时间会增加。
在16个工作线程上,运行500个并发级别的请求uwsgi开始记录错误:
writev(): Broken pipe [proto/uwsgi.c line 124]
负载也会上升到~ 10。测试不会花费太多时间,因为非2xx的响应是923 / 1000,这就是为什么这里的响应非常快,因为它几乎是空的。这也是对你总结中的第四点的回复。
假设我在这里面临的是基于I/O和网络的操作系统延迟,那么扩展该延迟的建议措施是什么?新硬件?更大的服务器?
谢谢
发布于 2013-02-24 17:44:56
请运行比一分钟更长的基准测试(至少5-10分钟),你不会从这么短的测试中获得太多信息。并使用uWSGI的carbon插件将统计数据推送到carbon/石墨服务器(您将需要一个),您将获得更多用于调试的信息。
当你向你的应用发送500个并发请求,但它无法处理这样的负载时,每个后端上的监听队列将很快被填满(默认情况下是100个请求),你可能想增加这个数量,但如果工作人员不能如此快速地处理请求,并且监听队列(也称为backlog)已满,linux网络堆栈将丢弃请求,你将开始收到错误。
您的第一个基准测试表明,您可以在大约42ms内处理单个请求,因此单个worker最多可以处理1000ms /42ms=每秒~23个请求(如果db和应用堆栈的其他部分不会随着并发性的增加而变慢)。所以要处理500个并发请求,你至少需要500 / 23 = 21个工作者(但实际上我会说至少40个),你只有16个,难怪它会在这样的负载下崩溃。
编辑:我混合了并发的速率--至少有21个工作线程允许你每秒处理500个请求,而不是500个并发请求。如果你真的想要处理500个并发请求,那么你只需要500个工作者。除非你要在异步模式下运行你的应用程序,否则请检查uWSGI文档中的"Gevent“部分。
PS。uWSGI提供了强大的负载均衡器和后端自动配置(请阅读“订阅服务器”和“FastRouter”下的文档)。您可以将其设置为允许您根据需要热插拔新的后端,您只需在新节点上启动workers,他们将订阅FastRouter并开始接收请求。这是水平扩展的最佳方式。使用AWS上的后端,您可以自动执行此操作,以便在需要时快速启动新的后端。
发布于 2013-02-24 14:47:03
添加更多的工作进程并获得更少的r/s意味着你的请求“是纯CPU”,并且没有IO等待可供另一个工作进程用来为另一个请求服务。
如果你想要扩展,你需要使用另一台cpu更多(或更快)的服务器。
然而,这是一个合成测试,你得到的r/s数是你正在测试的确切请求的上限,一旦投入生产,就会有更多的变量可以影响性能。
https://stackoverflow.com/questions/14962289
复制相似问题