Implementace long-polling v Javě (Spring)

doom

Implementace long-polling v Javě (Spring)
« kdy: 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.
« Poslední změna: 17. 04. 2018, 21:05:05 od Petr Krčmář »


David1234

Re:Implementace long-polling v Javě (Spring)
« Odpověď #1 kdy: 17. 04. 2018, 21:05:51 »
Proč se chcete vyhnout websoketum?

doom

Re:Implementace long-polling v Javě (Spring)
« Odpověď #2 kdy: 17. 04. 2018, 21:17:25 »
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.

Re:Implementace long-polling v Javě (Spring)
« Odpověď #3 kdy: 17. 04. 2018, 21:18:39 »
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é.

doom

Re:Implementace long-polling v Javě (Spring)
« Odpověď #4 kdy: 17. 04. 2018, 21:23:03 »
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?


Re:Implementace long-polling v Javě (Spring)
« Odpověď #5 kdy: 17. 04. 2018, 21:55:11 »
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.

Re:Implementace long-polling v Javě (Spring)
« Odpověď #6 kdy: 17. 04. 2018, 21:59:20 »
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. 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.

doom

Re:Implementace long-polling v Javě (Spring)
« Odpověď #7 kdy: 17. 04. 2018, 22:27:50 »
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. 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

doom

Re:Implementace long-polling v Javě (Spring)
« Odpověď #8 kdy: 17. 04. 2018, 22:30:31 »
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?

doom

Re:Implementace long-polling v Javě (Spring)
« Odpověď #9 kdy: 17. 04. 2018, 22:32:55 »
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 ...

Citace
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.

Re:Implementace long-polling v Javě (Spring)
« Odpověď #10 kdy: 17. 04. 2018, 23:35:48 »
K tomu scheludingu ...

Citace
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):

Kód: [Vybrat]
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.

doom

Re:Implementace long-polling v Javě (Spring)
« Odpověď #11 kdy: 18. 04. 2018, 00:17:15 »
Citace
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.

doom

Re:Implementace long-polling v Javě (Spring)
« Odpověď #12 kdy: 18. 04. 2018, 12:04:04 »
Kód: [Vybrat]
    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.

Natix

Re:Implementace long-polling v Javě (Spring)
« Odpověď #13 kdy: 18. 04. 2018, 17:02:33 »
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

borekz

  • ****
  • 492
    • Zobrazit profil
    • E-mail
Re:Implementace long-polling v Javě (Spring)
« Odpověď #14 kdy: 18. 04. 2018, 17:24:39 »
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.
« Poslední změna: 18. 04. 2018, 17:27:22 od borekz »