Po pierwsze, przepraszam za mój zły angielski. W moim projekcie mam wiele żądań sieci I/O. Główne dane przechowywane w innych projektach, a dostęp zapewnia internetowy interfejs API (JSON/XML), polling. Używamy tych interfejsów API dla każdej nowej sesji użytkownika (uzyskiwanie informacji o użytkowniku). Czasami mamy problem z czekaniem na odpowiedź. Używamy nginx + uwsgi + django. Jak wiesz, Django jest synchroniczny (lub blokujący). Używamy uwsgi z wielowątkowością do rozwiązania problemu z siecią IO oczekiwania. Postanowiłem przeczytać o geenie. Rozumiem różnicę między wielozadaniowością opartą na współpracy i prewencją. Miałem nadzieję, że gevent jest lepszym rozwiązaniem niż wątki uwsgi dla tego problemu (wąskie gardło sieci I/O). Ale wyniki były niemal identyczne. Czasami geulacja była słabsza. Może gdzieś się mylę. Powiedz mi proszę.Uwsgi z gevent vs wątki
Oto przykłady konfiguracji wtsgi. Gevent:
$ uwsgi --http :8001 --module ugtest.wsgi --gevent 40 --gevent-monkey-patch
przewlekania
$ uwsgi --http :8001 --module ugtest.wsgi --enable-threads --threads 40
Kontroler przykład:
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
testu (z 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
W obu przypadkach mam podobny czas. Jakie są zalety gevent/greenlets i kooperatywna wielozadaniowość w podobnym zagadnieniu (proxy API)?
Próbuję przetestować go z inną liczbą wątków/greenletów. Nie tysiące, ale setki. A wynik jest podobny. Myślę, że gevent jest najlepszym wyborem, jeśli mam więcej niż jedno żądanie w mojej akcji kontrolera (używając join()/joinall()). Ale w moim wydaniu ("proxy" -API) nie mam znaczących korzyści. W pierwszym przypadku (wątki) mamy prosty configure: --threads N. W drugim przypadku (gevent) mamy duży problem z łataniem sterownika PostgreSQL (na przykład), redis itp. Mamy również problem ze śledzeniem całego stosu ... – OLMER
Przykro nam, nie do końca Cię śledzić, jeśli nie możesz "załatać" django, nie możesz użyć gevent, thatsit. Twoja aplikacja musi być w 100% niezablokowana, w przeciwnym razie jest to aplikacja blokująca, a gevent nie pomoże ci (cóż, może nawet zrobić najgorsze) – roberto