Што мы ведаем пра мікрасэрвісы

Прывітанне! Мяне клічуць Вадзім Мадысан, я кірую распрацоўкай System Platform Авіта. Аб тым, як мы ў кампаніі пераходзім з маналітнай архітэктуры на мікрасэрвісную, было сказанае не раз. Час падзяліцца тым, як мы пераўтварылі сваю інфраструктуру, каб атрымаць з мікрасэрвісаў максімум карысці і не даць сабе ў іх згубіцца. Як нам тут дапамагае PaaS, як мы спрасцілі дэплой і звялі стварэнне мікрасэрвісу да аднаго кліку - чытайце далей. Не ўсё, пра што я пішу ніжэй, у Авіта рэалізавана ў поўнай меры, частка - тое, як мы развіваем нашу платформу.

(А яшчэ ў канцы гэтага артыкула я раскажу аб магчымасці патрапіць на трохдзённы семінар ад эксперта па мікрасэрвіснай архітэктуры Крыса Рычардсана).

Што мы ведаем пра мікрасэрвісы

Як мы прыйшлі да мікрасэрвісаў

Авіта - адзін з найбуйнейшых у свеце класіфайдаў, на ім публікуецца больш за 15 млн новых аб'яў у суткі. Наш бэкенд прымае больш за 20 тыс. запытаў у секунду. Цяпер у нас некалькі сотняў мікрасэрвісаў.

Мікрасэрвісную архітэктуру мы выбудоўваем не першы год. Як менавіта нашы калегі дэталях распавялі на нашай секцыі на РИТ++ 2017. На CodeFest 2017 (гл. відэа), Сяргей Арлоў і Міхаіл Пракапчук падрабязна патлумачылі, навошта нам увогуле спатрэбіўся пераход да мікрасэрвісаў і якую ролю тут у нас граў Kubernetes. Ну а зараз мы робім усё, каб звесці да мінімуму тыя выдаткі маштабавання, якія такой архітэктуры ўласцівыя.

Першапачаткова мы не рабілі экасістэму, якая ўсебакова дапамагала б нам у распрацоўцы і запуску мікрасэрвісаў. Проста збіралі тлумачальныя апенсорсныя рашэнні, запускалі іх у сябе і прапаноўвалі распрацоўніку разабрацца з імі. У выніку той хадзіў у дзясятак месцаў (дашборды, унутраныя сэрвісы), пасля чаго ўмацоўваўся ў імкненні пілаваць код па-старому, у маналіце. Зялёным колерам на схемах ніжэй пазначана тое, што робіць распрацоўшчык так ці інакш сваімі рукамі, жоўтым колерам - аўтаматызацыя.

Што мы ведаем пра мікрасэрвісы

Цяпер у CLI-ўтыліце PaaS адной камандай ствараецца новы сэрвіс, а яшчэ двума дадаецца новая база дадзеных і дэплоі ў Stage.

Што мы ведаем пра мікрасэрвісы

Як пераадолець эпоху «мікрасэрвіснай раздробненасці»

Пры маналітнай архітэктуры, дзеля кансістэнтнасці змен у прадукце распрацоўнікі былі змушаныя разбірацца, што дзеецца ў суседзяў. Пры працы па новай архітэктуры кантэксты сэрвісаў перасталі залежаць сябар ад сябра.

Акрамя таго, каб мікрасэрвісная архітэктура была эфектыўнай, патрабуецца наладзіць мноства працэсаў, а менавіта:

• лагіраванне;
• трасіроўка запытаў (Jaeger);
• агрэгацыя памылак (Sentry);
• статуты, паведамленні, падзеі з Kubernetes (Event Stream Processing);
• race limit / circuit breaker (можна выкарыстоўваць Hystrix);
• кантроль складнасці сэрвісаў (мы выкарыстоўваем Netramesh);
• маніторынг (Grafana);
• зборка (TeamCity);
• зносіны і натыфікацыя (Slack, email);
• трэкінг задач; (Jira)
• складанне дакументацыі.

Каб па меры маштабавання сістэма не страціла цэласнасць і заставалася эфектыўнай, мы пераасэнсавалі арганізацыю працы мікрасэрвісаў у Авіта.

Як мы кіруемся з мікрасэрвісамі

Праводзіць адзіную «палітыку партыі» сярод мноства мікрасэрвісаў Авіта дапамагаюць:

  • падзел інфраструктуры на пласты;
  • канцэпцыя Platform as a Service (PaaS);
  • маніторынг за ўсё, што з мікрасэрвісамі адбываецца.

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

A. Верхні - service mesh. Спачатку мы спрабавалі Istio, але аказалася, што ён выкарыстоўвае занадта шмат рэсурсаў, што на нашых аб'ёмах выходзіць залішне дорага. Таму старшы інжынер у камандзе архітэктуры Аляксандр Лук'янчанка распрацаваў уласнае рашэнне - Netramesh (даступна ў Open Source), якое мы зараз выкарыстоўваем у прадакшэне і якое спажывае ў некалькі разоў менш рэсурсаў, чым Istio (але і робіць не ўсё, чым можа пахваліцца Istio).
B. Сярэдні - Kubernetes. На ім мы разгортваем і эксплуатуем мікрасэрвісы.
C. Ніжні - bare metal. Мы не выкарыстоўваем аблокі і штукі тыпу OpenStack, а сядзім цалкам на bare metal.

Усе пласты аб'ядноўваюцца PaaS. А платформа гэтая, у сваю чаргу, складаецца з трох частак.

I. Генератары, кіраваныя праз CLI-ўтыліту. Менавіта яна дапамагае распрацоўніку стварыць мікрасэрвіс па-правільнаму і з мінімумам намаганняў.

II. Зводны калектар з кантролем усіх інструментаў праз агульны дашборд.

III. Сховішча. Стыкуецца з планіроўшчыкамі, якія аўтаматычна выстаўляюць трыгеры на значныя дзеянні. Дзякуючы такой сістэме ні адна задача не аказваецца выпушчанай толькі з-за таго, што нехта забыўся паставіць сабе цяг у Jira. Мы для гэтага выкарыстаем унутраную прыладу пад назовам Atlas.

Што мы ведаем пра мікрасэрвісы

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

Як уладкованы стандартны канвеер распрацоўкі мікрасэрвісу

У агульным выглядзе ланцужок стварэння мікрасэрвісу выглядае наступным чынам:

CLI-push → Continuous Integration → Bake → Дэплой → Штучныя тэсты → Canary-тэсты → Squeeze Testing → Прадакшэн → Абслугоўванне.

Пройдземся па ёй роўна ў такой паслядоўнасці.

CLI-push

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

У рэшце рэшт мы збудавалі простую CLI-ўтыліту, якая аўтаматызуе асноўныя крокі пры стварэнні мікрасэрвісу. Фактычна яна замяняе першы git push. Вось што менавіта яна робіць.

- Стварае сэрвіс па шаблоне - пакрокава, у рэжыме «візарда». У нас ёсць шаблоны для асноўных моў праграмавання ў бэкендзе Авіта: PHP, Golang і Python.

- Па адной камандзе разгортвае асяроддзе для лакальнай распрацоўкі на канкрэтнай машыне - паднімаецца Minikube, Helm-чарты аўтаматычна генеруюцца і запускаюцца ў лакальным kubernetes'е.

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

- Сама выконвае live-зборку. Дапусцім, распрацоўшчык паправіў нешта ў мікрасэрвісе праз сваю IDE. Утыліта бачыць змены ў файлавай сістэме і зыходзячы з іх перазбірае прыкладанне (для Golang) і перазапускае. Для PHP мы проста пракідваем дырэкторыю ўнутр куба і там live-reload атрымліваецца аўтаматам .

- Генеруе аўтатэсты. У выглядзе даўбешак, але цалкам прыдатных да выкарыстання.

• Дэплой мікрасэрвісу.

Разгортваць мікрасэрвіс у нас раней было крыху моташна. У абавязковым парадку патрабаваліся:

I. Dockerfile.

II. Канфіг.
III. Helm-чарт, які сам па сабе грувасткі і ўключае ў сябе:

- самі чарты;
- шаблоны;
- канкрэтныя значэнні з улікам розных асяроддзяў.

Мы пазбавіліся ад болю з перарабляннем маніфестаў Kubernetes, і зараз яны генеруюцца аўтаматычна. Але галоўнае, спрасцілі да мяжы дэплой. З гэтага часу ў нас ёсць Dockerfile, а ўвесь канфіг распрацоўнік прапісвае ў адным-адзіным кароткім файле app.toml.

Што мы ведаем пра мікрасэрвісы

Ды і ў самым app.toml зараз спраў на хвіліну. Прапісваем, дзе колькі дзід сэрвісу паднімаць (на dev-серверы, на staging, на прадакшэне), паказваем яго залежнасці. Звярніце ўвагу на радок size = "small" у блоку [engine]. Гэта ліміт, які будзе выдзелены сэрвісу праз Kubernetes.

Далей на базе канфіга аўтаматычна генеруюцца ўсе неабходныя Helm-чарты і ствараюцца падлучэнні да баз дадзеных.

• Базавая валідацыя. Такія праверкі таксама аўтаматызаваны.
Трэба адсочваць:
- ці ёсць Dockerfile;
- ці ёсць app.toml;
- Ці ёсць дакументацыя;
- Ці ў парадку залежнасці;
- Ці зададзены правілы алертаў.
Да апошняга пункта: уладальнік сэрвісу сам паказвае, якія прадуктовыя метрыкі маніторыць.

• Падрыхтоўка дакументацыі.
Да гэтага часу праблемнае месца. Накшталт самае відавочнае, але разам з тым і рэкордна «часта забываемае», а значыць, і ўразлівае звяно ланцужкі.
Неабходна, каб дакументацыя была пад кожны мікрасэрвіс. Уваходзяць у яе наступныя блокі.

I. Кароткае апісанне сэрвісу. Літаральна некалькі прапаноў аб тым, што ён робіць і для чаго патрэбен.

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

III. Runbook. Кароткі гайд па запуску сэрвісу і тонкасцям абыходжання з ім.

IV. FAQ, Дзе добра было б апярэдзіць праблемы, з якімі могуць сутыкнуцца вашыя калегі пры працы з сэрвісам.

V. Апісанне endpoints для API. Калі раптам вы не ўказалі кропкі прызначэння, расплачвацца за гэта амаль напэўна будуць калегі, чые мікрасэрвісы злучаны з вашым. Цяпер у нас для гэтага выкарыстоўваецца Swagger і наша рашэнне пад назовам brief.

VI. Labels. Або маркеры, якія паказваюць, да якога прадукта, функцыянальнасці, структурнаму падраздзяленню кампаніі ставіцца сэрвіс. Дапамагаюць хутка зразумець, напрыклад, ці не пілуеце вы функцыянальнасць, якую тыдзень таму выкацілі для таго ж бізнэс-юніта вашы калегі.

VII. Уладальнік ці ўладальнікі сэрвісу. У большасці выпадкаў яго - ці іх - з дапамогай PaaS атрымліваецца вызначыць аўтаматычна, але для страхоўкі мы патрабуем ад распрацоўніка паказваць іх і ўручную.

Нарэшце, добрая практыка - праводзіць рэўю дакументацыі, па аналогіі з code review.

Бесперапынная інтэграцыя

  • Падрыхтоўка рэпазітароў.
  • Стварэнне пайплайна ў TeamCity.
  • Выстаўленне правоў.
  • Пошук уладальнікаў сэрвісу. Тут гібрыдная схема ручная маркіроўка і мінімальная аўтаматыка ад PaaS. Цалкам аўтаматычная схема дае збоі пры перадачы сэрвісаў у падтрымку ў іншую каманду распрацоўкі ці, напрыклад, калі распрацоўшчык сэрвісу звольніўся.
  • Рэгістрацыя сэрвісу ў Atlas (гл. Вышэй). З усімі яго ўладальнікамі і залежнасцямі.
  • Праверка міграцый. Правяраем, ці няма сярод іх патэнцыйна небяспечных. Напрыклад, у адной з іх усплывае alter table ці яшчэ нешта здольнае парушыць сумяшчальнасць схемы дадзеных паміж рознымі версіямі сэрвісу. Тады міграцыя не выконваецца, а ставіцца ў падпіску - PaaS павінна прасігналіць уладальніку сэрвісу калі стане бяспечна яе прымяніць.

выпякаць

Наступная стадыя - упакоўка сэрвісаў перад дэплоем.

  • Зборка прыкладання. Па класіцы - у Docker-вобраз.
  • Генерацыя Helm-чартаў для самога сэрвісу і злучаных з ім рэсурсаў. У тым ліку для баз даных і кэша. Ствараюцца яны аўтаматычна ў адпаведнасці з тым канфігам app.toml, які быў сфарміраваны на стадыі CLI-push.
  • Стварэнне тыкетаў адмінам на адкрыццё партоў (калі гэта патрабуецца).
  • Прагон юніт-тэстаў і падлік code coverage. Калі пакрыццё кода ніжэй зададзенага парогавага значэння, то, хутчэй за ўсё, далей - на дэплой - сэрвіс не пройдзе. Калі яно на грані дапушчальнага, то сэрвісу будзе прысвоены «песімізавальны» каэфіцыент: тады пры адсутнасці паляпшэнняў паказчыка з цягам часу распрацоўнік атрымае апавяшчэнне аб тым, што прагрэсу па частцы тэстаў няма (і трэба б нешта з гэтым зрабіць).
  • Улік абмежаванняў па памяці і CPU. У асноўным мікрасэрвісы мы пішам на Golang і запускаем іх у Kubernetes. Адгэтуль адна тонкасць, злучаная з асаблівасцю мовы Golang: па змаўчанні пры запуску задзейнічаюцца ўсе ядры на машыне, калі ў відавочным выглядзе не выставіць зменную GOMAXPROCS і калі на адной машыне запускаецца некалькі такіх сэрвісаў, то яны пачынаюць канкураваць за рэсурсы, мяшаючы адзін аднаму. На графіках ніжэй паказана, як мяняецца час выканання, калі запусціць прыкладанне без канкурэнцыі і ў рэжыме гонкі за рэсурсы. (Зыходнікі графікаў ляжаць тут).

Што мы ведаем пра мікрасэрвісы

Час выканання, менш - лепш. Максімум: 643ms, мінімум: 42ms. Фота клікабельна.

Што мы ведаем пра мікрасэрвісы

Час на аперацыю, менш - лепш. Максімум: 14091 ns, мінімум: 151 ns. Фота клікабельна.

На этапе падрыхтоўкі зборкі можна выстаўляць гэтую зменную відавочна ці можна карыстацца бібліятэкай. automaxprocs ад хлопцаў з Uber.

Дэплой

• Праверка канвенцый. Перад тым як пачаць дастаўляць зборкі сэрвісу ў вызначаныя асяроддзі, трэба праверыць наступнае:
- API endpoints.
- Адпаведнасць адказаў API endpoints схеме.
- Фармат логаў.
- Выстаўленне загалоўкаў пры запытах да сэрвісу (цяпер гэта робіць netramesh)
- Выстаўленне маркера ўладальніка пры адпраўцы паведамленняў у шыну (event bus). Гэта трэба для адсочвання складнасці сэрвісаў праз шыну. У шыну можна адпраўляць як ідэмпатэнтныя дадзеныя, якія не падвышаюць складнасць сэрвісаў (што добра), так і бізнэс-дадзеныя, якія складнасць сэрвісаў узмацняюць (што вельмі дрэнна!). І ў той момант, калі гэтая складнасць становіцца праблемай, разуменне, хто піша і чытае шыну, дапамагае правільна падзяліць сэрвісы.

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

Сінтэтычныя тэсты

• Тэставанне ў закрытым контуры. Для яго мы зараз выкарыстоўваем апенсорсны Hoverfly.io. Спачатку ён запісвае рэальную нагрузку на сэрвіс, затым - як раз у закрытым контуры - яе эмулюе.

• Нагрузачнае тэсціраванне. Усе сэрвісы мы стараемся прывесці да аптымальнай прадукцыйнасці. І ўсе версіі кожнага сэрвісу павінны падвяргацца нагрузачнаму тэставанню - так мы можам зразумець бягучую прадукцыйнасць сэрвісу і розніцу з папярэднімі версіямі гэтага ж сэрвісу. Калі пасля апдэйта сэрвісу яго performance упаў у паўтара раза, гэта выразны сігнал для яго ўладальнікаў: трэба закапацца ў код і выправіць сітуацыю.
Ад сабраных дадзеных мы адштурхваемся, напрыклад, каб правільна рэалізаваць auto scaling і, у выніку, наогул зразумець, наколькі сэрвіс паддаецца маштабаванні.

Пры нагрузачным тэсціраванні мы правяраем, ці адказвае спажыванне рэсурсаў выстаўленым абмежаванням. І завастраем увагу перш за ўсё на экстрэмумах.

a) Глядзім на агульную нагрузку.
- Занадта малая - хутчэй за ўсё нешта наогул не працуе, калі нагрузка раптам ўпала ў некалькі разоў.
- Занадта вялікая - патрабуецца аптымізацыя.

b) Глядзім на адсечку па RPS.
Тут глядзім і розніцу бягучай версіі і папярэдняй і агульную колькасць. Напрыклад, калі сэрвіс выдае 100 rps - то ён альбо дрэнна напісаны, альбо гэта яго спецыфіка, але ў любым выпадку гэта нагода вельмі пільна паглядзець на сэрвіс.
Калі ж RPS наадварот занадта шмат, то, магчыма, нейкі баг і нейкі з endpoint-ов перастаў выконваць карысную нагрузку, а проста спрацоўвае які-небудзь return true;

Canary-тэсты

Пасля таго як пройдзены сінтэтычныя тэсты, мы абкочваем працу мікрасэрвісу на малой колькасці карыстальнікаў. Пачынаем асцярожна, з мізэрнай долі меркаванай аўдыторыі сэрвісу - менш за 0,1%. На гэтым этапе вельмі важна, каб у маніторынгу былі заведзены правільныя тэхнічныя і прадуктовыя метрыкі, каб яны максімальна хутка паказалі праблему ў сэрвісе. Мінімальны час canary-тэсту - 5 хвілін, асноўны - 2 гадзіны. Для складаных сэрвісаў выстаўляем час у ручным рэжыме.
Аналізуем:
- метрыкі, спецыфічныя для мовы, у прыватнасці, воркеры php-fpm;
- памылкі ў Sentry;
- статусы адказаў;
- Час адказаў (response time), дакладнае і сярэдняе;
- Latency;
- выключэнні, апрацаваныя і неапрацаваныя;
- прадуктовыя метрыкі.

Squeeze Testing

Squeeze Testing яшчэ называюць тэсціраваннем праз «выдушванне». Назоў методыкі ўвялі ў Netflix. Сутнасць яе ў тым, што спачатку мы запаўняем рэальным трафікам адзін інстанс да стану адмовы і такім чынам усталёўваны яго мяжа. Далей дадаем яшчэ адзін інстанс і нагружаем гэтую парачку - зноў да максімуму; мы бачым іх столь і дэльту з першым "сквізам". І так падлучальны па адным інстансе за крок і вылічаны заканамернасць у зменах.
Дадзеныя па тэстах праз "выдушванне" таксама сцякаюцца ў агульную базу метрык, дзе мы або ўзбагачаем імі вынікі штучнай нагрузкі, або наогул заменны імі "сінтэтыку".

Прадакшэн

• Маштабаванне. Выкочваючы сэрвіс на прадакшэн, мы адсочваем, як ён маштабуецца. Маніторыць пры гэтым толькі паказчыкі CPU, па нашым досведзе, неэфектыўна. Auto scaling з бенчмаркінгам RPS у чыстым выглядзе працуе, але толькі для асобных сэрвісаў, напрыклад анлайн-стрымінгу. Так што мы глядзім у першую чаргу на спецыфічныя для дадатку прадуктовыя метрыкі.

У выніку пры маштабаванні аналізуем:
- паказчыкі CPU і RAM,
- Колькасць запытаў у чарзе,
- час адказу,
- Прагноз на падставе назапашаных гістарычных дадзеных.

Пры маштабаванні сэрвісу таксама важна адсочваць яго залежнасці, каб не атрымалася так, што мы першы сэрвіс у ланцужку скейлім, а тыя, да якіх ён звяртаецца, падаюць пад нагрузкай. Каб усталяваць прымальную для ўсяго пула сэрвісаў нагрузку, мы глядзім на гістарычныя дадзеныя «бліжэйшага» залежнага сэрвісу (па камбінацыі паказчыку CPU і RAM разам з app-specific metrics) і супастаўляем іх з гістарычнымі дадзенымі які ініцыялізуе сэрвісу, і гэтак далей па ўсім «ланцужку », зверху данізу.

абслугоўванне

Пасля таго як мікрасэрвіс уведзены ў строй, мы можам наважваць на яго трыгеры.

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

Частка трыгераў адказвае за стабільнасць працы, частка – як функцыя абслугоўвання сістэмы – напрыклад, нейкі сэрвіс даўно не дэплаіраваўся і яго базавая выява перастаў праходзіць праверку бяспекі.

Дашбард

Калі зусім сцісла, дашборд - кантрольны пульт усяго нашага PaaS.

  • Адзіны пункт інфармацыі аб сэрвісе, з дадзенымі аб яго пакрыцці тэстамі, колькасці яго вобразаў, колькасці прадакшэн-копій, версій і г.д.
  • Сродак фільтрацыі дадзеных па сэрвісах і labels (маркерам прыналежнасці да бізнэс-юнітам, прадуктовай функцыянальнасці і т. д.)
  • Сродак інтэграцыі з інфраструктурнымі інструментамі для трасіроўкі, лагіравання, маніторынгу.
  • Адзіны пункт дакументацыі па сэрвісах.
  • Адзіная кропка агляду ўсіх падзей па сэрвісах.

Што мы ведаем пра мікрасэрвісы
Што мы ведаем пра мікрасэрвісы
Што мы ведаем пра мікрасэрвісы
Што мы ведаем пра мікрасэрвісы

Разам

Да ўкаранення PaaS новы распрацоўнік мог выдаткаваць некалькі тыдняў на тое, каб разабрацца ва ўсіх прыладах, неабходных для запуску мікрасэрвісу ў прадакшэн: Kubernetes, Helm, – у нашых унутраных асаблівасцях TeamCity, наладзе падлучэння да баз і кэшам у адмоваўстойлівым выглядзе і т. д. Цяпер на гэта сыходзіць пару гадзін - прачытаць quickstart і зрабіць сам сэрвіс.

Я рабіў даклад на гэтую тэму для HighLoad++ 2018, можна паглядзець відэа и прэзентацыю.

Бонус-трэк для тых, хто дачытаў да канца

Мы ў Авіта арганізуем унутраны трохдзённы трэнінг для распрацоўшчыкаў ад Крыса Рычардсана, эксперта па мікрасэрвіснай архітэктуры. Жадаем падарыць магчымасць удзелу ў ім камусьці з чытачоў гэтай пасады. Тут выкладзена праграма трэнінгу.

Трэнінг пройдзе з 5 па 7 жніўня ў Маскве. Гэта працоўныя дні, якія будуць поўнасцю заняты. Абед і навучанне будуць у нашым офісе, а дарогу і пражыванне выбраны ўдзельнік аплочвае сам.

Падаць заяўку на ўдзел можна у гэтай гугл-форме. Ад вас - адказ на пытанне, чаму менавіта вам трэба наведаць трэнінг і інфармацыя, як з вамі звязацца. Адказвайце на англійскай, таму што ўдзельніка, які патрапіць на трэнінг, Крыс будзе выбіраць сам.
Мы аб'явім імя ўдзельніка трэнінгу апдэйтам да гэтай пасады і ў сацыяльных сетках Авіта для распрацоўшчыкаў (AvitoTech у Фэйсбуку, Вконтакте, твітэры) не пазней за 19 ліпеня.

Крыніца: habr.com

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