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?
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? –
Mögliche dup, sicherlich verwandt: http://stackoverflow.com/questions/9501663/how-enable-requests-async-mode –
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. –