Uwsgi与gevent vs线程

时间:2015-01-11 18:04:19

标签: python django multithreading uwsgi gevent

首先,抱歉我的英语不好。 在我的项目中,我有很多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代理)中有什么优势?

2 个答案:

答案 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,至少在您的应用程序的这一部分。