Javascript Websockets Streams Verbindung checken

BTCStorage

Ensign
Registriert
Mai 2020
Beiträge
166
Ich probiere seit paar Tagen mit Websockets etwas zu bauen, aber ich bin im Moment nicht so zu frieden mit Websockets.

Wahrscheinlich liegt es auch daran das ich nicht viel Erfahrung habe mit Websockets oder vielleicht sind Websockets auch allgemein so gebaut, bisjen problematisch sage ich mal, ich probiere mal zu erklaeren was ich fuer Probleme mit Websockets habe.

1. Ich probiere zum Beispiel fuer verschiedene Crypto Currency ein Datenstream zu erhalten, das geht alles erstmal auch ganz einfach, mit folgendem Code sende ich eine Anfrage und erhalte auch nach wenigen Sekunden eine Verbindung:

Javascript:
// Stream anfragen
let adress = 'wss://stream.binance.com:9443/ws/btcusdt@kline_1h';
const ws = new WebSocket(adress);

// Stream erhalten
ws.on('message', function incoming(data)
{
  const obj = JSON.parse(data);
});

Soweit funktioniert alles erst mal ganz einfach. Wenn ich jetzt aber zum Beispiel fuer Bitcoin 5 verschiedene Candelstick Perioden erhalten will und das gleiche fuer vielleicht 10 andere Crypto Currencys, dann sende ich circa 50 mal eine Anfrage und habe dann circa 50 Streams offen. Nun passiert es aber hin und wieder auch das ein Streams von alleine aufhoert, damit der wieder startet muss man ja erst mal wissen welcher Stream genau aufgehoert hat und dann wahrscheinlich fuer diesen eine neue Verbindungsanfrage senden.

Und hier faengt auch mein erstes Problem an, ich weis gar nicht wie man heraus finden soll welcher Stream genau aufgehoert hat, es gibt zwar eine Variable welche "readyState" heist und diese soll so zu sagen einen die Info geben koennen ob die Verbindung noch offen ist, aber woher soll ich wissen welcher Stream mit "readyState" gemeint ist, es steht ja nichts weiteres dazu ob das der Bitcoin Stream ist oder Ethereum usw, ich bekomme ja einfach nur eine Nummer von "readyState" und habe aber circa 50 mal eine Verbindung fuer verschiedene Streams gesendet:

Javascript:
if(ws.readyState==3)
{
    //also sagen wir die Verbindung ist geschlossen, ok unf welche Verbinung welche Crypto Currency welche Periode usw?
    /*
     0    CONNECTING    Der Socket wurde erstellt, jedoch besteht noch keine Verbindung.
     1    OPEN    Eine Verbindung wurde hergestellt und kann zur Kommunikation genutzt werden.
     2    CLOSING    Die Verbindung wird beendet.
     3    CLOSED    Die Verbindung wurde geschlossen oder konnte nicht geöffnet werden.
    */
}

Wenn man also erst mal hier genau unterscheiden kann welcher Stream gestoptt hat dann koennte man auch wieder eine neue Verbindungsanfrage senden.

2. Dann habe ich auch noch etwas bemerkt, irgendwie steigt der Arbeitsspeicher verbrauch mit der Zeit wenn ich dieses Experiment mit Websockets mache, ich vermute das es vielleicht daran liegt das der Aufruf "const ws = new WebSocket(adress);" immer etwas mehr Arbeitsspeicher kostet, weil dort vielleicht immer durch Erstellen eines Objekts mehr Arbeitsspeicher verbraucht wird, aber naja die Logik ist auch bisjen komisch, die Konstante heist ja immer gleich "ws" aber ein anderen Weg wie ich eine Anfrage zum ebsocket sende habe ich noch nicht gefunden.

Also generell scheint der PC mit der Zeit immer mehr Arbeitsspeicher zu verbrauchen, wenn ich das so auf ein VPS Server laufen lasse, dann ist der VPS Server immer nach paar Stunden nicht mehr erreichbar und man mus ihn neu starten.


Es wuerde mich mal interissieren wie andere Leute das sehen, seit Ihr zufrieden mit Websockets? Sieht jemand Fehler in meiner Vorgehensweise und eine professionellere Weise wie man so circa 50 Streams anfraget und genau ueberpruefen kann welche Streams stoppen damit man die neu anfraegt?

Im Moment benutze ich die ganz einfache HTTP GET Anfrage zur Binance API, damit kann man auch Candelstick Daten bekommen und zwar ohne so viel Probleme, aber mit Ratelimits.
 
Du kannst über einen WebSocket alle Coins abonnieren, da brauchst keine 50 Verbindungen: https://github.com/binance/binance-...r/web-socket-streams.md#subscribe-to-a-stream

Ansonsten könntest du auch direkt den kombinierten Endpunkt nutzen:
Combined streams are accessed at [B]/stream?streams=<streamName1>/<streamName2>/<streamName3>[/B]

Damit hat sich dann auch die Frage erledigt, welcher der Verbindungen weg ist, weil es nur noch eine gibt.

Außerdem musst du die Dinge beachten:

  • A single connection to stream.binance.com is only valid for 24 hours; expect to be disconnected at the 24 hour mark
  • The websocket server will send a ping frame every 3 minutes. If the websocket server does not receive a pong frame back from the connection within a 10 minute period, the connection will be disconnected. Unsolicited pong frames are allowed.
 
Bist selbst zufrieden mit Websockets? Ich finde es irgendwie kompliziert, weil man schonn da schnell durcheinander kommen kann wie bei meinem Beispiel zu sehen ist, aufeinmal hat man lauter Websockets offen und weis nicht wo man die Info genau ablesen kann was man am empfangen ist.

Ich hatte auch irgendwo gesehen das es ein Stream gibt wo man alle Crypto Currencys bekommt, aber ich glaube das ist nur fuer die Tagescandelsticks, ich brauche aber fuer mindestens 6 verschiedene Perioden die Candelsticks, deswegen habe ich das auch nicht benutzt.

Die Moeglichkeit ueber eine Anfrage mehrere Crypto Currencys und Periode an zu fragen habe ich auch gesehen, aber das war auch nicht fuer mein Fall eine gute Loesung, ich baue naemlich etwas wo man belibieg Crypto Currencys auswaehlen kann und dafuer dann die Charts bekommen soll. Und ich will nicht deswegen fuer alle moeglichen Crypto Currencys direkt ein Stream anfragen, ich glaube das wuerde vielleicht auch technisch gesehen nicht funktionieren, wenn man mal animmt es gibt vielleicht circa 500 crypto currencys zur Auswahl und davon will ich fuer circa 5 Perioden alle Charts erhalten, dann muste ich ja 500 mal 5 rechnen, also 2500 Streams anfragen, ich wweis nicht ob das mit einer einzigen Websocket Verbindung angefragt werden kann und man dann auch wirklich fuer alle der Stream sauber empfangen wird usw. also zu kompliziert.

Deswegen habe ich das so dynamisch gebaut, die Crypto Currency welche angeklickt wird fuer die werden Streams angefragt an das Websocket, der Javascript Code dafuer wird also ausgefuehrt, aber wie man sieht komme ich dann wieder zum Anfangsproblem, es sind irgendwann lauter Streams offen und man kann gar nicht mehr herausfinden welche Streams man erhaelt, also fuer mein Gefuehl alles sehr unsauber.

Deswegen benutze ich jetzt ganz einfach nur die HTTP API Anfragen das weis man genau was man macht und funktioniert.

Also ich bin mir schon bisjen unsicher jetzt inwieweit Websockets eine gute Loesung ist, fuer den Webserver von Binance ist das vielleicht ganz gut, weil er nicht die ganze zeit HTTP Request bearbeiten muss, aber so als Programmierer wenn etwas dynamisch sein soll past das vielleicht nicht.
 
Ich bin mir ehrlich gesagt nicht so sicher ob meine Meinung zu Websockets daher kommt weil ich nicht viel Erfahrung damit habe oder ob vielleicht die von mir gennanten Probleme mit Websockets in echt bestehen, es waere schon interessant wenn jemand mit mehr Erfahrung etwas dazu sagt.

Wenn man so wie in mein Beispiel fuer verschiedene Crypto Currencys ein neuen Stream starten muss, wie soll man nachher unterscheiden koennen welche "readyState" Variable zu welcher Websocket Verbindung gehoert?

ich habe in meinen Tests am Ende immer lauter offene Streams gehabt aber konnte im nachhinein mit der "readyState" Variable nicht mehr ueberpruefen welche Verbindung irgendwann stoppt, weil die Variable mir keine Infos ueber den Streamnamen gibt sondern nur eine Zahl als Rueckgabe.

Ich denke aber das man vielleicht mit einem etwas anderen Aufbau die vielen verschiedenen Websocketverbindungen besser ueberwachen koennte. Im Prinzip mueste man eine Art Array bauen wo der Indexname die Bezeichnung der Crypto Currency hat und gleichzeittig eine eigene Websocketvebindung mit eigener "readyState" Variable. Problem hier waere nur das es alles dynamisch aufgebaut sein muss, weil man vorher nicht weis welche Crypto Currency ausgewaehlt wird. Eine andere Moeglichkeit waere auch hunderte von Websocket Verbindungsanfragen im Voraus zu programmieren und bei Auswahl einer Crypto Currency die dazu passende Websocket Verbindung benutzt fuer das senden der Streamanfrage.
 
Ich mag WebSockets. Das Problem liegt hier, wenn ich mal ganz direkt bin, bei dir. Biance bietet dir da doch die möglichkeit über einen WebSocket, alle Daten dynamisch abzufragen (bzw zu (un)subscriben).

Welcher ReadyState zu welchem Socket gehört ist eben deine Aufgabe, das passend umzusetzen. Das ist überhaupt kein Problem. Aber nochmal: Du brauchst nicht mehr als einen einzigen WebSocket für das was du vorhast.
 
  • Gefällt mir
Reaktionen: BTCStorage
Ich habe keine Benachrichtigung erhalten unf sehe gerade das du vor 2 Wochen schon geschrieben hast.

Du sagst das du denkst man kann das alles mit einer Websocketverbindung machen, ich weis nicht, bin mir nicht sicher, ich erklaere nochmal was ich vor hatte, wenn du willst kannst du dann nochmal was dazu sagen.

Zum Beispiel was ich vor hatte ist folgendes, wir haben sagen wir 500 Crypto Currencys, fuer diese 500 gibt es jeweils sagen wir auch 5 verschiedene Perioden. Wenn man fuer eine Crypto Currency und eine Periode davon ein Chart anfragen will muss man das so schreiben in der Websocket Anfrage:

// Stream anfragen
let adress = 'wss://stream.binance.com:9443/ws/btcusdt@kline_1h';
const ws = new WebSocket(adress);

Ich habe auch die Info gesehen das man verschiedene Crypto Currencys gleichzeittig anfragen kann, dazu muss man die anderen Crypto Currencys mit in die Websocket Anfrage schreiben. Aber ich weis nicht ob man dort jetzt 5 mal 500 also 2500 weitere Crypto Currencys in diese eine Websocket Anfrage schreiben kann, ich denke das wuerde bisjen zu lang werden der Anfragestring, wie siehst du das den, wie macht man das?
 
Hast du oben mal auf den Link geklickt, den ich geschrieben habe? Da geht's direkt zu "Subscribe to a stream". Damit kannst du dynamisch die Coins zur laufenden Verbindung hinzufügen.
 
  • Gefällt mir
Reaktionen: BTCStorage
Ja ich hatte mir die verschiedenen Infos schon angeschaut. Was du meinst ist doch mit einer Anfrage direkt mehrere Streams an zu fragen oder?
Combined streams are accessed at /stream?streams=<streamName1>/<streamName2>/<streamName3>

Das ist ja eigentlich auch das was ich meine, entweder ich muss circa 2500 Streams auf diese Weise gleichzeit anfragen, sagen wir wenn das irgendwie auch moeglich waere, wie koennte ich dann anhand von einer Websocket Verbindung wissen wenn irgendwo fuer eine Crypto Currency der Streams aufhoert, ich habe ja dann nur eine Websocket Verbindung wo ich alle Streams erhalten soll, aber aus Erfahrung weis ich das immer wieder Streams zufaellig stoppen.

Vorher habe ich das so gemacht das ich fuer jede Crypto Currency einzeln ein Stream angefragt habe, aber dann auch nur fuer die Crypto currencys welche ich gerade auch brauch, lass es mal 50 oder 100 Stueck sein, aber hier war das Problem das auch Streams immer wieder zufaellig stoppen und ich nachher aber nicht mehr mit einer "ReadState" variable pruefen kann welcher Streams noch laeuft.

Die einzige logische Loesung die ich hier mir vorstellen koennte, waere circa 2500 Websockets vor zu bereiten im Programmcode dann koennte man nachher auch fuer jede Verbindung mit "ReadyState" ueberpruefen ob der Stream noch laeuft, aber das waere halt vom Programmieren etwas aufwendig.

Wie siehst du das den, wie kann man fuer circa 500 Crypto Currencys die ganzen verschiedenen Streams anfragen, wuerdest du die alle in so eine Combined streams Anfrage schreiben?
 
Nein?!

Ich schreibe es nochmal: "Subscribe to a stream".

1639565958452.png


Damit kannst du dynamisch in einem einzigen WebSocket die Streams hinzufügen und entfernen.
 
  • Gefällt mir
Reaktionen: BTCStorage und JP-M
Das hoert sich gut an, so muss das normal auch sein. Ich muss dann am besten irgendwann kucken wie man das in Javascript schreibt mit dem dynamisch hinzufuegen, zur Zeit benutze ich die normale Kline API mit HTTP Request, aber wenn ich irgendwann wieder mit Websockets probieren will das zu bauen, weis ich ja schon mal das man sowas dynamisch machen kann.

Bei meinen letzten Tests war ich sehr unzufrieden mit den Websockets und ich habe da schon einige Tage getestet, aber es ist auch das erste mal das ich mit Websocket etwas probiere zu bauen, daher fehlt mir natuerlich auch noch viel Erfahrung.

Aber mal eine Frage noch, wenn du jetzt Beispielweise eine Websocket Verbindung offen hast und 50 - 100 Crypto Currencys hinzugefuegt hast, wie willst du ueberpruefen koennen ob du fuer die alle auch Daten empfaengst? Du hast ja wahrscheinlich dann nur eine Moeglichkeit die "ReadyState" Variable von der offenen Websocket Verbindung abfragen und wenn diese dir sagt das die Verbindung ist offen, kannst du aber nicht wissen wenn irgendwo fuer eine Crypto Currency keine Daten mehr gesendet werden oder?

Ich meine das kommt ab und zu vor das fuer manche Currencys keine Streams mehr laufen ohne das man es abfragen kann, vielleicht kannst du nachvollziehen was ich meine. Wenn man aber Luecken in den Candelstickcharts vermeiden will ist es schon wichtig das die Streams am laufen sind und das man eine neue Verbindung macht wenn ein Streams gestopt hat.

Bei HTTP Request ist das bisjen einfacher, wenn man da keine Daten zurueck bekommt sieht man es ja direkt, bei den Websockets bin ich noch nicht so erfahren und wollte deswegen gerne mit Leuten die sich auskennen dadrueber diskutieren.
 
Wenn aus heiterem Himmel für einzelne Währungen keine Daten mehr kommen, obwohl die Verbindung noch steht, dann ist das ein Bug in der API, die du melden solltest.

Falls du das selbst handlen willst, kannst du ja einfach speichern, wann du zuletzt für Währung X empfangen hast und wenn zu lange her neu subscriben.
 
Mit Bugs melden, kannst du dir bestimmt vorstellen kommt man nicht schnell voran, es kann ja lange dauern bis dort jemand was aendert, aber es ist natuerlich immer eine gute Sache Bugs zu melden.

Die Idee mit Zeit vom letzten empfangenen Stream zu speichern und ueberpruefen hatte ich auch, aber mein Aufbau war anscheinend nicht so gut. Ich hatte eine Konstante Names "ws" damit habe ich immer wieder fuer alle verschiedenen Crypto Currencys eine Verbindungsanfrage gesendet und nachher als ich sah das einige Streams am laufen waren aber auch einige gestoppt hatten, konnte ich nicht mehr heraus finden welche Streams jetzt noch laufen oder nicht, weil irgendwie alle die gleiche "ws" Konstante benutzen und auch die Anfrage fuer ein neuen Stream hat nicht immer so gut funktioniert, es war alles bisjen undurchschaubar. Aber das lagbestimmt auch daran das ich Websockets noch nicht gut genug gelernt habe.

Das Beispiel von dir mit dynamischen Hinzufuegen und nur ein Websocket, werde ich bestimmt mal irgendwann probieren, zur Zeit werde ich aber die einfachen HTTP Request benutzen.
 
Der Text zwischen den Zeilen kam wahrscheinlich nicht richtig rüber. Die Wahrscheinlichkeit, dass in dem basis und zeitgleich wichtigsten Feature der API ein derartig grober Bug ist, ist wohl sehr nahe 0.
Oder anders ausgedrückt: Der Fehler liegt in deinem Code.
 
  • Gefällt mir
Reaktionen: BTCStorage
Die Annahme ist natuerlich berechtigt, da ich mit Websockets erst neu angefangen hatte und es ist jetzt schon paar Wochen her wo ich diese Test gemacht habe, aber ich kann mir vorstellen es in Zukunft nohcmal auf zu bauen und zu probieren und mein genauen code zu zeigen, vielleicht hat ja dann jemand auch Lust sich das kurz an zu schauen. Eigentlich hatte ich von Websockets schon gute Funktion erwartet und wahrscheinlich hat mir die Erfahrung gefehlt und mein Code war nicht gut aufgebaut.
 
BTCStorage schrieb:
Ich hatte eine Konstante Names "ws" damit habe ich immer wieder fuer alle verschiedenen Crypto Currencys eine Verbindungsanfrage gesendet und nachher als ich sah das einige Streams am laufen waren aber auch einige gestoppt hatten, konnte ich nicht mehr heraus finden welche Streams jetzt noch laufen oder nicht, weil irgendwie alle die gleiche "ws" Konstante benutzen und auch die Anfrage fuer ein neuen Stream hat nicht immer so gut funktioniert, es war alles bisjen undurchschaubar.
Das klingt, als hast du was beim Capture des Contexts für den Callback vereiert. Hast du alles in einer Schleife aufgerufen? Siehe https://developer.mozilla.org/en-US...s#creating_closures_in_loops_a_common_mistake
 
Ich hatte bestimmt ein bloeden Fehler gemacht, meiner Meinung nach haette man immer eine eigene neue "ws" Konstante erstellen muessen mit unterschiedlichen Namen fuer jede Crypto Currency, aber da es so viele Crypto Currencys gibt sah das fuer mich auch nicht als gute Loesung aus.

Eine andere Idee die ich hatte waere gewesen eine Art Array in welcher ws Konstanten gepseichert werden, nur die welche man benutzt, aber da bin ich auch nicht dazu gekommen, da fehlte mir die Erfahrung das auf zu bauen.

Ich werde jetzt erst mal die normalen HTTP Request zur API benutzen, aber falls ich mein Programm irgendwann nochmal verbessern will kann ich mir vorstellen wieder mit Websockets zu probieren, beim naechsten mal werde ich ja zumindest etwas mehr Ideen haben und auch nochmal nachfragen, finde ich schoen das hier Leute auch mithelfen beim lernen.
 
Zurück
Oben