Parallelisierung von Severanfragen?

C

Conax

Mitglied
Vielen Dank erstmal an Alle die mir letztes mal geholfen haben. Die gute Nachricht ist das Programm macht im Prinzip was es soll - es holt mir von den verschiedenen Cryptobörsen den Betrag für das günstigste Angebot. Das Problem ist aber die Performance - Anfragen an die selbe Börse über unterschiedliche Coins werden jedesmal einzeln gestellt(sprich erst Verbindungsaufbau Anfrage z.B. bei anycoindirect Preis für Bitcoin dann wartet das Programm auf Feedback dann hole ich die Daten für Ethereum usw. usv. ) d.h. entweder müsste ich eine große Anfrage an den Server stellen statt jedesmall dieses Frage-Antwort Spiel oder wenn das nicht möglich sein sollte erstmal lauter kleine Anfragen parallel versenden und wenn dann die Antworten kommen diese entsprechend zuordnen. Was vielleicht auch einen Performancegewinn verspricht sind verschiedene Threads sprich für jede Kryptobörse einen Thread. Das sind zumindest die Gedankenspiele die ich mir gemacht habe.

Gedankenspiele sind das eine aber wie man so etwas konkret umsetzt ja wieder etwas völlig anderes weswegen ich wie jeder erstmal gegoogelt habe um mir Anreize zu holen:
https://docs.oracle.com/javase/tutorial/networking/datagrams/broadcasting.html
https://docs.oracle.com/javase/tutorial/collections/streams/parallelism.html
https://www.foreach.be/blog/parallel-and-asynchronous-programming-in-java-8

Hier mal der Code wie ich bisher die Daten beziehe als Parser habe ich diesen hier eingesetzt:
https://github.com/fangyidong/json-simple

Code:
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

// für Bitcoin
            URL url1 = new URL("https", "anycoindirect.eu",
                    "/api/public/buyprices?CoinCode=BTC&FiatCode=EUR&CoinAmount=1");

            // für Ethereum
            URL url2 = new URL("https", "anycoindirect.eu",
                    "/api/public/buyprices?CoinCode=ETH&FiatCode=EUR&CoinAmount=1");

            // für Litecoin
            URL url3 = new URL("https", "anycoindirect.eu",
                    "/api/public/buyprices?CoinCode=LTC&FiatCode=EUR&CoinAmount=1");

try (BufferedReader in = new BufferedReader(new InputStreamReader(url1.openStream())))
            {
                String inputLine;

               
                
                System.out.println("/***** File content Bitcoin *****/n");
                while ((inputLine = in.readLine()) != null)
                {
                    // System.out.println(inputLine);

                    JSONParser parser = new JSONParser();
                    JSONObject obj2 = (JSONObject) parser.parse(inputLine);

                    
                    JSONArray lang = (JSONArray) obj2.get("Data");
                    // @SuppressWarnings("rawtypes")
                    Iterator i = lang.iterator();

                    while (i.hasNext())
                    {
                        JSONObject innerObj = (JSONObject) i.next();
                       
                        System.out.println(innerObj.get("FiatAmount"));
                        anycoinbtc = (double) innerObj.get("FiatAmount");
                        break;
                    }
                }
            } catch (ParseException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException ioe)
            {
                ioe.printStackTrace(System.err);
            }

            try (BufferedReader in = new BufferedReader(new InputStreamReader(url2.openStream())))
            {
                String inputLine;

                
                System.out.println("/***** File content Ethereum *****/n");
                while ((inputLine = in.readLine()) != null)
                {
                    // System.out.println(inputLine);

                    JSONParser parser = new JSONParser();
                    JSONObject obj2 = (JSONObject) parser.parse(inputLine);

                    JSONArray lang = (JSONArray) obj2.get("Data");
                    // @SuppressWarnings("rawtypes")
                    Iterator i = lang.iterator();

                    while (i.hasNext())
                    {
                        JSONObject innerObj = (JSONObject) i.next();
                        
                        System.out.println(innerObj.get("FiatAmount"));
                        anycoineth = (double) innerObj.get("FiatAmount");
                        break;
                    }
                }
            } catch (ParseException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException ioe)
            {
                ioe.printStackTrace(System.err);
            }

            try (BufferedReader in = new BufferedReader(new InputStreamReader(url3.openStream())))
            {
                String inputLine;

               
                System.out.println("/***** File content Litecoin *****/n");
                while ((inputLine = in.readLine()) != null)
                {
                    // System.out.println(inputLine);

                    JSONParser parser = new JSONParser();
                    JSONObject obj2 = (JSONObject) parser.parse(inputLine);

                    JSONArray lang = (JSONArray) obj2.get("Data");
                    // @SuppressWarnings("rawtypes")
                    Iterator i = lang.iterator();

                    while (i.hasNext())
                    {
                        JSONObject innerObj = (JSONObject) i.next();
                        
                        System.out.println(innerObj.get("FiatAmount"));
                        anycoinltc = (double) innerObj.get("FiatAmount");
                        break;
                    }
                }
            } catch (ParseException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException ioe)
            {
                ioe.printStackTrace(System.err);
            }

Hat jemand Erfahrung wie ich besagtes Performanceproblem lösen kann?
 
Thallius

Thallius

Top Contributor
Bei den einzelnen Seiten nach einer passenden API suchen (damit zB alle Werte auf einmal angefragt werden können) und zusätzlich parallelisieren, am passendsten dürfte da ExecutorService sein

Ich denke nicht dass eine Seite ihre Daten als quasi komplett Dump kostenlos in einer API zur Verfügung stellt. Programme wie sie der TO schreibt sind sicher nicht im Interesse der Seitenbetreiber.
 
mrBrown

mrBrown

Super-Moderator
Mitarbeiter
Ich denke nicht dass eine Seite ihre Daten als quasi komplett Dump kostenlos in einer API zur Verfügung stellt. Programme wie sie der TO schreibt sind sicher nicht im Interesse der Seitenbetreiber.
Warum sollte eine API für Einzeldaten angeboten werden, aber eine die mehrere Daten zusammenfasst (und damit auch den Server massiv entlastet) „nicht im Interesse der Seitenbetreiber“ sein?
 
Thallius

Thallius

Top Contributor
Warum sollte eine API für Einzeldaten angeboten werden, aber eine die mehrere Daten zusammenfasst (und damit auch den Server massiv entlastet) „nicht im Interesse der Seitenbetreiber“ sein?

Weil bei den ganzen API auch nur eine maximale Anzahl Anfragen erlaubt ist. Die sind ganz bewusst nicht dafür gemacht was der TO will
 
mrBrown

mrBrown

Super-Moderator
Mitarbeiter
Weil bei den ganzen API auch nur eine maximale Anzahl Anfragen erlaubt ist. Die sind ganz bewusst nicht dafür gemacht was der TO will
Öffentlich dokumentierte APIs sind nicht dazu da, benutzt zu werden?

Ob begrenzt oder nicht ist zumindest völlig egal, wenn es um das Abfragen von Einzeldaten vs. Abfragen von Collections geht, das ist in beiden Fällen völlig gleichwertig umsetzbar...
 
mihe7

mihe7

Top Contributor
@mrBrown kann es sein, dass Du und @Thallius aneinander vorbei schreibt?

Technisch spielt es freilich oft kaum eine Rolle, ob Einzel- oder "Sammel"anfragen beantwortet werden. Auf der anderen Seite haben Dienstleister ein Interesse daran, dass die Leute für die Inanspruchnahme von Leistungen bezahlen.

Da ist die künstliche Verknappung des Gutes eine Möglichkeit und in diesem Zusammenhang macht es natürlich einen entscheidenden Unterschied, ob 10 Einzel- oder 10 Sammelanfragen gratis sind :)
 
X

Xyz1

Gast
Worum geht es hier in dem Thema den nochmal genau (kurz und knapp)? :) Erbitte Rekapitulation....
 
mrBrown

mrBrown

Super-Moderator
Mitarbeiter
@mrBrown kann es sein, dass Du und @Thallius aneinander vorbei schreibt?

Technisch spielt es freilich oft kaum eine Rolle, ob Einzel- oder "Sammel"anfragen beantwortet werden. Auf der anderen Seite haben Dienstleister ein Interesse daran, dass die Leute für die Inanspruchnahme von Leistungen bezahlen.

Da ist die künstliche Verknappung des Gutes eine Möglichkeit und in diesem Zusammenhang macht es natürlich einen entscheidenden Unterschied, ob 10 Einzel- oder 10 Sammelanfragen gratis sind :)
Naja, in dem Code oben wird offensichtlich eine API benutzt, der Anbieter scheint also nichts dagegen zu haben, dass die API benutzt wird.

Wenn man das begrenzt auf insgesamt 10 Anfragen macht’s natürlich ne Unterschied, aber wenn man das (was sinnvoll wäre), nicht auf die Anzahl der Anfragen sondern die Anzahl der Abgefragten Werte bezieht (eine Sammelabfrage mit 10 Werten = 10 Einzelabfragen) macht’s wieder keinen Unterschied in der Menge der Daten.

In diesem Fall ist die Dienstleistung aber auch der Handel mit „Coins“ und nicht mit Wechselkursen. Da würde ich erwarten, dass die freie Verfügbarkeit von Wechselkursen eher den Verkauf fördert bzw ihn zumindest nicht negativ beeinflusst...
 
X

Xyz1

Gast
Nein gleich drehen wir uns wieder im Kreis => keine Ahnung => du schon gar nicht => keine Ahnung usw.
Er kann natürlich das zwischen rein/raus durchaus überbrücken, aber ich bezweifle das das bei diesem Setting irgendeinen Sinn macht....
 
mihe7

mihe7

Top Contributor
Naja, in dem Code oben wird offensichtlich eine API benutzt, der Anbieter scheint also nichts dagegen zu haben, dass die API benutzt wird.
Ich habe mir deren Nutzungsbedingungen nicht angesehen. Es kann natürlich sein, dass es ihnen völlig gleich ist, wer wie oft ihrer Server nutzt.

aber wenn man das (was sinnvoll wäre), nicht auf die Anzahl der Anfragen sondern die Anzahl der Abgefragten Werte bezieht
Das ist sicher "sinnvoll" aus technischer Sicht. Wirtschaftlich will ich den Benutzer gerade keinen Komfort für lau bieten, sondern ihn dazu animieren, für Mehrwert zu bezahlen.

In diesem Fall ist die Dienstleistung aber auch der Handel mit „Coins“ und nicht mit Wechselkursen.
Die Dienstleistung besteht hier aus dem Anbieten eines (Web-)Services. Ob die Firma ansonsten mit Coins handelt oder Kühe melkt und Milch verkauft, interessiert doch nicht. Amazon war auch mal nur Buchhändler.

Dass das teilweise absurde Züge annehmen kann, ist klar: bei der Post konnte man sich früher ein Programm kaufen(!), mit diesem und einer monatlichen Nutzungsgebühr(!) man doch tatsächlich in die Lage versetzt wurde, Dienstleistungen bei der Post zu bestellen. Mehrwert: man brauchte keine Frankiermaschine mehr.
 
C

Conax

Mitglied
Also bisher beinhaltet das Programm 5 APIs von Kryptobörsen, 1 API vom Händler (anycoin direct) und 3 APIs für andere Dinge (Difficulty, block reward, Wechselkurse). Es soll ja einfach nur mal einen Überblick geben wo Coin XYZ gerade am günstigsten zu bekommen ist - früher hatte dafür der Börsenmarkler seine 5 Bildschirme an der Wand und heute gibt er ja auch das Wertpapier ein und sieht sofort wo dieses am günstigsten aktuell gehandelt wird. Außerdem ist natürlich der sog. Spread zwischen den Handelsplätzen auch sehr interessant und vor allem wodurch dieser ausgelöst wird bsp. wenn die Südkoreaner auf bithumb kaufen wie verrückt. Über manche der APIs lassen sich ja sogar Kauf- bzw. Verkaufsaufträge durchführen und jede Transaktion bringt der Handelsplattform schließlich Gebühren von daher wäre es ja unproduktiv Beschränkungen einzuführen.

Ich wüsste auch nicht warum sollte ein Händler wie anycoin direct (dies ist ja kein Marktplatz im klassischen Sinne) eine extra Gebühr verlangen um per API die "Premiumdaten" (also ein Datenpaket welches von allen Coins den aktuellen Preis enthält) frei zu geben. Ich bin ja sogar auf der Seite angemeldet aber eine Zusatzoption für spezielle API Features lässt sich auch nicht buchen.

Mein persönlicher Eindruck ist eher der das die Börsen und Händler alle über ihre API angebunden werden wollen (sonst würde man es ja erst gar nicht anbieten) aber die ganze Umsetzung aktuell noch stark in den Kinderschuhen steckt (das fängt ja mit der Doku zu den APIs schon an). Das Problem sehe ich also eher in der praktischen Herangehensweise - wie kann ich das was mir zur verfügung steht optimal nutzen? Über Philosophie, Konzept und was die Handelsplattform mit der API bezweckt können wir hier sicherlich lange mutmaßen halte ich aber für wenig zielführend.
 
mihe7

mihe7

Top Contributor
Es soll ja einfach nur mal einen Überblick geben wo Coin XYZ gerade am günstigsten zu bekommen ist

Das Ziel ist schon klar, aber genau das ist doch der Nutzen, den Du aus den Leistungen ziehst, den die Händler/Börsen anbieten: Du verwendest APIs, damit Du Dir automatisiert einen Überblick verschaffen kannst, wo Du am günstigsten an Produkt X kommst.

Schön, wenn das gratis möglich ist, selbstverständlich ist das allerdings nicht. Denn es ist schon etwas anderes als die Nutzung einer API zur Kaufabwicklung.

Das Problem sehe ich also eher in der praktischen Herangehensweise
Die hat @mrBrown doch hier schon beschrieben.
 
X

Xyz1

Gast
@mihe7 Man kann doch eigentlich nur die "Latenz" bei vielen, kleinen Anfragen zur Gegenseite überbrücken - anderes wäre unsinvoll.

(Wenn ich zum Bleistift eine "Latenz" von 10ms nach Frankfurt habe, könnte ich zum Beispiel 10 Anfragen gleichzeitig nach Frankfurt wegschicken um eben nicht 100ms sonder 10 bis 20ms nur zu brauchen. Was anschließend geschieht muss auch nochmal ausklamüsert werden!!)

Jetzt lese ich etwas mit "Bitcoin" - da stellt sich die Frage, was wann wie schnell sein soll! :rolleyes:

Es geht doch hoffentlich nicht um micro- oder nano- Trading!! :confused:
 
X

Xyz1

Gast
Ihr immer mit euren Services und Komfort (für Lau) - Die Dienstleistungsanbieter wollen doch auch nur ihrer Arbeit nachkommen.... :oops:

Das Ziel ist schon klar, aber genau das ist doch der Nutzen, den Du aus den Leistungen ziehst, den die Händler/Börsen anbieten: Du verwendest APIs, damit Du Dir automatisiert einen Überblick verschaffen kannst, wo Du am günstigsten an Produkt X kommst.

Erster Schritt wäre Dich als Roboter zu erkennen zu geben, wenn Du dann keine reliable Antwort bekommst dann weißt Du schonmal => Wahrscheinlich verboten.

in der praktischen Herangehensweise

Was möchtest du wissen? :)
 
mihe7

mihe7

Top Contributor
Man kann doch eigentlich nur die "Latenz" bei vielen, kleinen Anfragen zur Gegenseite überbrücken - anderes wäre unsinvoll.
Die Latenz ist aber gerade bei vielen kleinen Anfragen relativ hoch.

Mal praktisch:

100 Anfragen sequentiell:
Code:
Total transferred:      126589 bytes
HTML transferred:       56800 bytes
Requests per second:    9.36 [#/sec] (mean)
Time per request:       106.858 [ms] (mean)
Time per request:       106.858 [ms] (mean, across all concurrent requests)
Transfer rate:          11.57 [Kbytes/sec] received

100 Anfragen mit 4 parallelen Verbindungen:
Code:
Total transferred:      126505 bytes
HTML transferred:       56800 bytes
Requests per second:    30.22 [#/sec] (mean)
Time per request:       132.350 [ms] (mean)
Time per request:       33.088 [ms] (mean, across all concurrent requests)
Transfer rate:          37.34 [Kbytes/sec] received
 
B

Bontik

Gast
Macht es wirklich mit allen Coins, Hauptasche das Angebot ist gut oder nur die, die du willst?

Wenn du aussuchen kannst, dann fokussiere dich auf Dash. Ich muss ehrlich sein, dieser Währung ist heutzutage sehr gut und ihre Zukunft ist wirklich hell, deshalb die Empfehlung.
Ein Freund von mir hat es vor kurzem gekauft und kam sehr gut zurecht damit. Auf einer Seite (klicken) sammelte er sehr gute Infos und bekam so einen klaren Überblick. Auf diese Art konnte er sehr leicht vorankommen und jetzt profitiert er ganz gut.

Grüß!
 
D

daybyter

Aktives Mitglied
Ich hab auch meine Monate mit diesen Rest APIs gekämpft und es irgendwann aufgegeben.

Schau Dir mal die Websocket API's einiger Börsen an und evtl Xchange-Stream. Wir ham das damals aber nicht stabil ans Laufen gebracht und mussten was eigenes basteln.

Noch besser sind aber Fix (oder schnellere) Verbindungen, wo Du alles im Stream erledigst. Bastle gerade an einer Tradeapp eben dafür.
 
D

daybyter

Aktives Mitglied
Da hast Du mich irgendwie falsch verstanden. Ich hatte die Abfragen am Laufen, aber nicht in dem Tempo, welches ich gebraucht hätte. Mein Bot sollte knapp 385000 Handelswege überwachen und ich konnte einfach die Preise nicht schnell genug bekommen. Hab es dann mit Proxies versucht, aber das war nix stabiles. Deshalb der Umstieg auf Streams.
Hab übrigens sogar einen Teil meines Rest Codes in github hochgeladen.
 
D

daybyter

Aktives Mitglied
Wie kommst Du auf diese Zahlen? Meine Wege waren max 5 Schritte lang. Also 5 Multiplikationen und 5 Additionen. Aber dazu die Optimierung der gehandelten Summe, die viel Zeit braucht, wenn man es richtig macht.

Ich war irgendwann an dem Punkt, wo ich das auf der GPU rechnen wollte, aber ich konnte ausreichend unprofitable Wege schnell genug entfernen.

Das lief auf nem normalen Quadcore Desktop.

http://i.imgur.com/EgiTKPQ.png
 
X

Xyz1

Gast
Ah, dann vergiss das mit den Berechnungen wieder ich kenne den Algorithmus ja nicht
Also dauert nur das RESTfullying lange?
 
D

daybyter

Aktives Mitglied
Nein, das Problem waren die Zugriffslimitierungen der Anbieter. Da wurde teilweise der Zugriff auf 1 http Request alle 5s beschränkt.

Das ist absurd, wenn Du paar hundert Preise von denen brauchst. Also wurden Lösungen wie Proxies eingebaut und zeitweise liefen die Abfragen dann über bis zu 600 Proxies.

Aber wenn Du mal einen Streaming Bot gebaut hast, siehst DuDu, dass das alles Mist ist. Über diese Streams bekommst Du ja einerseits locker über 1000 Preise pro Sekunde und der Broker liefert Dir ja direkt die Änderungen. Du musst nicht mehr pollen, auf welchem Markt sich was tut.
 
Thallius

Thallius

Top Contributor
kapier ich alles nicht. Wozu brauchst du einen REST Server wenn du ein Frontend baust? REST ist das Backend und wenn du die Daten von fremden Servern sammelst, dann kannst du diese auch nur so sammeln wie sie dir dieser Server zur Verfügung stellt. Wenn der also nur eine Anfrage pro Sekunde pro Nutzer erlaubt und du gehst über hunderte von proxies um das zu umgehen, dann handelst du hochgradig illegal und ich würde verdammt aufpassen dass ich dabei nicht erwischt werde.
Was du jetzt genau mit Steams meinst die du jetzt benutzt erschließt sich mir auch nicht.
 
Thallius

Thallius

Top Contributor
Er meint vermutlich Reactive Streams.

Habe mir das gerade mal durchgelesen. Ist ja echt ein Witz. Da erfindet jemand etwas das Normalerweise jeder etwas intelligente Programmierer sowieso so umsetzen würde und gibt ihm einen wichtigen Namen.

Wer bitte programmiert denn bitte blockig Messages an andere devices? Egal ob es ein anderer Server oder einfach nur ein USB Stick ist. Sobald ich nicht 100% sicher sein kann, dass der messagecempfänger innerhalb von Millisekunden antwortet arbeite ich asynchron.

Da muss doch keiner für herkommen und ein „Reactive“ Design Pattern definieren und eine Reactive API schreiben....
 
mrBrown

mrBrown

Super-Moderator
Mitarbeiter
Du kanntest reactive Streams nicht, aber hälst sie für etwas was jeder Programmierer machen würde? o_O

Also entweder bist du ein unglaubliches Genie und hast in den letzten 15 Jahren unter einem Stein gelebt hat, oder ich weiß auch nicht...

(BTW: Asynchron ist nicht das gleiche wie reactive Streams...)
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
A Parallelisierung mit RMI ??? Netzwerkprogrammierung 3

Ähnliche Java Themen


Oben