Für mein Projekt jitt.li verwende ich die Twitter Streaming-API um Tweets über einen Websocket-Server an den Browser zu senden. Je nach gesetzten Filtern kann es nun vorkommen, dass viele hundert oder tausend Tweets pro Sekunde vom Twitter empfangen werden. Zunächst habe ich alle empfangenen Tweets direkt an den Websocket-Server gesendet. Der Datenfluss sah in etwa so aus:
Twitter -> API-Client -> Websocket-Server -> Browser
Das brachte jedoch einige Probleme mit sich: Zum einen wurde sehr viel Last vom Websocket-Server erzeugt was teilweise in einem Absturz endete. Zum anderen wurden oft mehr Tweets gesendet als man sie im Browser noch vernüftig hätte lesen können. Eine Möglichkeit dieses Problem zu lösen wäre die empfangenen Daten direkt vom API-Client filtern zu lassen und entsprechend reduziert an den Websocket-Server zu senden. Aber auch diese Möglichkeit bringt Probleme mit sich und wird von Twitter ausdrücklich nicht empfohlen. Je nach Komplexität des Filters im API-Client und der Menge der empfangenen Daten kann es passieren, dass der Client Daten langsamer abarbeitet als neue empfangen werden. In diesem Fall wird der Client von der API getrennt. Es ist also ratsam den API-Client so wenig wie möglich mit den empfangenen Daten arbeiten zu lassen. Meine Lösung sieht nun folgendermaßen aus:
Twitter -> API-Client -> Redis DB || -> Fetch-Script -> Websocket Server -> Browser
Der API-Client legt alle Daten ungefiltert in einer simplen Redis-Liste ab. Ein weiteres (davon unabhängiges) Script schaunt nun permanent nach ob neue Daten in der Datenbank vorhanden sind, falls ja werden sie an den Websocket-Server weitergereicht. Im ersten Moment sieht das nicht sehr viel anders aus als die ursprüngliche Variante jedoch gibt es einige große Vorteile:
- Der API-Client wird entlastet da alle Daten einfach ungefiltert in einer Datenbank abgelegt werden.
- Das Fetch-Script kann mit einem Limit beim Abrufen der Daten arbeiten. Egal wie viele neue Daten in der Queue liegen werden diese nur bis zu einer bestimmten Grenze an den Websocket-Server weitergeleitet. Der Rest wird verworfen. Somit wird der Websocket-Server ebenfalls entlastet.
Ein abschließender Hinweis: Beim Füllen der Queue (schreiben der Daten in die Redis-DB) sollte unbedingt auf ein Limit geachtet werden. Sollten die Daten aus irgendeinem Grund vom Fetch-Script nicht mehr abgearbeitet werden würde die DB sonst immer weiter aufgefüllt!