首先,抱歉我的英语不好。 在我的项目中,我有很多I / O网络请求。主数据存储在另一个项目中,并且访问由Web API(JSON / XML)提供,轮询。我们为每个新用户会话使用此API(获取有关用户的信息)。有时,我们在等待回复时遇到问题。 我们使用nginx + uwsgi + django。如您所知,Django是同步(或阻塞)。 我们使用uwsgi和多线程来解决网络IO等待的问题。 我决定读一下gevent。我理解合作和先发制人多任务之间的区别。我希望gevent可以更好地解决这个问题的uwsgi线程(网络I / O瓶颈)。但结果几乎相同。有时gevent较弱。 也许某个地方我错了。请告诉我。
这是uwsgi配置示例。 GEVENT:
$ uwsgi --http :8001 --module ugtest.wsgi --gevent 40 --gevent-monkey-patch
线程:
$ uwsgi --http :8001 --module ugtest.wsgi --enable-threads --threads 40
控制器示例:
def simple_test_action(request):
# get data from API without parsing (only for simple I/O test)
data = _get_data_by_url(API_URL)
return JsonResponse(data, safe=False)
import httplib
from urlparse import urlparse
def _get_data_by_url(url):
u = urlparse(url)
if str(u.scheme).strip().lower() == 'https':
conn = httplib.HTTPSConnection(u.netloc)
else:
conn = httplib.HTTPConnection(u.netloc)
path_with_params = '%s?%s' % (u.path, u.query, )
conn.request("GET", path_with_params)
resp = conn.getresponse()
print resp.status, resp.reason
body = resp.read()
return body
测试(geventhttpclient):
def get_info(i):
url = URL('http://localhost:8001/simpletestaction/')
http = HTTPClient.from_url(url, concurrency=100, connection_timeout=60, network_timeout=60)
try:
response = http.get(url.request_uri)
s = response.status_code
body = response.read()
finally:
http.close()
dt_start = dt.now()
print 'Start: %s' % dt_start
threads = [gevent.spawn(get_info, i) for i in xrange(401)]
gevent.joinall(threads)
dt_end = dt.now()
print 'End: %s' % dt_end
print dt_end-dt_start
在这两种情况下,我都有类似的时间。 gevent / greenlets和合作多任务在类似问题(API代理)中有什么优势?
答案 0 :(得分:6)
40的并发性并不是让gevent闪耀的水平。 Gevent是关于并发而不是并行(或每请求性能),因此具有这种“低”并发级别并不是获得改进的好方法。
通常,您会看到gevent并发的数量级为千,而不是40:)
对于阻塞I / O python线程也不错(GIL在I / O期间发布),gevent的优势在于资源使用(拥有1000个python线程将是矫枉过正)并且无需考虑锁定和朋友。
显然,请记住,您的整个应用程序必须是gevent友好的才能获得优势,而django(默认情况下)需要进行一些调整(例如,数据库适配器必须使用gevent friendly更改)。
答案 1 :(得分:1)
服务非阻塞不是关于性能,而是关于并发性。如果在子请求中花费了99%的请求时间,则无法优化这些99%。但是当所有可用的线程忙于服务时,新的客户端被拒绝,尽管99%的线程'等待子请求完成所花费的时间。非阻塞服务允许您通过在"处理程序之间共享空闲时间来使用#34;不受可用线程数量的限制。因此,如果99%正在等待,那么另外1%是CPU绑定处理,因此在最大化CPU之前可以同时拥有100倍以上的连接 - 没有多100倍的线程,这可能太昂贵了(并且使用Python&# 39; s GIL问题,你必须使用更昂贵的子流程。
现在,正如roberto所说,您的代码必须100%无阻塞才能挽救空闲时间。但是,正如您从上面的百分比示例中可以看到的,只有当请求几乎完全受IO限制时,它才变得至关重要。如果是这种情况,那么您可能不需要Django,至少在您的应用程序的这一部分。