Страницы

Поиск по вопросам

воскресенье, 30 июня 2019 г.

Как gunicorn запустить для обслуживания нескольких потоков?

Есть тестовое приложение:
import time from flask import Flask
app = Flask(import_name=__name__)
@app.route('/') def test(): time.sleep(5) return 'ok'
Запускаю gunicorn так:
(VENV) p2mbot@mbp:~/projects/test/gt$ gunicorn --workers 10 --threads 10 gt:app [2015-07-18 11:23:10 +0300] [13196] [INFO] Starting gunicorn 19.3.0 [2015-07-18 11:23:10 +0300] [13196] [INFO] Listening at: http://127.0.0.1:8000 (13196) [2015-07-18 11:23:10 +0300] [13196] [INFO] Using worker: threads [2015-07-18 11:23:10 +0300] [13199] [INFO] Booting worker with pid: 13199 [2015-07-18 11:23:10 +0300] [13200] [INFO] Booting worker with pid: 13200 [2015-07-18 11:23:10 +0300] [13201] [INFO] Booting worker with pid: 13201 [2015-07-18 11:23:10 +0300] [13202] [INFO] Booting worker with pid: 13202 [2015-07-18 11:23:10 +0300] [13203] [INFO] Booting worker with pid: 13203 [2015-07-18 11:23:10 +0300] [13204] [INFO] Booting worker with pid: 13204 [2015-07-18 11:23:10 +0300] [13205] [INFO] Booting worker with pid: 13205 [2015-07-18 11:23:10 +0300] [13206] [INFO] Booting worker with pid: 13206 [2015-07-18 11:23:10 +0300] [13207] [INFO] Booting worker with pid: 13207 [2015-07-18 11:23:10 +0300] [13208] [INFO] Booting worker with pid: 13208
Дальше в браузере одновременно открываю 5 вкладок этого тестового сайта. Я ожидаю, что эти вкладки в браузере отобразятся одновременно через 5 секунд, как задано в коде. Но они появляются поочередно, через каждые 5 секунд. Как будто работая все равно в один поток.
Что я делаю не так? :)


Ответ

Я могу воспроизвести поведение в Firefox и Google Chrome. Браузер выполняет только один запрос по заданной ссылке за раз.
Достаточно, использовать уникальные ссылки, чтобы увидеть, что gunicorn может обслуживать несколько запросов одновременно. Или вручную запустить несколько запросов (в этом случае не важно, одинаковые или разные ссылки).
Вот Питон скрипт, который выполняет несколько одновременных http-запросов и в то же время открывает те же ссылки в браузере:
#!/usr/bin/env python import webbrowser from multiprocessing.pool import ThreadPool
try: from urllib2 import urlopen except ImportError: # Python 3 from urllib.request import urlopen
urls = ['http://localhost:8000']*5 # same url urls += ['http://localhost:8000?unique=' + str(i) for i in range(5)] # uniq. urls pool = ThreadPool(len(urls) * 2) # make requests concurrently r = pool.map_async(lambda url: urlopen(url).read(), urls) pool.map(webbrowser.open_new_tab, urls) # open tabs in a browser r.get()
Для тестирования можно использовать, простое wsgi-приложение:
#file: wsgi_sleep.py import itertools import time
def app(environ, start_response, ids=itertools.count(1)): status = '200 OK' headers = [('Content-type', 'text/plain')] data = "# request(s) per worker: " + str(next(ids)) headers.append(('Content-Length', str(len(data)))) start_response(status, headers) time.sleep(5) return [data]
Его можно запустить как:
$ gunicorn --threads 20 --access-logfile - wsgi_sleep:app
Результат
127.0.0.1 - - [18/Jul/2015:19:15:09 +0000] "GET / HTTP/1.1" 200 26 "-" "Python-urllib/2.7" 127.0.0.1 - - [18/Jul/2015:19:15:09 +0000] "GET / HTTP/1.1" 200 26 "-" "Python-urllib/2.7" 127.0.0.1 - - [18/Jul/2015:19:15:09 +0000] "GET / HTTP/1.1" 200 26 "-" "Python-urllib/2.7" 127.0.0.1 - - [18/Jul/2015:19:15:09 +0000] "GET / HTTP/1.1" 200 26 "-" "Python-urllib/2.7" 127.0.0.1 - - [18/Jul/2015:19:15:09 +0000] "GET /?unique=0 HTTP/1.1" 200 26 "-" "Python-urllib/2.7" 127.0.0.1 - - [18/Jul/2015:19:15:09 +0000] "GET /?unique=1 HTTP/1.1" 200 26 "-" "Python-urllib/2.7" 127.0.0.1 - - [18/Jul/2015:19:15:09 +0000] "GET / HTTP/1.1" 200 26 "-" "Python-urllib/2.7" 127.0.0.1 - - [18/Jul/2015:19:15:09 +0000] "GET /?unique=3 HTTP/1.1" 200 27 "-" "Python-urllib/2.7" 127.0.0.1 - - [18/Jul/2015:19:15:09 +0000] "GET /?unique=2 HTTP/1.1" 200 26 "-" "Python-urllib/2.7" 127.0.0.1 - - [18/Jul/2015:19:15:09 +0000] "GET /?unique=4 HTTP/1.1" 200 26 "-" "Python-urllib/2.7" 127.0.0.1 - - [18/Jul/2015:19:15:14 +0000] "GET / HTTP/1.1" 200 27 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:39.0) Gecko/20100101 Firefox/39.0" 127.0.0.1 - - [18/Jul/2015:19:15:14 +0000] "GET /?unique=2 HTTP/1.1" 200 27 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:39.0) Gecko/20100101 Firefox/39.0" 127.0.0.1 - - [18/Jul/2015:19:15:14 +0000] "GET /?unique=4 HTTP/1.1" 200 27 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:39.0) Gecko/20100101 Firefox/39.0" 127.0.0.1 - - [18/Jul/2015:19:15:14 +0000] "GET /?unique=1 HTTP/1.1" 200 27 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:39.0) Gecko/20100101 Firefox/39.0" 127.0.0.1 - - [18/Jul/2015:19:15:14 +0000] "GET /?unique=3 HTTP/1.1" 200 27 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:39.0) Gecko/20100101 Firefox/39.0" 127.0.0.1 - - [18/Jul/2015:19:15:14 +0000] "GET /?unique=0 HTTP/1.1" 200 27 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:39.0) Gecko/20100101 Firefox/39.0" 127.0.0.1 - - [18/Jul/2015:19:15:19 +0000] "GET / HTTP/1.1" 200 27 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:39.0) Gecko/20100101 Firefox/39.0" 127.0.0.1 - - [18/Jul/2015:19:15:24 +0000] "GET / HTTP/1.1" 200 27 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:39.0) Gecko/20100101 Firefox/39.0" 127.0.0.1 - - [18/Jul/2015:19:15:29 +0000] "GET / HTTP/1.1" 200 27 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:39.0) Gecko/20100101 Firefox/39.0" 127.0.0.1 - - [18/Jul/2015:19:15:34 +0000] "GET / HTTP/1.1" 200 27 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:39.0) Gecko/20100101 Firefox/39.0"
Лог показывает, что запросы от urllib клиента завершаются практически одновременно в то время как запросы от браузера для повторяющихся ссылок происходят последовательно (не связано с network.http.max-connections-per-server, возможно связано с настройками кэширования).

Комментариев нет:

Отправить комментарий