Přepsání serveru v Javě

Serverfreak

Přepsání serveru v Javě
« kdy: 25. 05. 2017, 10:06:56 »
Může mi někdo prosím poradit, jakým způsobem přepsat server? Kontext: mám webovou službu, rozhraní je přes JSON, server je napsaný v Javě (přímo nad standardní knihovnou, žádný framework), kód je malý (nějaké základní zpracování dat, IPC k jedné lokální komponentě a přístup do databáze), ale požadavků není málo (tisíce za minutu) a současná verze je dost náročná na paměť a občas se zasekává (asi GC). Koukal jsem na node.js, ale jednovláknovost se mi moc nepozdává (server má ARM64 s 16 vlákny). Mám na přepsání čas a chuť experimentovat, jen si nejsem jistý, jakým směrem se vydat (mám prototyp v čistém C nad syscally, ale nedal bych ruku do ohně za spolehlivost, je to jen proof of concept).


v

Re:Přepsání serveru v Javě
« Odpověď #1 kdy: 25. 05. 2017, 10:15:38 »
go, erlang, haskell
lightweight procesy, komunikace mezi nimi, a v případě haskellu STM a typový systém (a aeson)

Re:Přepsání serveru v Javě
« Odpověď #2 kdy: 25. 05. 2017, 10:40:56 »
Začněte tím, že zjistíte, co způsobuje ty problémy. A pak tu danou věc buď opravte (pokud je to chyba), nebo vymyslete jiný způsob řešení (pokud je to věc návrhu). Pokud jenom současnou aplikaci přepíšete do jiného jazyka, skončíte (v lepším případě) s aplikací, která bude mít úplně ten samý problém.

Pokud to chcete přepisovat, můžete použít např. Spring (a Spring Boot), kde už máte podporu pro webové služby, JSON i přístup k databázím, IPC záleží na implementaci. Nebudete se pak muset věnovat infrastruktuře aplikace a budete se moci soustředit na její jádro. Případně, pokud byste chtěl optimalizovat síťovou vrstvu, doporučuju použít framework Netty, který je postavený nad NIO a odstíní vás od komplikací síťové komunikace.

To, že to máte napsané přímo nad standardní knihovnou a nepoužíváte žádný framework ani knihovny, je podle mne největší slabina, protože pak se vysilujete na řešení něčeho, co už dávno před vámi vyřešil někdo jiný (a nejspíš lépe).

Pokud si jenom chcete vyzkoušet přepsat to do něčeho jiného a je vám jedno, do čeho, zaměřil bych se na jazyky, které míří tímhle směrem, jak napsal „v“, do výčtu bych přidal třeba ještě Rust. Node.js na to podle mne není vhodný, ten je vhodný pro prototypování nebo izomorfní aplikace, ale není orientován na výkon pod zátěží. V čistém C bych to nepsal – to byste se opět vysiloval nad něčím, co je už dávno vyřešené. A než to řešit nějakým frameworkem v C, spíš bych zvolil jiný jazyk, protože tím získáte podporu nejen ze strany knihovny, ale i ze strany jazyka a překladače.

gll

Re:Přepsání serveru v Javě
« Odpověď #3 kdy: 25. 05. 2017, 10:49:04 »
Jste si jistý, že úzkým hrdlem je aplikace? Většinou bývá problém v databázi. Tisíce požadavků za minutu je nic.

Nejdřív bych se podíval na konfiguraci databáze.

Pokud je problém v aplikaci:

Jestli ty požadavky většinu času čekají na odpověď té lokální komponenty nebo databáze, zkusil bych navýšit počet souběžně zpracovávaných požadavků. V nejhorším případě můžete zkusit použít nějaký neblokující framework. Na jazyku nezáleží.

Další možnost je realizovat pomalá čekání v nějakém task queue a výsledek posílat klientovi pomocí websocketu. Nemusíte přepisovat celou aplikaci, stačí jen dlouho čekající části přesunout do task queue.

Přepsání celé aplikace bývá nejhorší možné řešení. Zrychlení se dá většinou docílit malou úpravou stávající aplikace.

Kdybyste chtěl přesto použít nodejs. Horizontální škálování nodejs http aplikací s nginx je triviální.

gll

Re:Přepsání serveru v Javě
« Odpověď #4 kdy: 25. 05. 2017, 10:54:25 »
go, erlang, haskell
lightweight procesy, komunikace mezi nimi, a v případě haskellu STM a typový systém (a aeson)

To je nejspíš overkill. S největší pravděpodobností je jeho problém řešitelný nějakým malým fixem. Na jeho místě bych se snažil zachovat maximální množství stávajícího kódu.


v

Re:Přepsání serveru v Javě
« Odpověď #5 kdy: 25. 05. 2017, 10:57:54 »
go, erlang, haskell
lightweight procesy, komunikace mezi nimi, a v případě haskellu STM a typový systém (a aeson)

To je nejspíš overkill. S největší pravděpodobností je jeho problém řešitelný nějakým malým fixem. Na jeho místě bych se snažil zachovat maximální množství stávajícího kódu.
já jsem vycházel z toho "Mám na přepsání čas a chuť " :)

Serverfreak

Re:Přepsání serveru v Javě
« Odpověď #6 kdy: 25. 05. 2017, 11:05:58 »
Začněte tím, že zjistíte, co způsobuje ty problémy. A pak tu danou věc buď opravte (pokud je to chyba), nebo vymyslete jiný způsob řešení (pokud je to věc návrhu). Pokud jenom současnou aplikaci přepíšete do jiného jazyka, skončíte (v lepším případě) s aplikací, která bude mít úplně ten samý problém.

Pokud to chcete přepisovat, můžete použít např. Spring (a Spring Boot), kde už máte podporu pro webové služby, JSON i přístup k databázím, IPC záleží na implementaci. Nebudete se pak muset věnovat infrastruktuře aplikace a budete se moci soustředit na její jádro. Případně, pokud byste chtěl optimalizovat síťovou vrstvu, doporučuju použít framework Netty, který je postavený nad NIO a odstíní vás od komplikací síťové komunikace.

To, že to máte napsané přímo nad standardní knihovnou a nepoužíváte žádný framework ani knihovny, je podle mne největší slabina, protože pak se vysilujete na řešení něčeho, co už dávno před vámi vyřešil někdo jiný (a nejspíš lépe).

Pokud si jenom chcete vyzkoušet přepsat to do něčeho jiného a je vám jedno, do čeho, zaměřil bych se na jazyky, které míří tímhle směrem, jak napsal „v“, do výčtu bych přidal třeba ještě Rust. Node.js na to podle mne není vhodný, ten je vhodný pro prototypování nebo izomorfní aplikace, ale není orientován na výkon pod zátěží. V čistém C bych to nepsal – to byste se opět vysiloval nad něčím, co je už dávno vyřešené. A než to řešit nějakým frameworkem v C, spíš bych zvolil jiný jazyk, protože tím získáte podporu nejen ze strany knihovny, ale i ze strany jazyka a překladače.
Děkuji. Prvotní "chyba" je v návrhu, protože každý požadavek se řeší v samostatném vlákně, ale stejně bych čekal, že GC si s tím poradí lépe. Jinak problém asi taky může být, že implementace SSL nad ARM je relativně pomalá.

To přepsání do C bylo jen cvičení, původně jsem chtěl libevent, ale nemá dobré reference. Myšlenka v pozadí je opustit Javu, nemyslím, že tady přináší nějaké výhody. Dík za tip na Rust, to vypadá hodně dobře, určitě s tím budu experimentovat.

Serverfreak

Re:Přepsání serveru v Javě
« Odpověď #7 kdy: 25. 05. 2017, 11:07:57 »
go, erlang, haskell
lightweight procesy, komunikace mezi nimi, a v případě haskellu STM a typový systém (a aeson)

To je nejspíš overkill. S největší pravděpodobností je jeho problém řešitelný nějakým malým fixem. Na jeho místě bych se snažil zachovat maximální množství stávajícího kódu.
já jsem vycházel z toho "Mám na přepsání čas a chuť " :)
Ano, chci experimentovat :) Dík za tipy, Haskell je na mě v tomto případě trochu moc FP, ale na Go se určitě podívám (a porovná s tím Rustem).

v

Re:Přepsání serveru v Javě
« Odpověď #8 kdy: 25. 05. 2017, 11:26:18 »
go, erlang, haskell
lightweight procesy, komunikace mezi nimi, a v případě haskellu STM a typový systém (a aeson)

To je nejspíš overkill. S největší pravděpodobností je jeho problém řešitelný nějakým malým fixem. Na jeho místě bych se snažil zachovat maximální množství stávajícího kódu.
já jsem vycházel z toho "Mám na přepsání čas a chuť " :)
Ano, chci experimentovat :) Dík za tipy, Haskell je na mě v tomto případě trochu moc FP, ale na Go se určitě podívám (a porovná s tím Rustem).
o Rustu toho moc nevím, ale nevypadá, že by měl lightweight procesy (třeba mě někdo opraví), to by pro mě byl velký nedostatek

dustin

Re:Přepsání serveru v Javě
« Odpověď #9 kdy: 25. 05. 2017, 11:34:52 »
Souhlasím, že nejdříve je potřeba zjistit příčiny stávajících problémů a až dle toho se rozhodnout, co s tím. Příklad - záseky všech odpovědí mohou místo GC způsobovat třeba zámky v DB v kombinaci s nějakým delším/neoptimálním dotazem. Nebo něco úplně jiného, to ukáže jen analýza.

Re:Přepsání serveru v Javě
« Odpověď #10 kdy: 25. 05. 2017, 11:43:34 »
Prvotní "chyba" je v návrhu, protože každý požadavek se řeší v samostatném vlákně
To by vyřešilo použití běžného serveru nebo frameworku, které mají pool vláken, která zpracovávají spojení. Případně, pokud zpracování tráví hodně času nějakým čekáním, můžete využít asynchronní zpracování – nativně s Netty, podporu pro to má i Spring.

ale stejně bych čekal, že GC si s tím poradí lépe
Jste si jistý, že to souvisí s GC? Nebylo by pak řešením použít jiný GC?

Jinak problém asi taky může být, že implementace SSL nad ARM je relativně pomalá.
To je to, co jsem psal na začátku – nejprve zjistit, v čem je problém. Jestli je to velké množství vláken, GC nebo pomalé SSL jsou diametrálně odlišné věci.

Myšlenka v pozadí je opustit Javu, nemyslím, že tady přináší nějaké výhody.
Taky nepřináší žádné nevýhody. A výhodou je podle mne velké množství knihoven a frameworků, které můžete jenom vzít a použít – a můžete se soustředit na to, co je specifické pro vaši aplikaci.

gll

Re:Přepsání serveru v Javě
« Odpověď #11 kdy: 25. 05. 2017, 11:49:06 »
Jestli ta vlákna skutečně něco dělají, tak Erlang ani Node.js nepomohou. Výpočetně náročné úlohy musíte zpracovávat v nějakém poolu s omezeným počtem vláken.

v

Re:Přepsání serveru v Javě
« Odpověď #12 kdy: 25. 05. 2017, 11:52:09 »
Jestli ta vlákna skutečně něco dělají, tak Erlang ani Node.js nepomohou. Výpočetně náročné úlohy musíte zpracovávat v nějakém poolu s omezeným počtem vláken.
tak zrovna erlang by takto pomohl, nebo go, nebo haskell

Honza

Re:Přepsání serveru v Javě
« Odpověď #13 kdy: 25. 05. 2017, 11:59:41 »
Prvotní "chyba" je v návrhu, protože každý požadavek se řeší v samostatném vlákně
Typická chyba Javistů...

Výpočetně náročné úlohy musíte zpracovávat v nějakém poolu s omezeným počtem vláken.
+1

gll

Re:Přepsání serveru v Javě
« Odpověď #14 kdy: 25. 05. 2017, 12:00:32 »
Jestli ta vlákna skutečně něco dělají, tak Erlang ani Node.js nepomohou. Výpočetně náročné úlohy musíte zpracovávat v nějakém poolu s omezeným počtem vláken.
tak zrovna erlang by takto pomohl, nebo go, nebo haskell

Erlang řeší problém velkého množství čekajících vláken. Pokud každé vlákno zpracovává například velké množství dat, tak Erlang ničemu nepomůže. Naopak to bude pomalejší.