Nejlepší odpověď
Odpověď na otázku, jak je uvedena, je stejná jako rozdíl mezi „jedním „a„ many “.
Ale myslím, že to, co jste pravděpodobně opravdu mysleli, je něco podobného: jak se liší metodiky programování pro programování v jednom vlákně v jednom procesu ve srovnání s více vlákny v jednom procesu?
O tématu byly napsány knihy. Ale velmi stručně, všechny rozdíly se týkají jednoho faktoru: při programování v jediném vlákně a procesu vždy víte, jak jste se dostali k aktuální instrukci. Pokyny se vyskytují v jedné sekvenci. Ale při programování pro mnoho vláken nemáte tušení, které instrukce byly provedeny v jakém pořadí, abyste se dostali k aktuální instrukci. To programování komplikuje.
Ale komplikuje to ještě jeden faktor: na rozdíl od procesů vlákna sdílejí paměť. Nevíte, které vlákno se naposledy dotklo daného paměťového místa, nebo které bude další, pokud nemáte nějakou „synchronizaci“. Proto je v Javě klíčové slovo „synchronized“ (odtrženo od Ady). Monitory, semafory, zámky , pro synchronizaci byly použity proměnné podmínky a dokonce i předávání zpráv.
Odpověď
(Aktualizace: Dávejte pozor na další odpověď, která říká, že nemůžete mít webový server s jedním vláknem, který zpracovává souběžné požadavky dobře, protože to prostě není pravda.)
Proč je web s více vlákny lepší než server s jedním vláknem? Není.
Existují čtyři základní způsoby, jak webový server dokáže zpracovat souběžnost:
- rozvětvení proces OS na žádost (jako staré verze Apache)
- na každé žádosti se objeví vlákno OS (jako nové verze Apache)
- pomocí smyčky události s jedním vláknem (jako nginx )
- pomocí zelených vláken nebo odlehčených procesů naplánováno runtime VM namísto OS (jako v Erlangu)
V současnosti jsou nejběžnější přístupy číslo 2 a 3.
Existují výhody a nevýhody obou z nich. Pro operace vázané na I / O (charakteristika typického webového serveru) získáte lepší výkon and vyšší počet souběžných požadavků , když použijete smyčku událostí s jedním vláknem . Nevýhodou však je, že pro všechny operace musíte použít výhradně asynchronní neblokující I / O, jinak zablokujete smyčku událostí a ztratíte výkon. Z tohoto důvodu je snazší implementovat vícevláknový server, ale platíte za výkon.
Za operace CPU-bound (méně časté pro obvyklý webový server, běžnější pro výpočetně náročné rozhraní API), je nejlepší mít jedno vlákno nebo proces OS na jádro . S cykly událostí s jedním vláknem je to snadné, protože můžete spustit shluk mnoha procesů jeden na jádro. Je těžké to udělat s vícevláknovými servery, protože pokud je rozmnožování vláken vaším jediným způsobem, jak zvládnout souběžné požadavky, pak nemůžete skutečně ovládat, kolik vláken budete mít – protože nekontrolujete počet požadavků. Jakmile budete mít více vláken než počet jader CPU, ztratíte výkon pro kontextové přepínače a využijete také spoustu paměti RAM.
Proto jednovláknový server nginx funguje lépe než vícevláknový webový server Apache (a proto byl nginx vytvořen na prvním místě). Také Redis , databáze známá pro výjimečně vysoký výkon, je jednovláknová .
Skutečný příklad, který vám mohu dát, je tento: Můj první webový server byl Apache běžící na stroji s Linuxem s 500 MB RAM. Pro každý požadavek to rozdělilo nový proces (ve skutečnosti měl fond, takže se toho moc nerozvětvovalo, ale musel tyto procesy udržovat naživu, aby je znovu použil a jednou za čas je zabil, aby se zabránilo úniku zdrojů).
Můj OS používal přibližně 100 MB RAM. Každý proces Apache používal 20 MB RAM. Znamenalo to, že můj server dokázal zpracovat pouze 20 souběžných požadavků a nebylo ho možné obejít, protože jsem už neměl RAM. Procesy byly většinou blokovány na I / O, takže využití CPU bylo velmi nízké, každý požadavek nad těmito 20 musel čekat a pokud těch 20 bylo např. dlouho běžící stahování, pak můj server zcela nereagoval.
Když byl představen webový server nginx, použil smyčku událostí s jedním vláknem a neblokoval žádný požadavek. Mohlo by zvládnout mnohem více souběžných požadavků, aniž by měl problém s mýtickým problémem c10k – nginx byl v zásadě vytvořen k vyřešení problému c10k (10 000 souběžných požadavků).
Představte si, kolik RAM se promrhá na 10 000 vláken, pokud může dokonce vytvořit tolik a kolik času se používá pro kontextové přepínače.
Využití paměti vícevláknového Apache vs. jednovláknového nginx:
Mimochodem, to je důvod, proč Ryan Dahl použil neblokující I / O a jednovláknovou smyčku událostí v Node.js a stále používá stejný nápad v Deno, protože to je způsob, jak psát vysoce výkonné síťové servery (na rozdíl od toho, co si můžete přečíst v jiných odpovědích zde).