2016-05-04 2 views
0

У меня есть сервер, обслуживающий HTML с nginx, uwsgi и flask. Это простой webapp. Когда вы обновляете страницу, webapp выполняет некоторые вызовы API в другом месте, а затем обрабатывает результаты, возвращаемые API-интерфейсами, и генерирует HTML-код, который затем возвращается.Python, обслуживающий html async

Теперь большую часть времени тратит на ожидание ответа API. Из-за этого я использую gevent, чтобы вызывать вызовы API и исправления обезьян и т. Д., Чтобы сделать все это одновременно. Если для обновления каждой страницы вам необходимо сделать 3 вызова API, вам не нужно ждать, пока первый вызов вернется, чтобы начать второй вызов. Вы инициируете все три из них, дождитесь их ответов и затем сгенерируете возвращаемый HTML-код.

Однако отдельный вопрос заключается в том, являются ли страницы обновленными от начала до конца, сами являются параллельными. Чтобы проверить это, я написал небольшой параллельный сценарий, чтобы сделать освежают к серверу:

from gevent import monkey 
monkey.patch_all() 

import requests, datetime 

import gevent 

def call_func(n): 
    before = datetime.datetime.now() 
    print 'initiating call '+str(n),before 
    requests.get('http://examplemyserver.com') 
    after = datetime.datetime.now() 
    print 'finishing call '+str(n),after, after-before 

gevent_list = [ gevent.spawn(call_func, n=n) for n in range(10) ] 

gevent.joinall(gevent_list) 

Вот результаты:

initiating call 0 2016-05-04 23:03:49.437540 
initiating call 1 2016-05-04 23:03:49.446304 
initiating call 2 2016-05-04 23:03:49.447911 
initiating call 3 2016-05-04 23:03:49.450232 
initiating call 4 2016-05-04 23:03:49.451774 
initiating call 5 2016-05-04 23:03:49.453331 
initiating call 6 2016-05-04 23:03:49.454759 
initiating call 7 2016-05-04 23:03:49.456301 
initiating call 8 2016-05-04 23:03:49.457663 
initiating call 9 2016-05-04 23:03:49.458981 
finishing call 0 2016-05-04 23:03:51.270078 0:00:01.832538 
finishing call 6 2016-05-04 23:03:52.169842 0:00:02.715083 
finishing call 3 2016-05-04 23:03:52.907892 0:00:03.457660 
finishing call 1 2016-05-04 23:03:53.498008 0:00:04.051704 
finishing call 8 2016-05-04 23:03:54.150188 0:00:04.692525 
finishing call 4 2016-05-04 23:03:55.032089 0:00:05.580315 
finishing call 7 2016-05-04 23:03:55.994570 0:00:06.538269 
finishing call 2 2016-05-04 23:03:56.659146 0:00:07.211235 
finishing call 9 2016-05-04 23:03:57.149156 0:00:07.690175 
finishing call 5 2016-05-04 23:03:58.002210 0:00:08.548879 

Итак, вы видите, десять страниц обновляется инициированные практически одновременно, однако они возвращаются последовательно с разницей в 1 секунду. Это говорит о том, что, хотя внутренние вызовы API выполняются одновременно, пока не будет получен ответ HTTP, новые HTTP-ответы не принимаются.

Итак, учитывая, что большая часть времени webapp тратится на ожидание ответов API, как я могу сделать весь процесс параллельным? Это что-то, что мне нужно изменить с помощью nginx? С uwsgi? С колбой? Я понятия не имею об архитектуре этих вещей.

Спасибо.

EDIT 1: Следуя за идеей Роба, я заменил сервер, который будет называться 'http://httpbin.org/delay/1'. Это результат я получаю:

initiating call 0 2016-05-04 23:36:18.697813 
initiating call 1 2016-05-04 23:36:18.706510 
initiating call 2 2016-05-04 23:36:18.708645 
initiating call 3 2016-05-04 23:36:18.711055 
initiating call 4 2016-05-04 23:36:18.712679 
initiating call 5 2016-05-04 23:36:18.714051 
initiating call 6 2016-05-04 23:36:18.715471 
initiating call 7 2016-05-04 23:36:18.717015 
initiating call 8 2016-05-04 23:36:18.718412 
initiating call 9 2016-05-04 23:36:18.720193 
finishing call 0 2016-05-04 23:36:20.599483 0:00:01.901670 
finishing call 2 2016-05-04 23:36:20.600829 0:00:01.892184 
finishing call 8 2016-05-04 23:36:20.611292 0:00:01.892880 
finishing call 5 2016-05-04 23:36:20.618842 0:00:01.904791 
finishing call 7 2016-05-04 23:36:20.620065 0:00:01.903050 
finishing call 6 2016-05-04 23:36:20.621344 0:00:01.905873 
finishing call 1 2016-05-04 23:36:20.622407 0:00:01.915897 
finishing call 4 2016-05-04 23:36:20.623392 0:00:01.910713 
finishing call 9 2016-05-04 23:36:20.624236 0:00:01.904043 
finishing call 3 2016-05-04 23:36:20.625075 0:00:01.914020 

Это то, что вы могли бы ожидать от сервера, который может принимать HTTP вызовы одновременно. Таким образом, это показывает, что приведенный выше код, который я использовал для теста, является правильным, и что проблема действительно на сервере. Он не принимает HTTP-вызовы одновременно.

EDIT2: Я играл вокруг и проверил, что наиболее простое приложение колба имеет такое же поведение, как мой сервер, поэтому я даю, что, как мой «минимальный пример»

Рассмотрим следующий сервер:

import time 

from flask import Flask, jsonify 
app = Flask(__name__) 

@app.route("/") 
def hello(): 
    time.sleep(2) 
    return '' 

if __name__ == "__main__": 
    app.run(host='0.0.0.0', port=80, debug=True) 

Теперь подключитесь к нему, взяв предыдущий код и указав его на http://localhost. В результате получается следующее:

initiating call 0 2016-05-04 23:49:12.629250 
initiating call 1 2016-05-04 23:49:12.638554 
initiating call 2 2016-05-04 23:49:12.643844 
initiating call 3 2016-05-04 23:49:12.645630 
initiating call 4 2016-05-04 23:49:12.647866 
initiating call 5 2016-05-04 23:49:12.649332 
initiating call 6 2016-05-04 23:49:12.650853 
initiating call 7 2016-05-04 23:49:12.652448 
initiating call 8 2016-05-04 23:49:12.653865 
initiating call 9 2016-05-04 23:49:12.655348 
finishing call 0 2016-05-04 23:49:14.671281 0:00:02.042031 
finishing call 1 2016-05-04 23:49:16.673649 0:00:04.035095 
finishing call 2 2016-05-04 23:49:18.676576 0:00:06.032732 
finishing call 3 2016-05-04 23:49:20.679746 0:00:08.034116 
finishing call 4 2016-05-04 23:49:22.681615 0:00:10.033749 
finishing call 5 2016-05-04 23:49:24.683817 0:00:12.034485 
finishing call 6 2016-05-04 23:49:26.686309 0:00:14.035456 
finishing call 7 2016-05-04 23:49:28.688079 0:00:16.035631 
finishing call 8 2016-05-04 23:49:30.691382 0:00:18.037517 
finishing call 9 2016-05-04 23:49:32.696471 0:00:20.041123 

Таким образом, в основном простая флэшка webapp не принимает вызовы HTTP одновременно. Как я могу это изменить?

+0

Также возможно, что http://examplemyserver.com является однопоточным. Это «examplemyserver.com» - производственный сервер или что-то, что вы собрали для этого эксперимента? –

+0

Возможный дубликат, конечно, связанный: http://stackoverflow.com/questions/9501663/how-enable-requests-async-mode –

+0

С Python2.7.6 я не могу воспроизвести ваши результаты. Я заменил URL на http: // httpbin.org/delay/1', но в остальном мой код идентичен вашему. Для меня все строки запросов встречаются более или менее одновременно, есть 1-секундная задержка, и все линии ответа происходят более или менее одновременно. –

ответ