2016-05-04 10 views
0

Ich habe einen Server HTML mit Nginx, uwsgi und Kolben dient. Es ist eine einfache Webanwendung. Wenn Sie eine Seite aktualisieren, führt die Webanwendung einige API-Aufrufe an anderer Stelle durch und behandelt dann die von den APIs zurückgegebenen Ergebnisse und generiert den HTML-Code, der dann zurückgegeben wird.Python Serving HTML async

Jetzt wird die meiste Zeit damit verbracht, darauf zu warten, dass die APIs reagieren. Aus diesem Grund verwende ich Gevent, um die API-Aufrufe und Monkey-Patching usw. zu machen, um alles gleichzeitig zu machen. Wenn Sie für jede Seitenaktualisierung 3 API-Aufrufe durchführen müssen, müssen Sie nicht warten, bis der erste Anruf zurückkehrt, um den zweiten Anruf einzuleiten. Sie initiieren alle drei, warten auf ihre Antworten und generieren dann den HTML-Code, der zurückgegeben werden soll.

Eine separate Frage ist jedoch, ob die Seite von Anfang bis Ende aktualisiert wird, sind sie gleichzeitig. Um dies zu testen, schrieb ich ein kleines Skript gleichzeitig zu Auffrischungen zu meinem Server zu machen:

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) 

Hier sind die Ergebnisse:

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 

Sie sehen also, zehn Seite aktualisiert praktisch zur gleichen Zeit initiiert werden, sie werden jedoch sequentiell mit einer Differenz von etwa 1 Sekunde zurückgegeben. Dies legt nahe, dass intern die externen API-Aufrufe gleichzeitig ausgeführt werden, bis eine HTTP-Antwort gegeben wird, aber keine neuen HTTP-Antworten akzeptiert werden.

Also, da der Großteil der Webapp-Zeit darauf verwendet wird, auf API-Antworten zu warten, wie kann ich den gesamten Prozess parallel gestalten? Ist es etwas, das ich mit nginx ändern muss? Mit uwsgi? Mit Flasche? Ich habe keine Ahnung von der Architektur dieser Dinge.

Danke.

EDIT 1: Nach Rob Idee, ersetzte ich den Server mit 'http://httpbin.org/delay/1' aufgerufen werden. Dies ist das Ergebnis, das ich erhalten:

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 

Dies ist, was Sie von einem Server erwarten würden, die nehmen können HTTP gleichzeitig aufruft. Das zeigt also, dass der obige Code, den ich für den Test verwendet habe, korrekt ist und dass das Problem tatsächlich auf dem Server liegt. Es nimmt keine HTTP-Aufrufe gleichzeitig.

EDIT2: Ich spielte herum und überprüft, dass die einfachste mögliche Kolben App das gleiche Verhalten wie mein Server hat, so gebe ich das als meine „minimal Beispiel“

den folgenden Server vor:

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) 

Verbinden Sie sich nun mit ihm, indem Sie den vorherigen Code nehmen und auf http://localhost zeigen. Das Ergebnis ist folgendes:

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 

Also im Grunde ein einfacher Kolben Webapp dauert nicht HTTP gleichzeitig aufruft. Wie kann ich das ändern?

+0

Es ist auch möglich, dass http://examplemyserver.com ist single-threaded. Es "examplemyserver.com" ein Produktionsserver oder etwas, das Sie für dieses Experiment aufgemacht haben? –

+0

Mögliche dup, sicherlich verwandt: http://stackoverflow.com/questions/9501663/how-enable-requests-async-mode –

+0

Mit Python2.7.6 kann ich Ihre Ergebnisse nicht reproduzieren. Ich habe die URL durch "http: // httpbin.org/delay/1" ersetzt, aber ansonsten ist mein Code identisch mit Ihrem. Für mich treten alle Anforderungszeilen mehr oder weniger gleichzeitig auf, es gibt eine Verzögerung von 1 Sekunde und alle Antwortzeilen treten mehr oder weniger gleichzeitig auf. –

Antwort