Hallo,
bisschen spät aber noch kurz zur Ergänzung.
Du kannst auch einfach gutes altes
AJAX verwenden.
Ablauf:
1. die Clients senden einen Javascript/AJAX request an den Server (HTTP/GET)
2. der Server merkt sich den client in einer "Callback" Liste.
...
3. Bei neuen Inhalten in der DB (Bsp.-Weise ein insert/update) sendet der Server eine HTTP/response + Bsp.: JSON Daten
an die Clients in der Callbackliste.
4. die Clients zeigen die neuen Daten per Javascript auf der Seite an (Bsp.: <div> hinzufügen)
5. und lösen sofort wieder einen "gibts-neue-daten"-AJAX request aus.
und damit bist du wieder bei 2. .... und das geht immer so weiter.
Der AJAX Ansatz ist m.E. ganz gut, weil:
1. man kein periodisches polling hat. Der Client fragt einmal, der Server legt das auf Halde und das wars.
2. man Standard HTTP verwendet. Websockets ginge eben auch, ist aber ein anderes Protokol .. da muss man dann auch
Hier ein Beispiel wo ich das mal genauso mit Realtime updates von Tweets gemacht habe.
Die Server Applikation liest im twitter stream (tweepy) und trägt neue tweets mit #python in die DB ein. Die Clients (Browser) fragen der Server per AJAX und warten. Der Server schickt updates
an alle wartenden Clients wenn neue Tweets da sind.
Die Clients fügen die dann als <div> in der linken Column hinzu. ...
Die Dash Componenten aktualisieren sich auch mit den neuen Daten (Top twitter user, top hashtags usw..)
Als Beispiel der verwendete Javascript code . In diesem Fall jquery getJSON()
https://api.jquery.com/jQuery.getJSON/
Code: Alles auswählen
var num_tweets = 0;
var max_tweets = 2;
function get_messages() {
$.getJSON( "/messages", function( data, status, xhr ) {
console.log("got it ;)")
var items = [];
console.log(data);
$(".tweets").prepend( "<div>" + data["html"] + "</div>" );
$("#num_tweets").text(data["num_tweets"]);
if (num_tweets >= max_tweets){
$('.tweets').children().last().remove();
}
num_tweets += 1
setTimeout(get_messages,0);
});
}
Und die Server Seite (in diesem Fall Tornado / PythonOnWheels) .. geht aber so auch mit Tornado pur (dann sind die URLs nur nicht so schön
Code: Alles auswählen
@app.add_route('/messages', dispatch={"get" : "get_messages"})
class TweetHandler(PowHandler):
#
# on HTTP GET this method will be called. See dispatch parameter.
#
callbacks=set()
@web.asynchronous
def get_messages(self):
"""
long polling handler method registering the callbacks
"""
print("Adding callback...")
self.__class__.callbacks.add(self._callback)
#print(self.__class__.callbacks)
def _callback(self, tweet_json):
print("sending callback...")
self.success(message="new tweet", data=tweet_json, pure=True)
self.finish()
async def fire_callbacks(self, tweet_json):
print("fire all callbacks!")
print(50*"-")
tweet_json["num_tweets"] = len(tweet_cache)
for c in self.__class__.callbacks:
c(tweet_json)
self.__class__.callbacks = set()
Die fire_callbacks methode wird genau dann aufgerufen, wenn neue Tweets (in der Datenbank) sind.
Der Ansatz kann nur Problematisch werder, wenn man tausende von clients hat, da dann recht viele offene Verbindungen bestehen.+
Bei einer "normalen" Anzahl ist das aber kein Problem. Ansonsten kann man die Webserver Prozesse erhöhen.