#python #многопоточность #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 секунд. Как будто работая все равно в один поток. Что я делаю не так? :)
Ответы
Ответ 1
Я могу воспроизвести поведение в 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, возможно связано с настройками кэширования).Ответ 2
Да, в общем-то, вы всё правильно делаете, вот только действительно работаете с одним потоком, так как ваш браузер уже имеет соединение с сервером. Попробуйте открыть разные браузеры.
Комментариев нет:
Отправить комментарий