Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: doom 17. 04. 2018, 20:03:59
-
Ahoj, resili jste nekdo long-polling v jave, idealne v springu? Chtel bych jsem se poradit jak to resit bez zbytecneho zatizeni vlaken. Predpokladejme ze se serverem komunikuji dvaja user-i, ak posle prvy user request se zadosti o nove data, vlakno s requestom sa hodi do smycky, kde bude kontrolovat nejakej zdroj, rekneme ze cache namisto db. Jestlize druhej user posle nejake nova data na server, objevi se v cache, kde ich ziska prvy user, a vrati je v response. Tenhle pristup funguje, zkousel jsem to implementovat. No co ak je tych userov vic, rekneme 500, 1000, 10000? Bude porad tenhle pristup s pausovanim vlaken vhodnej? Pozeral jsem aka komunikace probiha v messengeri od fb, tam se taky vyuziva zrejme long-polling, a ty requesty se drzi na servru nekdy i pres 2 minuty, a tych userov maju miliardy.
S kolegami vyvijime takovou aplikaci ktorej soucasti je take chat. Websocketom se zatim chceme vyhnout, a implementovat to cez LP. Proto bych poprosil odpovedi k teme, vime ze to jde i jinac, lenze ne vsetchni prohlizece to podporuji, a potrebujeme aby ta aplikace bezala i na starsich prohlizecich, mob. telefonech atd. Vopred dekuji za rady.
-
Proč se chcete vyhnout websoketum?
-
Proč se chcete vyhnout websoketum?
Posledni veta pred podekovanim :) taky je vraj long polling snazsi na implementaci. Nespecializujeme se komunikacni protokoly, proto pro nasi vyuziti je uplne postacijici LP, nejaka odozva < 5 sekund je uplne ok.
-
Spring podporuje asynchronní zpracování HTTP požadavků, takže nemusíte vytvářet desetitisíce vláken a řešit nějaké pauzování. Mimochodem Spring podporuje i WebSockety se SockJS fallbackem. Nevymýšlel bych kolo, zejména když už tam máte Spring a síťová komunikace není váš core business, a použil bych to, co je ve Springu už dostupné.
-
Spring podporuje asynchronní zpracování HTTP požadavků, takže nemusíte vytvářet desetitisíce vláken a řešit nějaké pauzování. Mimochodem Spring podporuje i WebSockety se SockJS fallbackem. Nevymýšlel bych kolo, zejména když už tam máte Spring a síťová komunikace není váš core business, a použil bych to, co je ve Springu už dostupné.
Aynchronni zpracovani v springu rozhodne pouzijem. Ale jak udrzat request klienta nazivu bez pauznuti vlakna nebo spusteni smycky ve vlakne ktora by kontrolovala nove data?
-
Právě přes asynchronous request: https://nickebbitt.github.io/blog/2017/03/22/async-web-service-using-completable-future
A místo cyklu stačí vrátit CompletableFuture a naplánovat polling přes ScheduledExecutorService: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html#schedule(java.lang.Runnable,%20long,%20java.util.concurrent.TimeUnit) , s retry, když se nepovede (není výsledek) nebo failure při timeout.
DeferredResult je další možnost, který dokonce timeout přímo podporuje. Místo polling se dá interně použít třeba messaging, aby se zbytečně nezatěžoval ani server.
-
Aynchronni zpracovani v springu rozhodne pouzijem. Ale jak udrzat request klienta nazivu bez pauznuti vlakna nebo spusteni smycky ve vlakne ktora by kontrolovala nove data?
Proč to chcete řešit sám a nepoužijete to, co už je ve Springu hotové?
Tady máte průvodce aplikací založené na WebSocket: Using WebSocket to build an interactive web application (https://spring.io/guides/gs/messaging-stomp-websocket/). Myslím, že z toho můžete vyjít a nemusíte vymýšlet vlastní protokol a pokoušet se vlamovat do nižších vrstev, pauzovat vlákna a bůhví co dalšího.
-
Aynchronni zpracovani v springu rozhodne pouzijem. Ale jak udrzat request klienta nazivu bez pauznuti vlakna nebo spusteni smycky ve vlakne ktora by kontrolovala nove data?
Proč to chcete řešit sám a nepoužijete to, co už je ve Springu hotové?
Tady máte průvodce aplikací založené na WebSocket: Using WebSocket to build an interactive web application (https://spring.io/guides/gs/messaging-stomp-websocket/). Myslím, že z toho můžete vyjít a nemusíte vymýšlet vlastní protokol a pokoušet se vlamovat do nižších vrstev, pauzovat vlákna a bůhví co dalšího.
uz se mne na to ptal David1234, pokud by to pres LP bylo moc komplikovane zvazime websockety jako dalsi variantu
-
Právě přes asynchronous request: https://nickebbitt.github.io/blog/2017/03/22/async-web-service-using-completable-future
A místo cyklu stačí vrátit CompletableFuture a naplánovat polling přes ScheduledExecutorService: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html#schedule(java.lang.Runnable,%20long,%20java.util.concurrent.TimeUnit) , s retry, když se nepovede (není výsledek) nebo failure při timeout.
DeferredResult je další možnost, který dokonce timeout přímo podporuje. Místo polling se dá interně použít třeba messaging, aby se zbytečně nezatěžoval ani server.
uz jsme nastrelili projekt a prave tam vyuzivame CompletableFuture<XXX> ako navratovy typ asynchronni metody, metoda je oanotovana @Async. Kazdopadne z toho vznika dalsi otazka, jakym zpusobem pak v tej metode kontrolovat nova data, spominal jste messaging. Ten neznam tak se na nej podivam, ale pokud by to melo byt bez nej, co odporucite?
-
Právě přes asynchronous request: https://nickebbitt.github.io/blog/2017/03/22/async-web-service-using-completable-future
A místo cyklu stačí vrátit CompletableFuture a naplánovat polling přes ScheduledExecutorService: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html#schedule(java.lang.Runnable,%20long,%20java.util.concurrent.TimeUnit) , s retry, když se nepovede (není výsledek) nebo failure při timeout.
DeferredResult je další možnost, který dokonce timeout přímo podporuje. Místo polling se dá interně použít třeba messaging, aby se zbytečně nezatěžoval ani server.
K tomu scheludingu ...
Notice that the methods to be scheduled must have void returns and must not expect any arguments
Potrebujeme metode predat nejakej argument na zaklade ktereho ma rozpoznat nova data pro daneho uzivatele, cize to se asi pouzit neda.
-
K tomu scheludingu ...
Notice that the methods to be scheduled must have void returns and must not expect any arguments
Potrebujeme metode predat nejakej argument na zaklade ktereho ma rozpoznat nova data pro daneho uzivatele, cize to se asi pouzit neda.
Tak metoda (Runnable) má nějaký closure context, případně může mít instance variables. Zjednodušený example přes polling (poznámky o konstantách, špatných parametrech a jménech anotací prosím do /dev/null):
CompletableFuture<Message> notifyMessages(@SessionParam("username") String username) {
CompletableFuture<Message> result = new CompletableFuture<>();
long timeoutTimestamp = System.currentTimeMillis()+30000;
Runnable checker = () -> {
List<Message> messages = messageStore.loadMessages(username);
if (messages.isEmpty()) {
long nextSchedule = System.currentTimeMillis()+10000;
if (nextSchedule >= timeoutTimestamp) {
result.completeExceptionaly(new TimeoutException());
}
else {
executor.schedule(checker, 10000);
}
}
else {
result.complete(messages);
}
}
executor.schedule(checker, 10000);
return result;
}
U messaging by se musel nastavit listener na message, který by zkompletoval future podle filtrovaného a zaregistrovaného username.
-
Tak metoda (Runnable) má nějaký closure context, případně může mít instance variables. Zjednodušený example přes polling (poznámky o konstantách, špatných parametrech a jménech anotací prosím do /dev/null):
Diki moc, zitra to zkusim. Nejdu ti vytknout anotace ani parametre, jenom si nejsem jisty jesli muze pouzit sam sebe.
-
CompletableFuture<List<Message>> notifyMessages(String username) {
CompletableFuture<List<Message>> result = new CompletableFuture<>();
long timeoutTimestamp = System.currentTimeMillis()+60000;
new Runnable() {
Runnable y = this::run;
@Override
public void run() {
List<Message> messages = messageStore.loadMessages(username);
if (messages.isEmpty()) {
long nextSchedule = System.currentTimeMillis()+10000;
if (nextSchedule >= timeoutTimestamp) {
result.completeExceptionally((new TimeoutException()));
}
else {
executor.schedule(y, new Date());
}
}
else {
result.complete(messages);
}
}
};
return result;
}
Upravil sem to takhle no pri debugu se funkce hitne, ale do runnable to nepadne, a vrati to porad 503. Ta povodni implementace mi nefungovala, kompilatoru se nelibilo ze vola runnable samo sebe.
-
A co použít reaktivní web framework, který je nově součástí Springu (založený na Project Reactor)?
https://www.youtube.com/watch?v=GlvyHIqT3K4
-
Jak jsi sám napsa, jde i i jinak. Pokud bych chtěl obsloužit desetitisíce uživatelů, tak bych použil epoll místo vláken a C++ místo Javy, ideálně jako plugin do Nginx. Ale když už to musí v Javě, tak by snad šlo něco udělat s java.nio a případně netty serverem.
-
Jak jsi sám napsa, jde i i jinak. Pokud bych chtěl obsloužit desetitisíce uživatelů, tak bych použil epoll místo vláken a C++ místo Javy, ideálně jako plugin do Nginx. Ale když už to musí v Javě, tak by snad šlo něco udělat s java.nio a případně netty serverem.
Těžko to bude psát v C++ nebo pod Netty někdo, kdo má problém rozchodit příklad z příručky Springu. Právě proto existuje taková spousta hotových knihoven a frameworků, aby se každý mohl věnovat svému core businessu a k implementaci nějaké okrajové funkce mohl použít něco, co už je hotové. Kdyby to tazatel potřeboval nějak moc optimalizovat, asi by se takhle neptal ve fóru (resp. by mu to nijak nepomohlo). Tohle má být zřejmě nějaká okrajová funkcionalita, takže je nejlepší poskládat to z už hotových komponent a případnou optimalizaci řešit teprve tehdy, až by se zjistilo, že je s výkonem problém.
-
Jak jsi sám napsa, jde i i jinak. Pokud bych chtěl obsloužit desetitisíce uživatelů, tak bych použil epoll místo vláken a C++ místo Javy, ideálně jako plugin do Nginx. Ale když už to musí v Javě, tak by snad šlo něco udělat s java.nio a případně netty serverem.
Těžko to bude psát v C++ nebo pod Netty někdo, kdo má problém rozchodit příklad z příručky Springu. Právě proto existuje taková spousta hotových knihoven a frameworků, aby se každý mohl věnovat svému core businessu a k implementaci nějaké okrajové funkce mohl použít něco, co už je hotové. Kdyby to tazatel potřeboval nějak moc optimalizovat, asi by se takhle neptal ve fóru (resp. by mu to nijak nepomohlo). Tohle má být zřejmě nějaká okrajová funkcionalita, takže je nejlepší poskládat to z už hotových komponent a případnou optimalizaci řešit teprve tehdy, až by se zjistilo, že je s výkonem problém.
Pravdepodobne nebude tu appku vyuzivat v jeden moment vic nez 100 prihlasenych userov. Tie tisice jsem uvedl jako moznej priklad, jestli to jde udelat tak, aby to zvladlo i takovej napor. Ze zacatku to ale urcite nehrozi.