Mail.ru Group-ում մենք ունենք Tarantool. սա հավելված սերվեր է Lua-ում, որը նաև կրկնապատկվում է որպես տվյալների բազա (կամ հակառակը): Այն արագ և զով է, բայց մեկ սերվերի հնարավորությունները դեռևս անսահմանափակ չեն: Ուղղահայաց մասշտաբը նույնպես համադարման չէ, ուստի Tarantool-ն ունի գործիքներ հորիզոնական մասշտաբավորման համար՝ vshard մոդուլը
Լավ նորություն. մենք հավաքել ենք մի քանի մեծ կադրեր (օրինակ
Կոնկրետ ո՞րն է խնդիրը։
Տարանտուլա ունենք, վշարդ ունենք, էլ ի՞նչ ուզես։
Նախ, դա հարմարության խնդիր է: Vshard-ի կոնֆիգուրացիան կազմաձևված է Lua աղյուսակների միջոցով: Որպեսզի Tarantool-ի բազմաթիվ պրոցեսների բաշխված համակարգը ճիշտ աշխատի, կոնֆիգուրացիան պետք է ամենուր նույնը լինի: Ոչ ոք չի ցանկանում դա անել ձեռքով: Հետևաբար, օգտագործվում են բոլոր տեսակի սցենարներ, Ansible և տեղակայման համակարգեր:
Քարթրիջն ինքն է կառավարում vshard-ի կոնֆիգուրացիան, դա անում է դրա հիման վրա սեփական բաշխված կոնֆիգուրացիա. Դա, ըստ էության, պարզ YAML ֆայլ է, որի պատճենը պահվում է Tarantool-ի յուրաքանչյուր օրինակում: Պարզեցումն այն է, որ շրջանակն ինքն է վերահսկում իր կազմաձևումը և ապահովում, որ այն նույնն է ամենուր:
Երկրորդ, դա կրկին հարմարության խնդիր է։ vshard կոնֆիգուրացիան կապ չունի բիզնես տրամաբանության զարգացման հետ և միայն շեղում է ծրագրավորողին իր աշխատանքից։ Երբ մենք քննարկում ենք նախագծի ճարտարապետությունը, մենք ամենից հաճախ խոսում ենք առանձին բաղադրիչների և դրանց փոխազդեցության մասին: Դեռ վաղ է մտածել 3 տվյալների կենտրոններում կլաստեր ստեղծելու մասին:
Մենք նորից ու նորից լուծեցինք այս խնդիրները, և ինչ-որ պահի մեզ հաջողվեց մշակել մի մոտեցում, որը պարզեցնում էր հավելվածի հետ աշխատանքը նրա ողջ կյանքի ցիկլի ընթացքում՝ ստեղծում, մշակում, փորձարկում, CI/CD, սպասարկում:
Քարթրիջը ներկայացնում է դերի հայեցակարգը Tarantool-ի յուրաքանչյուր գործընթացի համար: Դերը հասկացություն է, որը թույլ է տալիս ծրագրավորողին կենտրոնանալ կոդ գրելու վրա: Նախագծում առկա բոլոր դերերը կարող են գործարկվել Tarantool-ի մեկ օրինակով, և դա բավական կլինի թեստերի համար:
Tarantool Cartridge-ի հիմնական հատկանիշները.
- ավտոմատացված կլաստերային խմբավորում;
- ընդլայնելով հավելվածի ֆունկցիոնալությունը՝ օգտագործելով նոր դերեր.
- Ծրագրի ձևանմուշ մշակման և տեղակայման համար;
- ներկառուցված ավտոմատ Sharing;
- ինտեգրում Luatest թեստավորման շրջանակին;
- կլաստերի կառավարում WebUI-ի և API-ի միջոցով;
- փաթեթավորման և տեղակայման գործիքներ:
Բարեւ աշխարհ!
Ես չեմ կարող սպասել, որ ցուցադրվի հենց շրջանակը, այնպես որ մենք ճարտարապետության մասին պատմությունը կթողնենք ավելի ուշ և կսկսենք պարզ բանից: Եթե ենթադրենք, որ Tarantool-ն ինքն արդեն տեղադրված է, ապա մնում է անել
$ tarantoolctl rocks install cartridge-cli
$ export PATH=$PWD/.rocks/bin/:$PATH
Այս երկու հրամանները կտեղադրեն հրամանի տողի կոմունալ ծառայությունները և թույլ կտան ստեղծել ձեր առաջին հավելվածը ձևանմուշից.
$ cartridge create --name myapp
Եվ սա այն է, ինչ մենք ստանում ենք.
myapp/
├── .git/
├── .gitignore
├── app/roles/custom.lua
├── deps.sh
├── init.lua
├── myapp-scm-1.rockspec
├── test
│ ├── helper
│ │ ├── integration.lua
│ │ └── unit.lua
│ ├── helper.lua
│ ├── integration/api_test.lua
│ └── unit/sample_test.lua
└── tmp/
Սա git պահոց է պատրաստի «Բարև, աշխարհ»: դիմումը. Եկեք փորձենք գործարկել այն անմիջապես, նախապես տեղադրելով կախվածությունները (ներառյալ ինքնին շրջանակը).
$ tarantoolctl rocks make
$ ./init.lua --http-port 8080
Այսպիսով, մենք ունենք մեկ հանգույց, որն աշխատում է ապագա բեկորային հավելվածի համար: Հետաքրքրասեր աշխարհականը կարող է անմիջապես բացել վեբ ինտերֆեյսը, մկնիկի միջոցով կարգավորել մեկ հանգույցի կլաստեր և վայելել արդյունքը, բայց դեռ վաղ է ուրախանալու համար: Առայժմ հավելվածը ոչ մի օգտակար բան չի կարող անել, այնպես որ ես ձեզ ավելի ուշ կպատմեմ տեղակայման մասին, բայց հիմա ժամանակն է գրել կոդ:
Դիմումների մշակում
Պարզապես պատկերացրեք, մենք նախագծում ենք մի նախագիծ, որը պետք է ստանա տվյալներ, պահպանի դրանք և ստեղծի հաշվետվություն օրական մեկ անգամ:
Մենք սկսում ենք գծապատկեր նկարել և դրա վրա տեղադրել երեք բաղադրիչ՝ դարպաս, պահեստ և ժամանակացույց: Մենք շարունակում ենք աշխատել ճարտարապետության վրա: Քանի որ մենք օգտագործում ենք vshard-ը որպես պահեստ, մենք սխեմային ավելացնում ենք vshard-router և vshard-storage: Ո՛չ դարպասը, ո՛չ ժամանակացույցն ուղղակիորեն մուտք չեն գործի պահոց. հենց դրա համար է երթուղիչը, դրա համար է այն ստեղծվել:
Այս դիագրամը դեռ ճշգրիտ չի ներկայացնում, թե ինչ ենք կառուցելու նախագծում, քանի որ բաղադրիչները վերացական տեսք ունեն: Մենք դեռ պետք է տեսնենք, թե ինչպես է դա նախագծվելու իրական Tarantool-ի վրա. եկեք խմբավորենք մեր բաղադրիչներն ըստ գործընթացի:
Առանձին ատյաններում vshard-router-ը և gateway-ը պահելը քիչ իմաստ ունի: Ինչու՞ պետք է ևս մեկ անգամ շրջել ցանցում, եթե դա արդեն երթուղիչի պարտականությունն է: Դրանք պետք է իրականացվեն նույն գործընթացի շրջանակներում: Այսինքն՝ և՛ gateway-ը, և՛ vshard.router.cfg-ը սկզբնավորվում են մեկ պրոցեսում, և թող դրանք փոխազդեն լոկալ։
Դիզայնի փուլում հարմար էր աշխատել երեք բաղադրիչի հետ, բայց ես՝ որպես ծրագրավորող, կոդը գրելիս չեմ ուզում մտածել Tarnatool-ի երեք օրինակ գործարկելու մասին։ Պետք է թեստեր անցկացնեմ և ստուգեմ, որ ճիշտ եմ գրել gateway-ը: Կամ գուցե ես ուզում եմ իմ գործընկերներին ցույց տալ մի առանձնահատկություն: Ինչու՞ ես պետք է անցնեմ երեք օրինակ տեղակայելու դժվարությունների միջով: Այսպես ծնվեց դերեր հասկացությունը։ Դերը սովորական luash մոդուլ է, որի կյանքի ցիկլը կառավարվում է Քարթրիջի կողմից: Այս օրինակում դրանք չորսն են՝ դարպաս, երթուղիչ, պահեստ, ժամանակացույց: Մեկ այլ նախագծում կարող է ավելին լինել: Բոլոր դերերը կարող են իրականացվել մեկ գործընթացում, և դա բավարար կլինի:
Եվ երբ խոսքը վերաբերում է բեմադրության կամ արտադրության տեղակայմանը, ապա մենք Tarantool-ի յուրաքանչյուր գործընթացին կհատկացնենք իր դերերը՝ կախված ապարատային հնարավորություններից.
Տոպոլոգիայի կառավարում
Տեղեկություններ այն մասին, թե որտեղ են առաջադրվում դերերը, պետք է ինչ-որ տեղ պահվեն: Եվ սա «ինչ-որ տեղ» բաշխված կոնֆիգուրացիան է, որը ես արդեն նշեցի վերևում: Դրա հետ կապված ամենակարևորը կլաստերային տոպոլոգիան է։ Ահա 3 Tarantool գործընթացների 5 կրկնօրինակման խմբեր.
Մենք չենք ցանկանում կորցնել տվյալները, ուստի մենք խնամքով ենք վերաբերվում ընթացիկ գործընթացների մասին տեղեկատվությանը: Քարթրիջը հետևում է կոնֆիգուրացիային՝ օգտագործելով երկփուլային կատարում: Երբ մենք ցանկանում ենք թարմացնել կոնֆիգուրացիան, այն նախ ստուգում է, որ բոլոր օրինակները հասանելի են և պատրաստ են ընդունելու նոր կազմաձևը: Դրանից հետո երկրորդ փուլը կիրառում է կազմաձևը: Այսպիսով, եթե նույնիսկ մեկ օրինակ պարզվի, որ ժամանակավորապես անհասանելի է, ոչ մի վատ բան տեղի չի ունենա: Կազմաձևը պարզապես չի կիրառվի, և դուք նախապես սխալ կտեսնեք:
Նաև տոպոլոգիայի բաժնում նշվում է այնպիսի կարևոր պարամետր, ինչպիսին է յուրաքանչյուր կրկնօրինակման խմբի առաջատարը: Սովորաբար սա այն պատճենն է, որը ձայնագրվում է: Մնացածն ամենից հաճախ միայն կարդալու համար է, թեև կարող են լինել բացառություններ: Երբեմն խիզախ ծրագրավորողները չեն վախենում կոնֆլիկտներից և կարող են զուգահեռաբար տվյալներ գրել մի քանի կրկնօրինակների վրա, սակայն կան որոշ գործողություններ, որոնք, անկախ ամեն ինչից, չպետք է երկու անգամ կատարվեն։ Դրա համար կա առաջնորդի նշան:
Դերերի կյանք
Որպեսզի վերացական դերը գոյություն ունենա նման ճարտարապետության մեջ, շրջանակը պետք է ինչ-որ կերպ կառավարի դրանք: Բնականաբար, վերահսկողությունը տեղի է ունենում առանց Tarantool-ի գործընթացը վերսկսելու: Դերերը կառավարելու համար կա 4 հետ կանչ: Քարթրիջն ինքը կանվանի դրանք՝ կախված նրանից, թե ինչ է գրված իր բաշխված կազմաձևում՝ դրանով իսկ կիրառելով կոնֆիգուրացիան կոնկրետ դերերի վրա:
function init()
function validate_config()
function apply_config()
function stop()
Յուրաքանչյուր դեր ունի իր գործառույթը init
. Այն կոչվում է մեկ անգամ, երբ դերը միացված է, կամ երբ Tarantool-ը վերագործարկվում է: Այնտեղ հարմար է, օրինակ, նախաստորագրել box.space.create-ը, կամ ժամանակացույցը կարող է գործարկել որոշ ֆոնային մանրաթել, որը կկատարի աշխատանքը որոշակի ժամանակային ընդմիջումներով:
Մեկ գործառույթ init
կարող է բավարար չլինել: Քարթրիջը դերերին թույլ է տալիս օգտվել բաշխված կոնֆիգուրացիայից, որն օգտագործում է տոպոլոգիան պահելու համար: Մենք կարող ենք նույն կոնֆիգուրացիայում նոր բաժին հայտարարել և դրանում պահել բիզնեսի կոնֆիգուրացիայի մի հատված: Իմ օրինակում սա կարող է լինել տվյալների սխեման կամ ժամանակացույցի կարգավորումներ ժամանակացույցի դերի համար:
Կլաստերային զանգեր validate_config
и apply_config
ամեն անգամ, երբ բաշխված կոնֆիգուրացիան փոխվում է: Երբ կոնֆիգուրացիան կիրառվում է երկփուլային կատարման միջոցով, կլաստերը ստուգում է, որ յուրաքանչյուր դերը պատրաստ է ընդունել այս նոր կազմաձևը և, անհրաժեշտության դեպքում, սխալի մասին հաղորդում է օգտվողին: Երբ բոլորը համաձայնում են, որ կոնֆիգուրացիան նորմալ է, ապա apply_config
.
Նաև դերերն ունեն մեթոդ stop
, որն անհրաժեշտ է դերի արդյունքը մաքրելու համար: Եթե ասենք, որ ժամանակացույցն այլևս անհրաժեշտ չէ այս սերվերում, այն կարող է դադարեցնել այն մանրաթելերը, որոնք սկսել է օգտագործել init
.
Դերերը կարող են փոխազդել միմյանց հետ: Մենք սովոր ենք Lua-ով ֆունկցիայի կանչեր գրել, բայց կարող է պատահել, որ տվյալ պրոցեսը չունենա մեզ անհրաժեշտ դերը։ Ցանցով զանգերը հեշտացնելու համար մենք օգտագործում ենք rpc (հեռավոր ընթացակարգի զանգ) օժանդակ մոդուլը, որը կառուցված է Tarantool-ում ներկառուցված ստանդարտ netbox-ի հիման վրա: Սա կարող է օգտակար լինել, եթե, օրինակ, ձեր gateway-ը ցանկանում է ուղղակիորեն խնդրել ժամանակացույցին կատարել աշխատանքը հենց հիմա, այլ ոչ թե սպասել մեկ օր:
Մյուս կարևոր կետը սխալների հանդուրժողականության ապահովումն է: Քարթրիջը օգտագործում է SWIM արձանագրությունը՝ առողջությունը վերահսկելու համար
Այս արձանագրության հիման վրա Քարթրիջը կազմակերպում է խափանումների ավտոմատ մշակում: Յուրաքանչյուր գործընթաց վերահսկում է իր միջավայրը, և եթե առաջնորդը հանկարծ դադարի արձագանքել, կրկնօրինակը կարող է ստանձնել իր դերը, և Քարթրիջը համապատասխանաբար կարգավորում է գործող դերերը:
Այստեղ դուք պետք է զգույշ լինեք, քանի որ հաճախակի հետ ու առաջ անցնելը կարող է հանգեցնել տվյալների հակասությունների՝ կրկնօրինակման ժամանակ: Իհարկե, դուք չպետք է պատահականորեն միացնեք ավտոմատ ձախողումը: Մենք պետք է հստակ հասկանանք, թե ինչ է կատարվում և վստահ լինենք, որ առաջնորդի վերականգնումից և թագը նրան վերադարձնելուց հետո կրկնօրինակումը չի կոտրվի։
Այս ամենից դուք կարող եք տպավորություն ստանալ, որ դերերը նման են միկրոսերվիսներին: Ինչ-որ իմաստով դրանք հենց դա են, միայն որպես մոդուլներ Tarantool գործընթացների ներսում: Բայց կան նաև մի շարք հիմնարար տարբերություններ. Նախ, նախագծի բոլոր դերերը պետք է ապրեն նույն կոդի բազայում: Եվ Tarantool-ի բոլոր պրոցեսները պետք է գործարկվեն նույն կոդային բազայից, որպեսզի այնպիսի անակնկալներ չլինեն, ինչպիսիք են, երբ մենք փորձում ենք նախաստորագրել ժամանակացույցը, բայց այն պարզապես գոյություն չունի: Նաև չպետք է թույլ տաք կոդի տարբերակների տարբերություններ, քանի որ նման իրավիճակում համակարգի վարքագիծը շատ դժվար է կանխատեսել և կարգաբերել:
Ի տարբերություն Docker-ի, մենք չենք կարող պարզապես դերի «պատկեր» վերցնել, այն տեղափոխել մեկ այլ սարք և գործարկել այնտեղ: Մեր դերերը այնքան մեկուսացված չեն, որքան Docker կոնտեյներները: Բացի այդ, մենք չենք կարող երկու նույնական դերեր կատարել մեկ օրինակում: Դերը կա՛մ կա, կա՛մ չկա, ինչ-որ իմաստով դա միայնակ է: Եվ երրորդը, դերերը պետք է նույնը լինեն ամբողջ վերարտադրման խմբում, քանի որ հակառակ դեպքում դա անհեթեթ կլինի. տվյալները նույնն են, բայց կոնֆիգուրացիան տարբեր է:
Տեղակայման գործիքներ
Ես խոստացա ցույց տալ, թե ինչպես է Քարտրիջն օգնում տեղակայել հավելվածները: Ուրիշների կյանքը հեշտացնելու համար շրջանակը փաթեթավորում է RPM փաթեթներ.
$ cartridge pack rpm myapp -- упакует для нас ./myapp-0.1.0-1.rpm
$ sudo yum install ./myapp-0.1.0-1.rpm
Տեղադրված փաթեթը պարունակում է գրեթե այն ամենը, ինչ ձեզ հարկավոր է՝ և՛ հավելվածը, և՛ տեղադրված կախվածությունները: Tarantool-ը նույնպես կհայտնվի սերվերում՝ որպես RPM փաթեթի կախվածություն, և մեր ծառայությունը պատրաստ է գործարկման: Սա արվում է systemd-ի միջոցով, բայց նախ պետք է մի փոքր կոնֆիգուրացիա գրել։ Նվազագույնը նշեք յուրաքանչյուր գործընթացի URI-ը: Օրինակ երեքը բավական է.
$ sudo tee /etc/tarantool/conf.d/demo.yml <<CONFIG
myapp.router: {"advertise_uri": "localhost:3301", "http_port": 8080}
myapp.storage_A: {"advertise_uri": "localhost:3302", "http_enabled": False}
myapp.storage_B: {"advertise_uri": "localhost:3303", "http_enabled": False}
CONFIG
Այստեղ մի հետաքրքիր նրբերանգ կա. Միայն երկուական արձանագրության պորտը նշելու փոխարեն, մենք նշում ենք գործընթացի ողջ հանրային հասցեն, ներառյալ հոսթի անունը: Սա անհրաժեշտ է, որպեսզի կլաստերային հանգույցները իմանան, թե ինչպես միանալ միմյանց: Վատ գաղափար է օգտագործել 0.0.0.0 որպես advertise_uri հասցե, այն պետք է լինի արտաքին IP հասցե, այլ ոչ թե վարդակից: Առանց դրա, ոչինչ չի աշխատի, ուստի Քարթրիջը պարզապես թույլ չի տա ձեզ սխալ advertise_uri հանգույց գործարկել:
Այժմ, երբ կազմաձևումը պատրաստ է, կարող եք սկսել գործընթացները: Քանի որ սովորական համակարգային միավորը թույլ չի տալիս մեկից ավելի գործընթաց սկսել, Քարթրիջի վրա հավելվածները տեղադրվում են այսպես կոչված. ցուցված միավորներ, որոնք աշխատում են այսպես.
$ sudo systemctl start myapp@router
$ sudo systemctl start myapp@storage_A
$ sudo systemctl start myapp@storage_B
Կազմաձևում մենք նշել ենք HTTP պորտը, որի վրա Քարթրիջը սպասարկում է վեբ ինտերֆեյսը - 8080: Եկեք գնանք դրան և նայենք.
Մենք տեսնում ենք, որ թեև գործընթացներն աշխատում են, բայց դրանք դեռ կազմաձևված չեն: Քարթրիջը դեռ չգիտի, թե ով ում հետ պետք է կրկնօրինակի և չի կարող ինքնուրույն որոշում կայացնել, ուստի սպասում է մեր գործողություններին։ Բայց մենք մեծ ընտրություն չունենք. նոր կլաստերի կյանքը սկսվում է առաջին հանգույցի կազմաձևումից: Այնուհետև մենք կավելացնենք մյուսներին կլաստերի մեջ, նրանց դերեր կհատկացնենք, և այս պահին տեղակայումը կարելի է հաջողությամբ ավարտված համարել:
Եկեք մի բաժակ լցնենք ձեր սիրելի ըմպելիքը և հանգստանանք երկար աշխատանքային շաբաթից հետո։ Հավելվածը կարող է օգտագործվել:
Արդյունքները
Որո՞նք են արդյունքները: Փորձեք այն, օգտագործեք այն, թողեք հետադարձ կապ, ստեղծեք տոմսեր Github-ում:
Սայլակ
[1]
Source: www.habr.com