Linux ցանցային հավելվածի կատարումը: Ներածություն

Վեբ հավելվածներն այժմ օգտագործվում են ամենուր, և տրանսպորտային բոլոր արձանագրությունների մեջ HTTP-ն զբաղեցնում է առյուծի բաժինը։ Վեբ հավելվածների մշակման նրբությունները ուսումնասիրելիս մարդկանց մեծամասնությունը շատ քիչ ուշադրություն է դարձնում օպերացիոն համակարգին, որտեղ իրականում աշխատում են այս հավելվածները: Զարգացման (Dev) և գործառնությունների (Ops) տարանջատումը միայն վատթարացրեց իրավիճակը: Սակայն DevOps-ի մշակույթի աճի հետ մեկտեղ ծրագրավորողները դառնում են պատասխանատու իրենց հավելվածները ամպի մեջ գործարկելու համար, ուստի նրանց համար շատ օգտակար է լավ ծանոթանալ օպերացիոն համակարգի հետին պլանին: Սա հատկապես օգտակար է, եթե դուք փորձում եք համակարգ տեղադրել հազարավոր կամ տասնյակ հազարավոր միաժամանակյա միացումների համար:

Վեբ ծառայությունների սահմանափակումները շատ նման են այլ հավելվածների սահմանափակումներին: Անկախ նրանից, թե դա բեռի հավասարակշռողներ են, թե տվյալների բազայի սերվերներ, այս բոլոր հավելվածներն ունեն նմանատիպ խնդիրներ բարձր արդյունավետության միջավայրում: Հասկանալով այս հիմնարար սահմանափակումները և ընդհանուր առմամբ դրանք հաղթահարելը կօգնի ձեզ գնահատել ձեր վեբ հավելվածների կատարումն ու մասշտաբայնությունը:

Ես գրում եմ հոդվածների այս շարքը՝ պատասխանելով երիտասարդ ծրագրավորողների հարցերին, ովքեր ցանկանում են դառնալ լավ տեղեկացված համակարգերի ճարտարապետներ: Անհնար է հստակ հասկանալ Linux հավելվածների օպտիմիզացման տեխնիկան՝ առանց սուզվելու այն հիմունքների մեջ, թե ինչպես են դրանք աշխատում օպերացիոն համակարգի մակարդակում: Չնայած կան բազմաթիվ տեսակի հավելվածներ, այս շարքում ես ցանկանում եմ ուսումնասիրել վեբ վրա հիմնված հավելվածները, այլ ոչ թե աշխատասեղանի ծրագրերը, ինչպիսիք են բրաուզերը կամ տեքստային խմբագրիչը: Այս նյութը նախատեսված է մշակողների և ճարտարապետների համար, ովքեր ցանկանում են հասկանալ, թե ինչպես են աշխատում Linux կամ Unix ծրագրերը և ինչպես դրանք կառուցվածքավորել բարձր արդյունավետության համար:

Linux-ն է սերվերի սենյակ օպերացիոն համակարգ, և ամենից հաճախ ձեր հավելվածներն աշխատում են այս ՕՀ-ով: Չնայած ես ասում եմ «Linux», բայց շատ ժամանակ կարելի է հանգիստ ենթադրել, որ ես նկատի ունեմ բոլոր Unix-ի նման օպերացիոն համակարգերը ընդհանրապես: Այնուամենայնիվ, ես չեմ փորձարկել ուղեկցող կոդը այլ համակարգերում: Այսպիսով, եթե դուք հետաքրքրված եք FreeBSD-ով կամ OpenBSD-ով, ձեր արդյունքները կարող են տարբեր լինել: Երբ ես փորձում եմ Linux-ին հատուկ ինչ-որ բան, ես դա նշում եմ:

Թեև դուք կարող եք օգտագործել այս գիտելիքները զրոյից հավելված ստեղծելու համար, և այն կատարյալ օպտիմիզացված կլինի, ավելի լավ է դա չանել: Եթե ​​դուք գրում եք նոր վեբ սերվեր C կամ C++ լեզվով ձեր կազմակերպության բիզնես հավելվածի համար, դա կարող է լինել ձեր աշխատանքի վերջին օրը: Այնուամենայնիվ, այս հավելվածների կառուցվածքի իմացությունը կօգնի գոյություն ունեցող ծրագրերի ընտրությանը: Դուք կկարողանաք համեմատել գործընթացի վրա հիմնված համակարգերը թելի վրա հիմնված, ինչպես նաև իրադարձությունների վրա հիմնված համակարգերի հետ: Դուք կհասկանաք և կգնահատեք, թե ինչու է Nginx-ն ավելի լավ, քան Apache httpd-ը, ինչու Tornado-ի վրա հիմնված Python հավելվածը կարող է ավելի շատ օգտվողների սպասարկել՝ համեմատած Django-ի վրա հիմնված Python հավելվածի հետ:

ZeroHTTPd: Ուսուցման գործիք

ZeroHTTPd վեբ սերվեր է, որը ես զրոյից գրել եմ C-ում՝ որպես ուսուցման գործիք: Այն չունի արտաքին կախվածություն, ներառյալ Redis-ի հասանելիությունը: Մենք վարում ենք մեր սեփական Redis ընթացակարգերը: Լրացուցիչ մանրամասների համար տե՛ս ստորև:

Թեև մենք կարող էինք երկար քննարկել տեսությունը, չկա ավելի լավ բան, քան կոդ գրելը, այն գործարկելը և սերվերի բոլոր ճարտարապետությունները միմյանց հետ համեմատելը: Սա ամենաակնհայտ մեթոդն է։ Հետևաբար, մենք կգրենք պարզ ZeroHTTPd վեբ սերվեր՝ օգտագործելով յուրաքանչյուր մոդել՝ գործընթացի վրա հիմնված, շղթայի վրա հիմնված և իրադարձությունների վրա հիմնված: Եկեք ստուգենք այս սերվերներից յուրաքանչյուրը և տեսնենք, թե ինչպես են նրանք կատարում միմյանց համեմատ: ZeroHTTPd-ն իրականացվում է մեկ C ֆայլում: Իրադարձությունների վրա հիմնված սերվերը ներառում է ուտաշ, հեշ աղյուսակի հիանալի իրականացում, որը գալիս է մեկ վերնագրի ֆայլում: Մնացած դեպքերում կախվածություններ չկան, որպեսզի չբարդացնեն նախագիծը։

Կոդում կան բազմաթիվ մեկնաբանություններ, որոնք կօգնեն ձեզ հասկանալ: Լինելով պարզ վեբ սերվեր մի քանի տող կոդի մեջ՝ ZeroHTTPd-ը նաև նվազագույն շրջանակ է վեբ զարգացման համար: Այն ունի սահմանափակ ֆունկցիոնալություն, բայց կարող է սպասարկել ստատիկ ֆայլեր և շատ պարզ «դինամիկ» էջեր։ Պետք է ասեմ, որ ZeroHTTPd-ը լավ է սովորելու, թե ինչպես ստեղծել բարձր արդյունավետությամբ Linux հավելվածներ: Մեծ հաշվով, վեբ ծառայությունների մեծ մասը սպասում է հարցումներին, ստուգում դրանք և մշակում դրանք: Սա հենց այն է, ինչ կանի ZeroHTTPd-ը: Սա սովորելու գործիք է, ոչ թե արտադրություն: Այն հիանալի չէ սխալների հետ վարվելու հարցում և դժվար թե պարծենա անվտանգության լավագույն փորձից (այո, ես օգտագործել եմ strcpy) կամ C լեզվի խելացի հնարքները։Բայց հուսով եմ, որ այն լավ կկատարի իր գործը։

Linux ցանցային հավելվածի կատարումը: Ներածություն
ZeroHTTPd գլխավոր էջ: Այն կարող է արտադրել տարբեր տեսակի ֆայլեր, ներառյալ պատկերները

Հյուրերի գրքի հայտ

Ժամանակակից վեբ հավելվածները սովորաբար չեն սահմանափակվում միայն ստատիկ ֆայլերով: Նրանք ունեն բարդ փոխազդեցություններ տարբեր տվյալների բազաների, քեշերի և այլնի հետ: Այսպիսով, մենք կստեղծենք պարզ վեբ հավելված, որը կոչվում է «Հյուրերի գիրք», որտեղ այցելուները գրառումներ են թողնում իրենց անունների տակ: Հյուրերի գրքերի խանութների մուտքերը թողել են ավելի վաղ: Էջի ներքևում կա նաև այցելուների հաշվիչ:

Linux ցանցային հավելվածի կատարումը: Ներածություն
Վեբ հավելված «Հյուրերի գիրք» ZeroHTTPd

Այցելուների հաշվիչը և հյուրերի գրքի գրառումները պահվում են Redis-ում: Redis-ի հետ հաղորդակցվելու համար իրականացվում են սեփական ընթացակարգեր, որոնք կախված չեն արտաքին գրադարանից: Ես homebrew-ի կոդերի տարածման մեծ երկրպագու չեմ, երբ կան հանրությանը հասանելի և լավ փորձարկված լուծումներ: Սակայն ZeroHTTPd-ի նպատակն է ուսումնասիրել Linux-ի աշխատանքը և մուտքը արտաքին ծառայություններ, մինչդեռ HTTP հարցումների սպասարկումը լուրջ ազդեցություն ունի կատարողականի վրա: Մենք պետք է լիովին վերահսկենք Redis-ի հետ հաղորդակցությունը մեր յուրաքանչյուր սերվերի ճարտարապետության մեջ: Որոշ ճարտարապետություններում մենք օգտագործում ենք արգելափակող զանգեր, մյուսներում՝ իրադարձությունների վրա հիմնված ընթացակարգեր: Արտաքին Redis հաճախորդի գրադարանի օգտագործումը չի ապահովի այս վերահսկողությունը: Բացի այդ, մեր փոքրիկ Redis հաճախորդը կատարում է միայն մի քանի գործառույթ (բանալին ստանալը, կարգավորումը և ավելացումը; զանգվածի ստացում և ավելացում): Բացի այդ, Redis արձանագրությունը չափազանց էլեգանտ է և պարզ: Դուք նույնիսկ կարիք չունեք այն հատուկ ուսուցանելու: Հենց այն փաստը, որ արձանագրությունն ամբողջ աշխատանքը կատարում է շուրջ հարյուր տող կոդով, ցույց է տալիս, թե որքան լավ է այն մտածված:

Հետևյալ նկարը ցույց է տալիս, թե ինչ է անում հավելվածը, երբ հաճախորդը (բրաուզերը) պահանջում է /guestbookURL.

Linux ցանցային հավելվածի կատարումը: Ներածություն
Ինչպես է աշխատում հյուրերի գրքի հավելվածը

Երբ հյուրերի գրքի էջը պետք է թողարկվի, կա մեկ զանգ դեպի ֆայլային համակարգ՝ կաղապարը հիշողության մեջ կարդալու համար և երեք ցանցային զանգ դեպի Redis: Կաղապարի ֆայլը պարունակում է էջի HTML բովանդակության մեծ մասը վերևի սքրինշոթում: Կան նաև հատուկ տեղապահեր բովանդակության դինամիկ մասի համար՝ գրառումներ և այցելուների հաշվիչ։ Մենք դրանք ստանում ենք Redis-ից, տեղադրում ենք էջ և հաճախորդին տրամադրում լիարժեք ձևավորված բովանդակություն։ Երրորդ զանգը դեպի Redis կարելի է խուսափել, քանի որ Redis-ը վերադարձնում է նոր բանալի արժեքը, երբ ավելացվում է: Այնուամենայնիվ, մեր սերվերի համար, որն ունի ասինխրոն իրադարձությունների վրա հիմնված ճարտարապետություն, շատ ցանցային զանգեր լավ թեստ են ուսումնական նպատակների համար: Այսպիսով, մենք մերժում ենք այցելուների թվի Redis վերադարձի արժեքը և հարցում ենք անում առանձին զանգով:

Սերվերի ճարտարապետություն ZeroHTTPd

Մենք կառուցում ենք ZeroHTTPd-ի յոթ տարբերակ՝ նույն ֆունկցիոնալությամբ, բայց տարբեր ճարտարապետություններով.

  • Կրկնվող
  • Fork սերվեր (մեկ երեխայի գործընթաց յուրաքանչյուր հարցում)
  • Pre-fork սերվեր (գործընթացների նախնական պատառաքաղ)
  • Սերվեր կատարման թելերով (մեկ թեմա յուրաքանչյուր հարցում)
  • Սերվեր նախնական թելի ստեղծմամբ
  • Ճարտարապետության վրա հիմնված poll()
  • Ճարտարապետության վրա հիմնված epoll

Մենք չափում ենք յուրաքանչյուր ճարտարապետության կատարումը՝ սերվերը բեռնելով HTTP հարցումներով: Բայց բարձր զուգահեռ ճարտարապետությունները համեմատելիս հարցումների թիվը մեծանում է: Մենք երեք անգամ փորձարկում ենք և հաշվարկում միջինը:

Փորձարկման մեթոդաբանություն

Linux ցանցային հավելվածի կատարումը: Ներածություն
ZeroHTTPd բեռնվածության փորձարկման կարգավորում

Կարևոր է, որ թեստերն իրականացնելիս բոլոր բաղադրիչները չաշխատեն նույն մեքենայի վրա: Այս դեպքում ՕՀ-ն կրում է լրացուցիչ ժամանակացույց, քանի որ բաղադրիչները մրցում են CPU-ի համար: Ընտրված սերվերի ճարտարապետություններից յուրաքանչյուրի օպերացիոն համակարգի վերադիր չափումը այս վարժության ամենակարևոր նպատակներից է: Ավելի շատ փոփոխականներ ավելացնելը կվնասի գործընթացին: Հետևաբար, վերը նշված նկարի կարգավորումը լավագույնս աշխատում է:

Ի՞նչ է անում այս սերվերներից յուրաքանչյուրը:

  • load.unixism.net. Այստեղ մենք վազում ենք ab, Apache Benchmark կոմունալ. Այն առաջացնում է բեռ, որն անհրաժեշտ է մեր սերվերի ճարտարապետությունը փորձարկելու համար:
  • nginx.unixism.net. Երբեմն մենք ցանկանում ենք գործարկել սերվերային ծրագրի մեկից ավելի օրինակ: Դա անելու համար Nginx սերվերը համապատասխան կարգավորումներով աշխատում է որպես բեռի հավասարակշռող, որը գալիս է ab մեր սերվերի գործընթացներին:
  • zerohttpd.unixism.net. Այստեղ մենք գործարկում ենք մեր սերվերի ծրագրերը յոթ տարբեր ճարտարապետության վրա՝ մեկ առ մեկ:
  • redis.unixism.net. Այս սերվերը գործարկում է Redis daemon-ը, որտեղ պահվում են հյուրերի գրքի մուտքերը և այցելուների հաշվիչները:

Բոլոր սերվերները աշխատում են նույն պրոցեսորի միջուկով: Գաղափարը յուրաքանչյուր ճարտարապետության առավելագույն կատարումը գնահատելն է: Քանի որ բոլոր սերվերային ծրագրերը փորձարկվում են նույն սարքաշարի վրա, սա համեմատության հիմք է: Իմ թեստային կարգավորումը բաղկացած է Digital Ocean-ից վարձակալված վիրտուալ սերվերներից:

Ի՞նչ ենք մենք չափում:

Դուք կարող եք չափել տարբեր ցուցանիշներ: Մենք գնահատում ենք յուրաքանչյուր ճարտարապետության աշխատանքը տվյալ կոնֆիգուրացիայի մեջ՝ սերվերները բեռնելով զուգահեռության տարբեր մակարդակների հարցումներով.

Թեստի արդյունքներ

Հետևյալ գծապատկերը ցույց է տալիս սերվերների աշխատանքը տարբեր ճարտարապետությունների վրա՝ զուգահեռության տարբեր մակարդակներում: y առանցքը վայրկյանում հարցումների քանակն է, x առանցքը՝ զուգահեռ կապեր։

Linux ցանցային հավելվածի կատարումը: Ներածություն

Linux ցանցային հավելվածի կատարումը: Ներածություն

Linux ցանցային հավելվածի կատարումը: Ներածություն

Ստորև ներկայացված է աղյուսակ՝ արդյունքներով:

հարցումներ մեկ վայրկյանում

զուգահեռություն
կրկնվող
պատառաքաղ
նախնական պատառաքաղ
հոսք
նախնական հեռարձակում
քվեարկություն
էպոլլ

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 միաժամանակյա հարցումներից ավելին մեզ մնացել է ընդամենը երկու խաղացող՝ pre-fork և epoll: Քանի որ բեռը մեծանում է, հարցումների վրա հիմնված սերվերն ավելի վատ է աշխատում, քան հոսքայինը: Թելերի նախաստեղծման ճարտարապետությունը արժանի մրցակից է epoll-ին, վկայում է այն մասին, թե որքան լավ է Linux միջուկը պլանավորում մեծ թվով թելեր:

ZeroHTTPd աղբյուրի կոդը

ZeroHTTPd աղբյուրի կոդը այստեղ. Յուրաքանչյուր ճարտարապետության համար կա առանձին գրացուցակ:

ZeroHTTPd │ ├── 01_iterative │ ├── main.c ├── 02_forking │ ├── main.c ├── ├├── 03_preforking ├── _թելեր │ ├── հիմնական.c ├── 04_prethreading │ ├── main.c ├── 05_poll │ ├── main.c ├── 06_epoll │ └─├ └── └── ├── հիմնական. ├── index.html │ └── tux png └── կաղապարներ └── հյուրերի գիրք └── index.html

Բացի բոլոր ճարտարապետությունների համար յոթ գրացուցակներից, վերին մակարդակի գրացուցակում կան ևս երկուսը` հանրային և կաղապարներ: Առաջինը պարունակում է index.html ֆայլը և առաջին սքրինշոթի պատկերը: Դուք կարող եք այնտեղ տեղադրել այլ ֆայլեր և թղթապանակներ, և ZeroHTTPd-ը պետք է առանց որևէ խնդրի սպասարկի այդ ստատիկ ֆայլերը: Եթե ​​զննարկիչի ուղին համընկնում է հանրային թղթապանակի ուղու հետ, ապա ZeroHTTPd-ը փնտրում է index.html ֆայլը այս գրացուցակում: Հյուրերի գրքի բովանդակությունը ստեղծվում է դինամիկ: Այն ունի միայն գլխավոր էջ, և դրա բովանդակությունը հիմնված է «templates/guestbook/index.html» ֆայլի վրա: ZeroHTTPd-ը հեշտությամբ ավելացնում է դինամիկ էջեր ընդլայնման համար: Գաղափարն այն է, որ օգտվողները կարող են ձևանմուշներ ավելացնել այս գրացուցակում և անհրաժեշտության դեպքում երկարացնել ZeroHTTPd-ը:

Բոլոր յոթ սերվերները կառուցելու համար գործարկեք make all վերին մակարդակի գրացուցակից - և բոլոր կառուցումները կհայտնվեն այս գրացուցակում: Գործարկվող ֆայլերը փնտրում են հանրային և ձևանմուշների դիրեկտորիաներ այն գրացուցակում, որտեղից դրանք գործարկվել են:

Linux API

Այս հոդվածաշարի տեղեկատվությունը հասկանալու համար ձեզ հարկավոր չէ լավ տիրապետել Linux API-ին: Այնուամենայնիվ, ես խորհուրդ եմ տալիս ավելին կարդալ այս թեմայի վերաբերյալ, ինտերնետում կան բազմաթիվ տեղեկատու ռեսուրսներ: Թեև մենք կանդրադառնանք Linux API-ների մի քանի կատեգորիաների, մեր ուշադրությունը հիմնականում կենտրոնանալու է գործընթացների, շղթաների, իրադարձությունների և ցանցային ստեկի վրա: Բացի Linux API-ի մասին գրքերից և հոդվածներից, ես նաև խորհուրդ եմ տալիս կարդալ մանա համակարգային զանգերի և օգտագործվող գրադարանային գործառույթների համար:

Կատարողականություն և մասշտաբայնություն

Մեկ նշում կատարողականության և մասշտաբայնության մասին: Նրանց միջեւ տեսականորեն որեւէ կապ չկա։ Դուք կարող եք ունենալ վեբ ծառայություն, որը շատ լավ է աշխատում՝ մի քանի միլիվայրկյան արձագանքման ժամանակով, բայց այն ընդհանրապես չի ծավալվում: Նմանապես, կարող է լինել վատ կատարող վեբ հավելված, որի պատասխանը տևում է մի քանի վայրկյան, բայց այն տատանվում է տասնյակ հազարավոր միաժամանակյա օգտատերերի համար: Այնուամենայնիվ, բարձր կատարողականության և մասշտաբայնության համադրությունը շատ հզոր համադրություն է: Բարձր արդյունավետությամբ հավելվածները սովորաբար օգտագործում են ռեսուրսները խնայողաբար և այդպիսով արդյունավետ կերպով սպասարկում են սերվերի ավելի շատ միաժամանակ օգտագործողներ՝ նվազեցնելով ծախսերը:

CPU և I/O առաջադրանքներ

Ի վերջո, հաշվարկների մեջ միշտ կան երկու հնարավոր տեսակի առաջադրանքներ՝ I/O և CPU-ի համար: Ինտերնետով հարցումներ ստանալը (ցանցային I/O), ֆայլերի սպասարկումը (ցանցային և սկավառակի I/O), տվյալների բազայի հետ հաղորդակցվելը (ցանց և սկավառակի I/O) բոլոր I/O գործողություններն են: Տվյալների բազայի որոշ հարցումներ կարող են լինել մի փոքր ինտենսիվ պրոցեսոր (տեսակավորում, միջինում մեկ միլիոն արդյունք և այլն): Վեբ հավելվածների մեծ մասը սահմանափակված է առավելագույն հնարավոր I/O-ով, և պրոցեսորը հազվադեպ է օգտագործվում ամբողջ հզորությամբ: Երբ տեսնում եք, որ որոշ I/O առաջադրանք օգտագործում է մեծ քանակությամբ պրոցեսոր, դա, ամենայն հավանականությամբ, կիրառման վատ ճարտարապետության նշան է: Սա կարող է նշանակել, որ պրոցեսորի ռեսուրսները վատնվում են գործընթացի կառավարման և համատեքստի փոխարկման վրա, և դա ամբողջովին օգտակար չէ: Եթե ​​դուք ինչ-որ բան եք անում, ինչպիսին է պատկերի մշակումը, աուդիո ֆայլերի փոխակերպումը կամ մեքենայական ուսուցումը, ապա հավելվածը պահանջում է հզոր պրոցեսորի ռեսուրսներ: Բայց շատ ծրագրերի համար դա այդպես չէ:

Իմացեք ավելին սերվերի ճարտարապետության մասին

  1. Մաս I. Կրկնվող ճարտարապետություն
  2. Մաս II. Fork սերվերներ
  3. Մաս III. Pre-fork սերվերներ
  4. Մաս IV. Սերվերներ կատարման թելերով
  5. Մաս V. Նախնական պարուրակային սերվերներ
  6. Մաս VI. Պոլի վրա հիմնված ճարտարապետություն
  7. Մաս VII. epoll-ի վրա հիմնված ճարտարապետություն

Source: www.habr.com

Добавить комментарий