L'applicazioni web sò avà aduprate in ogni locu, è trà tutti i protokolli di trasportu, HTTP occupa a parte di u leone. Quandu studia i sfumaturi di u sviluppu di l'applicazioni web, a maiò parte di a ghjente presta assai poca attenzione à u sistema operatore induve queste applicazioni funzionanu. A separazione di u sviluppu (Dev) è l'operazioni (Ops) hà solu peghju a situazione. Ma cù l'aumentu di a cultura DevOps, i sviluppatori sò diventati rispunsevuli di eseguisce e so applicazioni in u nuvulu, per quessa, hè assai utile per elli à familiarizà bè cù u backend di u sistema operatore. Questu hè soprattuttu utile sè vo circate di implementà un sistema per millaie o decine di millaie di cunnessione simultanee.
I limitazioni in i servizii web sò assai simili à quelli in altre applicazioni. Qu'il s'agisse d'équilibreurs de charges ou de serveurs de bases de données, toutes ces applications ont des problèmes similaires dans un environnement à haut rendement. A capiscitura di sti limitazioni fundamentali è cumu per superà in generale vi aiuterà à valutà u rendiment è a scalabilità di e vostre applicazioni web.
Я пишу эту серию статей в ответ на вопросы молодых разработчиков, которые хотят стать хорошо информированными системными архитекторами. Невозможно чётко понять методы оптимизации приложений Linux, не погрузившись в основы, как они работают на уровне операционной системы. Хотя есть много типов приложений, в этом цикле я хочу исследовать сетевые приложения, а не десктопные, такие как браузер или текстовый редактор. Этот материал рассчитан на разработчиков и архитекторов, которые хотят понять, как работают программы Linux или Unix и как их структурировать для высокой производительности.
Linux Is sala di servitori операционная система, и чаще всего ваши приложения работают именно на этой ОС. Хотя я говорю «Linux», большую часть времени вы можете с уверенностью предположить, что имеются в виду все Unix-подобные операционные системы в целом. Тем не менее, я не тестировал сопровождающий код на других системах. Итак, если вас интересует FreeBSD или OpenBSD, результат может отличаться. Когда я пробую что-то Linux-специфическое, то указываю на это.
Mentre pudete aduprà sta cunniscenza per custruisce una app da zero è serà perfettamenti ottimizzata, hè megliu micca fà quessa. Se scrivite un novu servitore web in C o C++ per l'applicazione cummerciale di a vostra urganizazione, questu pò esse u vostru ultimu ghjornu nantu à u travagliu. Tuttavia, cunnosce a struttura di sti appiicazioni vi aiuterà à sceglie prugrammi esistenti. Puderete paragunà i sistemi basati in prucessu cù i sistemi basati in filu è ancu quelli basati in l'avvenimenti. Puderete capisce è apprezzà perchè Nginx rende megliu cà Apache httpd, perchè una applicazione Python basata in Tornado pò serve più utenti cumparatu cù una applicazione Python basata in Django.
ZeroHTTPd: Strumenta di apprendimentu
hè un servitore web chì aghju scrittu da zero in C cum'è strumentu d'insignamentu. Ùn hà micca dipendenze esterne, cumpresu l'accessu à Redis. Eseguimu e nostre prucedure Redis. Vede quì sottu per più dettagli.
Ancu s'è puderemu discutiri a teoria in longu, ùn ci hè nunda di megliu cà scrive codice, eseguisce, è paragunà tutte l'architetture di u servitore cù l'altri. Questu hè u metudu più evidenti. Dunque, scriveremu un servitore web ZeroHTTPd simplice utilizendu ogni mudellu: basatu in prucessu, basatu in filu è basatu in avvenimenti. Cuntrollamu ognunu di sti servitori è vede cumu si cumportanu paragunatu à l'altri. ZeroHTTPd hè implementatu in un unicu schedariu C U servitore basatu in l'avvenimentu include , una grande implementazione di a tavola hash chì vene in un unicu file di header. In altri casi, ùn ci sò micca dipendenze, per ùn cumplicà u prugettu.
В коде очень много комментариев, чтобы помочь разобраться. Будучи простым веб-сервером в нескольких строчках кода, ZeroHTTPd также представляет собой минимальный фреймворк для веб-разработки. У него ограниченная функциональность, но он способен выдавать статические файлы и очень простые «динамические» страницы. Должен сказать, что ZeroHTTPd хорошо подходит для обучения, как создавать высокопроизводительные Linux-приложения. По большому счёту, большинство веб-сервисов ждут запросов, проверяют их и обрабатывают. Именно это будет делать ZeroHTTPd. Это инструмент для обучения, а не для продакшна. Он не силён в обработке ошибок и вряд ли похвастается лучшими практиками безопасности (о да, я использовал strcpy) o i trucchi intelligenti di a lingua C Ma spergu chì faci bè u so travagliu.

Pagina iniziale di ZeroHTTPd. Si pò pruduce diversi tipi di schedari cumpresi images
Applicazione di u Libru d'ospiti
L'applicazioni web muderni sò generalmente micca limitati à i schedari statici. Hanu interazzione cumplessu cù diverse basa di dati, cache, etc. Allora avemu da creà una applicazione web simplice chjamata "Guest Book" induve i visitori lascianu entrate sottu i so nomi. U libru di l'ospiti conserva e entrate lasciate prima. Ci hè ancu un contatore di visitatori à u fondu di a pagina.

Applicazione Web "Guest Book" ZeroHTTPd
Счётчик посетителей и записи гостевой книги хранятся в Redis. Для коммуникаций с Redis реализованы собственные процедуры, они не зависят от внешней библиотеки. Я не большой поклонник выкатывать доморощенный код, когда есть общедоступные и хорошо протестированные решения. Но цель ZeroHTTPd — изучить производительность Linux и доступ к внешним службам, в то время как обслуживание HTTP-запросов серьёзно влияет на производительность. Мы должны полностью контролировать коммуникации с Redis в каждой из наших серверных архитектур. В одной архитектуре мы используем блокирующие вызовы, в других — процедуры на основе событий. Использование внешней клиентской библиотеки Redis не даст такой контроль. Кроме того, наш маленький клиент Redis выполняет только несколько функций (получение, настройка и увеличение ключа; получение и добавление к массиву). К тому же, протокол Redis исключительно элегантный и простой. Его даже учить специально не надо. Сам факт, что всю работу протокол выполняет примерно в ста строчках кода, говорит о том, насколько он хорошо продуман.
A figura seguente mostra ciò chì l'applicazione face quandu u cliente (navigatore) dumanda /guestbookURL.

Cumu funziona l'applicazione di u libru d'ospiti
Quandu una pagina di u libru d'ospiti deve esse emessa, ci hè una chjama à u sistema di fugliale per leghje u mudellu in memoria è trè chjama di rete à Redis. U schedariu di mudellu cuntene a maiò parte di u cuntenutu HTML per a pagina in a screenshot sopra. Ci hè ancu un locu speciale per a parte dinamica di u cuntenutu: posti è contatore di visitatori. Ricevemu da Redis, inserite in a pagina è furnisce u cliente cun cuntenutu sanu furmatu. A terza chjama à Redis pò esse evitata perchè Redis torna u novu valore chjave quandu aumenta. In ogni casu, per u nostru servitore, chì hà una architettura asincrona basata nantu à l'avvenimenti, assai chjama di rete sò una bona prova per scopi di apprendimentu. Allora scartamu u valore di ritornu Redis di u numeru di visitatori è l'interroghemu cù una chjama separata.
Architettura di u servitore ZeroHTTPd
Custruemu sette versioni di ZeroHTTPd cù a listessa funziunalità ma diverse architetture:
- Iterativu
- Servitore Fork (un prucessu zitellu per dumanda)
- Servitore di pre-fork (pre-fork di prucessi)
- Servitore cù fili di esecuzione (un filu per dumanda)
- Servitore cù creazione di pre-thread
- Basatu nantu à l'architettura
poll() - Basatu nantu à l'architettura
epoll
Misuremu a prestazione di ogni architettura carchendu u servitore cù richieste HTTP. Ma quandu paragunate architetture altamente parallele, u numeru di dumande aumenta. Testemu trè volte è calculemu a media.
Metodologia di prova

Configurazione di teste di carica ZeroHTTPd
Hè impurtante chì quandu eseguite e teste, tutti i cumpunenti ùn viaghjanu micca nantu à a stessa macchina. In questu casu, u sistema operativu incurre un overhead di pianificazione supplementu cum'è cumpunenti compete per CPU. A misurazione di u sistema operatore sopra di ognuna di l'architetture di u servitore sceltu hè unu di i scopi più impurtanti di questu esercitu. Aghjunghjendu più variàbili diventerà preghjudiziu à u prucessu. Per quessa, u paràmetru in a stampa sopra funziona megliu.
Chì facenu ognunu di sti servitori?
- load.unixism.net: Questu hè induve corremu
ab, Utilità Apache Benchmark. Genera a carica necessaria per pruvà e nostre architetture di u servitore. - nginx.unixism.net: A volte vulemu eseguisce più di una istanza di un prugramma di servitore. Per fà questu, u servitore Nginx cù i paràmetri appropritati funziona cum'è un equilibratore di carica chì vene da ab à i nostri prucessi di u servitore.
- zerohttpd.unixism.net: Quì eseguimu i nostri prugrammi di u servitore nantu à sette architetture diverse, una per volta.
- redis.unixism.net: Stu servitore esegue u daemon Redis, induve l'entrata di u libru d'ospiti è i contatori di visitatori sò almacenati.
Tutti i servitori funzionanu nantu à u stessu core di processore. L'idea hè di valutà a prestazione massima di ogni architettura. Siccomu tutti i prugrammi di u servitore sò pruvati nantu à u stessu hardware, questu hè una basa di paraguni. A mo cunfigurazione di prova hè custituita da servitori virtuali affittati da Digital Ocean.
Chì misuremu ?
Pudete misurà diversi indicatori. Evaluemu u funziunamentu di ogni architettura in una cunfigurazione data carchendu i servitori cù richieste à diversi livelli di parallelismu: a carica cresce da 20 à 15 000 utenti simultanei.
Risultati di test
U graficu seguente mostra a prestazione di i servitori in diverse architetture à diversi livelli di parallelismu. L'assi y hè u numeru di richieste per seconda, l'assi x hè cunnessione parallela.



A sottu hè una tavula cù i risultati.
richieste per seconda
paralelisimu
iterativu
forchetta
pre-furchetta
streaming
pre-streaming
vota
epollu
20
7
112
2100
1800
2250
1900
2050
50
7
190
2200
1700
2200
2000
2000
100
7
245
2200
1700
2200
2150
2100
200
7
330
2300
1750
2300
2200
2100
300
-
380
2200
1800
2400
2250
2150
400
-
410
2200
1750
2600
2000
2000
500
-
440
2300
1850
2700
1900
2212
600
-
460
2400
1800
2500
1700
2519
700
-
460
2400
1600
2490
1550
2607
800
-
460
2400
1600
2540
1400
2553
900
-
460
2300
1600
2472
1200
2567
1000
-
475
2300
1700
2485
1150
2439
1500
-
490
2400
1550
2620
900
2479
2000
-
350
2400
1400
2396
550
2200
2500
-
280
2100
1300
2453
490
2262
3000
-
280
1900
1250
2502
larga diffusione
2138
5000
-
larga diffusione
1600
1100
2519
-
2235
8000
-
-
1200
larga diffusione
2451
-
2100
10
-
-
larga diffusione
-
2200
-
2200
11
-
-
-
-
2200
-
2122
12
-
-
-
-
970
-
1958
13
-
-
-
-
730
-
1897
14
-
-
-
-
590
-
1466
15
-
-
-
-
532
-
1281
Из графика и таблицы видно, что выше 8000 одновременных запросов у нас остаётся только две игрока: пре-форк и epoll. С ростом нагрузки сервер на базе poll работает хуже, чем потоковый. Архитектура с предварительным созданием потоков составляет достойную конкуренцию epoll: это свидетельство, насколько хорошо ядро Linux планирует большое количество потоков.
Codice Source ZeroHTTPd
Codice Source ZeroHTTPd . Ci hè un repertoriu separatu per ogni architettura.
ZeroHTTPd │ ├── 01_iterative │ ├── main.c ├── 02_forking │ ├── main.c ├── 03_preforking │── ├─ _esima lettura │ ├── main.c ├── 04_prethreading │ ├── main.c ├── 05_poll │ ├── main.c ├── 06_epoll │ └── 07_poll │ ├── main.c ├── XNUMX_epoll │ └── └── rende public.c ├─ ── index html │ └── tux png └── mudelli └── guestbook └── index.html
In più di sette cartulari per tutte l'architetture, ci sò dui più in u cartulare di primu livellu: publicu è mudelli. U primu cuntene u schedariu index.html è l'imaghjini da a prima screenshot. Pudete mette altri schedarii è cartulare, è ZeroHTTPd duveria serve i schedari statici senza prublemi. Se u percorsu in u navigatore currisponde à u percorsu in u cartulare publicu, allora ZeroHTTPd cerca u schedariu index.html in questu repertoriu. U cuntenutu per u libru d'ospiti hè generatu dinamicamente. Hè solu una pagina di casa, è u so cuntenutu hè basatu annantu à u schedariu "templates/guestbook/index.html". ZeroHTTPd aghjunghje facilmente pagine dinamiche per estensione. L'idea hè chì l'utilizatori ponu aghjunghje mudelli à questu repertoriu è allargà ZeroHTTPd quantu necessariu.
Per custruisce tutti i sette servitori, eseguite make all da u cartulare di primu livellu - è tutte e custruzzioni appariscenu in questu cartulare. I fugliali eseguibili cercanu i repertorii publichi è mudelli in u cartulare da quale sò lanciati.
Linux API
Чтобы понять информацию в этом цикле статей, не обязательно хорошо разбираться в Linux API. Однако рекомендую прочитать больше на эту тему, в Сети много справочных ресурсов. Хотя мы коснёмся нескольких категорий Linux API, наше внимание будет сосредоточено в основном на процессах, потоках, событиях и сетевом стеке. Кроме книг и статей про Linux API, рекомендую также почитать маны для системных вызовов и используемых библиотечных функций.
Prestazione è scalabilità
Una nota nantu à u rendiment è a scalabilità. In teoria, ùn ci hè micca una cunnessione trà elli. Pudete avè un serviziu web chì travaglia assai bè, cù un tempu di risposta di uni pochi millisecondi, ma ùn scala micca in tuttu. In listessu modu, ci pò esse una applicazione web mal prestata chì pigghia uni pochi di seconde per risponde, ma scala da decine per trattà decine di millaie di utilizatori simultanei. Tuttavia, a cumminazzioni di altu rendiment è scalabilità hè una cumminazione assai putente. L'applicazioni d'altu rendiment generalmente utilizanu risorse cù parsimonia è cusì serve in modu efficiente à l'utilizatori più cuncurrenti in u servitore, riducendu i costi.
CPU è attività I/O
Infine, in l'informatica, ci sò sempre dui tipi di cumpetenze pussibuli: per I/O è CPU. Riceve dumande nantu à Internet (I/O di rete), serve i schedari (I/O di rete è di discu), cumunicà cù a basa di dati (I/O di rete è di discu) sò tutte l'attività I/O. Alcune dumande di basa di dati ponu esse un pocu CPU intensive (selezzione, una media di un milione di risultati, etc.). A maiò parte di l'applicazioni web sò limitati da u massimu I / O pussibule, è u processatore hè raramente utilizatu à piena capacità. Quandu vi vede chì qualchissimu compitu I / O usa assai CPU, hè più prubabile un signu di l'architettura di l'applicazione povera. Questu pò significà chì e risorse di CPU sò sprecate in a gestione di u prucessu è u cambiamentu di u cuntestu - è questu ùn hè micca sanu utile. Sè vo fate qualcosa cum'è trasfurmazioni di l'imaghjini, cunversione di file audio, o apprendimentu automaticu, allora l'applicazione richiede risorse CPU putenti. Ma per a maiò parte di l'applicazioni questu ùn hè micca u casu.
Sapete più nantu à l'architettura di u servitore
Source: www.habr.com
