Прадукцыйнасць сеткавых прыкладанняў Linux. Увядзенне

Вэб-прыкладанні цяпер выкарыстоўваюцца паўсюдна, а сярод усіх транспартных пратаколаў ільвіную дзель займае HTTP. Вывучаючы нюансы распрацоўкі вэб-прыкладанняў, большасць надае вельмі мала ўвагі аперацыйнай сістэме, дзе гэтыя прыкладанні рэальна запускаюцца. Падзел распрацоўкі (Dev) і эксплуатацыі (Ops) толькі пагаршала сітуацыю. Але з распаўсюджваннем культуры DevOps распрацоўшчыкі пачынаюць несці адказнасць за запуск сваіх прыкладанняў у воблаку, таму для іх вельмі карысна дасканала пазнаёміцца ​​з бэкэндам аперацыйнай сістэмы. Гэта асабліва карысна, калі вы спрабуеце разгарнуць сістэму для тысяч ці дзясяткаў тысяч адначасовых падлучэнняў.

Абмежаванні ў вэб-службах вельмі падобныя на абмежаванні ў іншых прыкладаннях. Няхай гэта будзе балансавальнікі нагрузкі або серверы БД, ва ўсіх гэтых прыкладанняў аналагічныя праблемы ў высокапрадукцыйнай асяроддзі. Разуменне гэтых фундаментальных абмежаванняў і спосабаў іх пераадолення ў цэлым дазволіць ацаніць прадукцыйнасць і маштабаванасць вашых вэб-прыкладанняў.

Я пішу гэтую серыю артыкулаў у адказ на пытанні маладых распрацоўшчыкаў, якія хочуць стаць добра інфармаванымі сістэмнымі архітэктарамі. Немагчыма выразна зразумець метады аптымізацыі прыкладанняў Linux, не пагрузіўшыся ў асновы, як яны працуюць на ўзроўні аперацыйнай сістэмы. Хоць ёсць шмат тыпаў прыкладанняў, у гэтым цыкле я хачу даследаваць сеткавыя прыкладанні, а не дэсктопныя, такія як браўзэр або тэкставы рэдактар. Гэты матэрыял разлічаны на распрацоўшчыкаў і архітэктараў, якія жадаюць зразумець, як працуюць праграмы Linux або Unix і як іх структураваць для высокай прадукцыйнасці.

Linux - гэта серверная аперацыйная сістэма, і часцей за ўсё вашыя прыкладанні працуюць менавіта на гэтай АС. Хоць я кажу "Linux", большую частку часу вы можаце з упэўненасцю выказаць здагадку, што маюцца на ўвазе ўсе Unix-падобныя аперацыйныя сістэмы ў цэлым. Тым не менш, я не тэставаў суправаджальны код на іншых сістэмах. Такім чынам, калі вас цікавіць FreeBSD ці OpenBSD, вынік можа адрознівацца. Калі я спрабую нешта Linux-спецыфічнае, то паказваю на гэта.

Хаця вы можаце выкарыстоўваць атрыманыя веды для стварэння прыкладання з нуля, і яно будзе цудоўна аптымізавана, але лепш так не рабіць. Калі вы напішаце новы вэб-сервер на C ці C++ для бізнес-дадатку сваёй арганізацыі, магчыма, гэта будзе ваш апошні дзень на працы. Аднак веданне структуры гэтых прыкладанняў дапаможа ў выбары ўжо існуючых праграм. Вы зможаце параўноўваць сістэмы на аснове працэсаў з сістэмамі на аснове патокаў, а таксама на аснове падзей. Вы зразумееце і ацаніце, чаму Nginx працуе лепш, чым Apache httpd, чаму прыкладанне Python на аснове Tornado можа абслугоўваць больш карыстальнікаў у параўнанні з дадаткам Python на аснове Django.

ZeroHTTPd: інструмент навучання

ZeroHTTPd - вэб-сервер, які я напісаў з нуля на C у якасці навучальнай прылады. У яго няма вонкавых залежнасцяў, у тым ліку доступу да Redis. Мы запускаем уласныя працэдуры Redis. Больш падрабязна гл. ніжэй.

Хоць мы маглі б доўга абмяркоўваць тэорыю, няма нічога лепш, чым напісаць код, запусціць яго і параўнаць паміж сабой усе сервернай архітэктуры. Гэта самы наглядны метад. Таму мы будзем пісаць просты вэб-сервер ZeroHTTPd, ужываючы кожную мадэль: на аснове працэсаў, струменяў і падзей. Праверым кожны з гэтых сервераў і паглядзім, як яны працуюць у параўнанні сябар з сябрам. ZeroHTTPd рэалізаваны ў адным файле C. У склад сервера на аснове падзей уваходзіць uthash, выдатная рэалізацыя хэш-табліцы, якая пастаўляецца ў адным загалоўкавых файлаў. У астатніх выпадках ніякіх залежнасцяў няма, каб не ўскладняць праект.

У кодзе вельмі шмат каментароў, каб дапамагчы разабрацца. Будучы простым вэб-серверам у некалькіх радках кода, ZeroHTTPd таксама ўяўляе сабой мінімальны фрэймворк для вэба-распрацоўкі. У яго абмежаваная функцыянальнасць, але ён здольны выдаваць статычныя файлы і вельмі простыя "дынамічныя" старонкі. Павінен сказаць, што ZeroHTTPd добра падыходзіць для навучання, як ствараць высокапрадукцыйныя Linux-прыкладанні. Па вялікім рахунку, большасць вэб-сэрвісаў чакаюць запытаў, правяраюць іх і апрацоўваюць. Менавіта гэта будзе рабіць ZeroHTTPd. Гэта інструмент для навучання, а не для прадакшна. Ён не моцны ў апрацоўцы памылак і ці наўрад пахваліцца лепшымі практыкамі бяспекі (о так, я выкарыстаў strcpy) або мудрагелістымі трукамі мовы C. Але я спадзяюся, ён добра справіцца са сваёй задачай.

Прадукцыйнасць сеткавых прыкладанняў Linux. Увядзенне
Загалоўная старонка ZeroHTTPd. Ён можа выдаваць розныя тыпы файлаў, уключаючы выявы

Дадатак гасцявой кнігі

Сучасныя вэб-прыкладанні звычайна не абмежаваныя статычнымі файлы. У іх складаныя ўзаемадзеянні з рознымі БД, кэшамі і г. д. Таму мы створым просты вэб-дадатак пад назвай «Гасцінная кніга», дзе наведвальнікі пакідаюць запісы пад сваімі імёнамі. У гасцявой кнізе захоўваюцца запісы, пакінутыя раней. Ёсць таксама лічыльнік наведвальнікаў у ніжняй частцы старонкі.

Прадукцыйнасць сеткавых прыкладанняў Linux. Увядзенне
Вэб-дадатак "Госьцёвая кніга" ZeroHTTPd

Лічыльнік наведвальнікаў і запісы гасцявой кнігі захоўваюцца ў Redis. Для камунікацый з Redis рэалізаваны ўласныя працэдуры, яны не залежаць ад знешняй бібліятэкі. Я не вялікі прыхільнік выкочваць дамарослы код, калі ёсць агульнадаступныя і добра пратэставаныя рашэнні. Але мэта ZeroHTTPd - вывучыць прадукцыйнасць Linux і доступ да вонкавых службаў, у той час як абслугоўванне HTTP-запытаў сур'ёзна ўплывае на прадукцыйнасць. Мы павінны цалкам кантраляваць камунікацыі з Redis у кожнай з нашых серверных архітэктур. У адной архітэктуры мы выкарыстоўваем блакавальныя выклікі, у іншых - працэдуры на аснове падзей. Выкарыстанне знешняй кліенцкай бібліятэкі Redis не дасць такі кантроль. Акрамя таго, наш маленькі кліент Redis выконвае толькі некалькі функцый (атрыманне, настройка і павелічэнне ключа; атрыманне і даданне да масіва). Да таго ж, пратакол Redis выключна элегантны і просты. Яго нават вучыць спецыяльна не трэба. Сам факт, што ўсю працу пратакол выконвае прыкладна ў ста радках кода, кажа аб тым, наколькі ён добра прадуманы.

На наступным малюнку паказаны дзеянні прыкладання, калі кліент (браўзэр) запытвае /guestbookURL.

Прадукцыйнасць сеткавых прыкладанняў Linux. Увядзенне
Механізм працы прыкладання гасцявой кнігі

Калі трэба выдаць старонку гасцявой кнігі, адбываецца адзін выклік да файлавай сістэмы для чытання шаблона ў памяць і тры сеткавыя выклікі да Redis. Файл шаблону змяшчае большую частку змесціва HTML для старонкі на скрыншоце уверсе. Там ёсць таксама спецыяльныя запаўняльнікі для дынамічнай часткі кантэнту: запісаў і лічыльніка наведвальнікаў. Мы атрымліваем іх з Redis, устаўляемы на старонку і выдаём кліенту цалкам сфармаваны кантэнт. Трэцяга выкліку Redis можна пазбегнуць, паколькі Redis вяртае новае значэнне ключа пры павелічэнні. Аднак для нашага сервера з асінхроннай архітэктурай на аснове падзей мноства сеткавых выклікаў - добрае выпрабаванне ў навучальных мэтах. Такім чынам, мы адкідаем якое вяртаецца значэнне Redis аб колькасці наведвальнікаў і запытваем яго асобным выклікам.

Серверныя архітэктуры ZeroHTTPd

Мы будуем сем версій ZeroHTTPd з аднолькавай функцыянальнасцю, але рознымі архітэктурамі:

  • Ітэратыўная
  • Форк сервер (адзін даччыны працэс на запыт)
  • Прэ-форк сервер (папярэдні форкінг працэсаў)
  • Сервер c патокамі выканання (адзін thread на запыт)
  • Сервер з папярэднім стварэннем патокаў
  • Архітэктура на базе poll()
  • Архітэктура на базе epoll

Вымяраем прадукцыйнасць кожнай архітэктуры, загрузіўшы сервер HTTP-запытамі. Але пры параўнанні архітэктур з высокай ступенню паралелізму колькасць запытаў павялічваецца. Тэстуем тры разы і лічым сярэдняе.

Метадалогія тэсціравання

Прадукцыйнасць сеткавых прыкладанняў Linux. Увядзенне
Устаноўка для нагрузачнага тэсціравання ZeroHTTPd

Важна, каб пры выкананні тэстаў усе кампаненты не працавалі на адной машыне. У гэтым выпадку АС нясе дадатковыя накладныя выдаткі на планаванне, паколькі кампаненты супернічаюць за CPU. Вымярэнне накладных выдаткаў аперацыйнай сістэмы з кожнай з абраных серверных архітэктур з'яўляецца адной з найболей важных мэт гэтага практыкавання. Даданне большай колькасці зменных стане згубным для працэсу. Такім чынам, настройка на малюнку вышэй працуе лепш за ўсё.

Што робіць кожны з гэтых сервераў

  • load.unixism.net: тут мы запускаем ab, утыліту Apache Benchmark. Яна генеруе нагрузку, неабходную для тэсціравання нашых серверных архітэктур.
  • nginx.unixism.net: часам мы жадаем запусціць больш аднаго асобніка сервернай праграмы. Для гэтага сервер Nginx з адпаведнымі наладамі працуе як балансавальнік нагрузкі, якая паступае ад ab на нашыя серверныя працэсы.
  • zerohttpd.unixism.net: тут мы запускаем нашы серверныя праграмы на сямі розных архітэктурах, па адной за раз.
  • redis.unixism.net: на гэтым серверы працуе дэман Redis, дзе захоўваюцца запісы ў гасцявой кнізе і лічыльнік наведвальнікаў.

Усе серверы працуюць на адным працэсарным ядры. Ідэя ў тым, каб ацаніць максімальную прадукцыйнасць кожнай з архітэктур. Бо ўсе серверныя праграмы тэстуюцца на адным абсталяванні, гэта базавы ўзровень для іх параўнання. Мая тэставая ўстаноўка складаецца з віртуальных сервераў, арандаваных у Digital Ocean.

Што мы вымяраем?

Можна вымераць розныя паказчыкі. Мы ацэньваем прадукцыйнасць кожнай архітэктуры ў дадзенай канфігурацыі, загружаючы серверы запытамі на розных узроўнях паралелізму: нагрузка расце ад 20 да 15 000 адначасовых карыстачоў.

вынікі тэстаў

На наступнай дыяграме паказана прадукцыйнасць сервераў на рознай архітэктуры пры розных узроўнях паралелізму. Па восі y - колькасць запытаў у секунду, па восі x - паралельныя злучэнні.

Прадукцыйнасць сеткавых прыкладанняў Linux. Увядзенне

Прадукцыйнасць сеткавых прыкладанняў Linux. Увядзенне

Прадукцыйнасць сеткавых прыкладанняў Linux. Увядзенне

Ніжэй табліца з вынікамі.

запытаў у секунду

паралелізм
ітэратыўны
відэлец
прэ-форк
струменевы
прэ-струменевы
галасаванне
epoll

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
вялікі роскід
2138

5000
-
вялікі роскід
1600
1100
2519
-
2235

8000
-
-
1200
вялікі роскід
2451
-
2100

10 000
-
-
вялікі роскід
-
2200
-
2200

11 000
-
-
-
-
2200
-
2122

12 000
-
-
-
-
970
-
1958

13 000
-
-
-
-
730
-
1897

14 000
-
-
-
-
590
-
1466

15 000
-
-
-
-
532
-
1281

З графіка і табліцы бачна, што вышэй за 8000 адначасовых запытаў у нас застаецца толькі два гульцы: пре-форк і epoll. З ростам нагрузкі сервер на базе poll працуе горш, чым струменевае. Архітэктура з папярэднім стварэннем струменяў складае годную канкурэнцыю epoll: гэтае сведчанне, наколькі добра ядро ​​Linux плануе вялікую колькасць струменяў.

Зыходны код ZeroHTTPd

Зыходны код ZeroHTTPd тут. Для кожнай архітэктуры асобны каталог.

ZeroHTTPd
│
├── 01_iterative
│ ├── main.c
├── 02_forking
│ ├── main.c
├── 03_preforking
│ ├── main.c
├── 04_threading
│ ├── main.c
├── 05_prethreading
│ ├── main.c
├── 06_poll
│ ├── main.c
├── 07_epoll
│ └── main.c
├── Makefile
├── public
│ ├── index.html
│ └── tux.png
└── templates
    └── guestbook
        └── index.html

Акрамя сямі дырэкторый для ўсіх архітэктур, у каталогу верхняга ўзроўня ёсць яшчэ дзве: public і templates. У першым ляжыць файл index.html і малюнак з першага скрыншота. Туды можна змясціць іншыя файлы і тэчкі, і ZeroHTTPd павінен без праблем выдаць гэтыя статычныя файлы. Калі path у браўзэры адпавядае шляхі ў тэчцы public, то ZeroHTTPd шукае ў гэтым каталогу файл index.html. Кантэнт для гасцявой кнігі генеруецца дынамічна. У яго толькі галоўная старонка, а яе змесціва заснавана на файле 'templates/guestbook/index.html'. У ZeroHTTPd лёгка дадаюцца дынамічныя старонкі для пашырэння. Ідэя складаецца ў тым, што карыстачы могуць дадаваць у гэтым каталог шаблоны і пашыраць ZeroHTTPd па меры неабходнасці.

Для зборкі ўсіх сямі сервераў запусціце make all з каталога верхняга ўзроўня - і ўсе білды з'явяцца ў гэтым каталогу. Выконваныя файлы шукаюць каталогі public і templates у тым каталогу, адкуль яны запускаюцца.

Linux API

Каб зразумець інфармацыю ў гэтым цыкле артыкулаў, не абавязкова добра разбірацца ў Linux API. Аднак рэкамендую прачытаць больш на гэтую тэму, у сетцы шмат даведачных рэсурсаў. Хоць мы закранем некалькі катэгорый Linux API, наша ўвага будзе засяроджана ў асноўным на працэсах, патоках, падзеях і сеткавым стэку. Акрамя кніг і артыкулаў пра Linux API, рэкамендую таксама пачытаць маны для сістэмных выклікаў і выкарыстоўваных бібліятэчных функцый.

Прадукцыйнасць і маштабаванасць

Адна заўвага аб прадукцыйнасці і маштабаванасці. Тэарэтычна паміж імі няма ніякай сувязі. У вас можа быць вэб-сэрвіс, які працуе вельмі добра, з часам водгуку ў некалькі мілісекунд, але ён наогул не маштабуецца. Сапраўды гэтак жа можа быць дрэнна працуе вэб-прыкладанне, якое патрабуе некалькі секунд для адказу, але яно маштабуецца на дзясяткі для апрацоўкі дзясяткаў тысяч адначасовых карыстачоў. Тым не менш, спалучэнне высокай прадукцыйнасці і маштабаванасці - вельмі магутнае спалучэнне. Высокапрадукцыйныя прыкладанні ў цэлым эканомна выкарыстоўваюць рэсурсы і, такім чынам, эфектыўна абслугоўваюць больш адначасовых карыстачоў на серверы, змяншаючы выдаткі.

Задачы CPU і I/O

Нарэшце, у вылічэннях заўсёды два магчымыя тыпы задач: для I/O і CPU. Атрыманне запытаў праз інтэрнэт (сеткавы ўвод-вывад), абслугоўванне файлаў (сеткавы і дыскавы ўвод-вывад), камунікацыі з базай дадзеных (сеткавы і дыскавы ўвод-вывад) – усё гэта дзеянні I/O. Некаторыя запыты да БД могуць крыху нагружаць CPU (сартаванне, вылічэнне сярэдняга значэння мільёна вынікаў і г.д.). Большасць вэб-прыкладанняў абмежаваныя па максімальна магчымым I/O, а працэсар рэдка выкарыстоўваецца на поўную магутнасць. Калі вы бачыце, што ў нейкай задачы ўводу-вываду выкарыстоўваецца шмат CPU, хутчэй за ўсё, гэта прыкмета дрэннай архітэктуры прыкладання. Гэта можа азначаць, што рэсурсы CPU марнуюцца на кіраванне працэсамі і пераключэнне кантэксту - і гэта не зусім карысна. Калі вы робіце нешта накшталт апрацоўкі малюнкаў, пераўтварэнні аўдыёфайлаў або машыннага навучання, тады прыкладанне патрабуе магутных рэсурсаў CPU. Але для большасці дадаткаў гэта не так.

Больш падрабязна аб серверных архітэктурах

  1. частка I. Ітэратыўная архітэктура
  2. частка II. Форк-серверы
  3. частка III. Прэ-форк серверы
  4. Частка IV. Серверы з патокамі выканання
  5. Частка V. Серверы з папярэднім стварэннем патокаў
  6. Частка VI. Архітэктура на базе poll
  7. Частка VII. Архітэктура на базе epoll

Крыніца: habr.com

Дадаць каментар