Тысячи пользователей онлайн: как работать, когда у тебя высоконагруженный проект
«Я не успеваю писать код, но участвую во всех важных обсуждениях». Как работает руководитель разработки Яндекс.Практикума
Тысячи пользователей онлайн: как работать, когда у тебя высоконагруженный проект
Кто такой технический директор? Почему он главный, но не пишет код?

Вот вы зашли в интернет-магазин: посмот­ре­ли реко­мен­да­ции, выбра­ли, что нуж­но, поло­жи­ли в кор­зи­ну, опла­ти­ли. Для вас это как один связ­ный фильм. А для мага­зи­на это серия запро­сов: «пока­зать реко­мен­да­ции», «доба­вить товар в кор­зи­ну», «обра­бо­тать опла­ту».

Если вы един­ствен­ный поль­зо­ва­тель мага­зи­на, то про­блем не будет. Но если вдруг тыся­ча поль­зо­ва­те­лей решит одно­вре­мен­но что-то купить, то сер­вер полу­чит в тыся­чу раз боль­ше запро­сов — и если на сер­ве­ре что-то сде­ла­но кри­во, всё это хозяй­ство мёрт­во ляжет.

Тако­ва судь­ба высо­ко­на­гру­жен­ных про­ек­тов.

👉 Эта ста­тья напи­са­на по моти­вам раз­го­во­ра с Алек­сан­дром Тре­ге­ром, руко­во­ди­те­лем служ­бы раз­ра­бот­ки Прак­ти­ку­ма. Рань­ше Алек­сандр рабо­тал в сер­ви­се зна­комств Badoo. Може­те пред­ста­вить, насколь­ко там всё нагру­же­но.

Высокая нагрузка — это сколько?

Высо­ко­на­гру­жен­ные про­ек­ты (хай­ло­ад) — это сай­ты, сер­ви­сы и при­ло­же­ния, кото­рые обра­ба­ты­ва­ют боль­шое коли­че­ство запро­сов. Это интернет-магазины, мес­сен­дже­ры, соци­аль­ные сети, интернет-банки: сот­ни и тыся­чи поль­зо­ва­те­лей одно­вре­мен­но поку­па­ют, обща­ют­ся, загру­жа­ют фото­гра­фии, пере­во­дят день­ги. Сер­ве­ра без оста­нов­ки обра­ба­ты­ва­ют их дей­ствия.

«Боль­шое коли­че­ство запро­сов» — поня­тие отно­си­тель­ное. Чёт­кой гра­ни­цы, после кото­рой про­ект мож­но счи­тать высо­ко­на­гру­жен­ным, нет: это зави­сит от инфра­струк­ту­ры. Если у вас неболь­шой сер­вер, то даже ста­биль­ные 10 запро­сов в секун­ду могут стать про­бле­мой. Но если усред­нить, то гра­ни­ца высо­кой нагруз­ки про­ле­га­ет око­ло сот­ни запро­сов в секун­ду.

Сот­ня запро­сов в секун­ду — это, ско­рее все­го, тыся­чи и десят­ки тысяч поль­зо­ва­те­лей онлайн: если каж­дый поль­зо­ва­тель дела­ет запрос раз в несколь­ко секунд, как раз набе­га­ет несколь­ко сотен запро­сов в секун­ду.

В чём проблема

Если запро­сов слиш­ком мно­го, сер­вер не успе­ва­ет их обра­ба­ты­вать и начи­на­ет сбо­ить. Чем это чре­ва­то:

  • Стра­ни­цы сай­та начи­на­ют загру­жать­ся мед­лен­нее или вовсе не загру­жа­ют­ся.
  • Появ­ля­ют­ся слу­чай­ные ошиб­ки, поль­зо­ва­те­ли не могут выпол­нять при­выч­ные опе­ра­ции.
  • Соеди­не­ние меж­ду сер­ве­ром и поль­зо­ва­те­лем в прин­ци­пе теря­ет­ся.

Поль­зо­ва­те­лей это напря­га­ет, а биз­нес теря­ет день­ги. В усло­ви­ях жёст­кой кон­ку­рен­ции это вооб­ще может озна­чать поте­рю людей: напри­мер, в 2007 году, когда толь­ко начи­на­лись соц­се­ти, в сту­ден­че­ской сре­де было два сай­та — «Вкон­так­те» и «Факуль­тет». О вто­ром вы ниче­го не слы­ша­ли, пото­му что он дико тор­мо­зил в пико­вое вре­мя, и все посте­пен­но пере­полз­ли во «Вкон­так­те».

А ещё в хайлоад-проектах мень­ше про­стор для экс­пе­ри­мен­та. В любой момент тыся­чи людей по все­му миру могут исполь­зо­вать сер­вис, так что он дол­жен быть ста­биль­ным. При­хо­дит­ся исполь­зо­вать про­ве­рен­ные тех­но­ло­гии и уде­лять боль­ше вни­ма­ния тести­ро­ва­нию.

Что нужно учитывать при разработке хайлоад-проекта

Мно­го запро­сов — мно­го дан­ных. Поль­зо­ва­те­ли загру­жа­ют фото­гра­фии, запол­ня­ют анке­ты, пере­пи­сы­ва­ют­ся — это всё нуж­но хра­нить и обра­ба­ты­вать. Зна­чит, нуж­но мно­го сер­ве­ров, а если про­ект меж­ду­на­род­ный, то ещё и в раз­ных стра­нах, что­бы у поль­зо­ва­те­лей из Аме­ри­ки всё рабо­та­ло так же быст­ро, как и у поль­зо­ва­те­лей из Евро­пы.

Объ­ём дан­ных может рез­ко вырас­ти. Нико­гда не зна­ешь, что про­изой­дёт зав­тра. Может, выстре­лит рекла­ма, при­дёт мил­ли­он новых поль­зо­ва­те­лей и нагруз­ка ста­нет в несколь­ко раз выше. Сего­дня у тебя созда­ёт­ся гига­байт лич­ных сооб­ще­ний в день, а зав­тра — 10 гига­байт в день.

Поэто­му недо­ста­точ­но про­сто иметь мно­го сер­ве­ров, что­бы про­сто решать теку­щие зада­чи. Нуж­но спро­ек­ти­ро­вать систе­му так, что­бы иметь воз­мож­ность быст­ро её мас­шта­би­ро­вать.

Луч­ше всё дуб­ли­ро­вать. «1» — пло­хое чис­ло для высо­ко­на­гру­жен­но­го про­ек­та. Любой сер­вер или сер­вис может неожи­дан­но вый­ти из строя, поэто­му при­хо­дит­ся всё дуб­ли­ро­вать. Запас­ной сер­вер, репли­ка базы дан­ных — без это­го нику­да.

Исполь­зо­вать кэши­ро­ва­ние. Ответ на запрос поль­зо­ва­те­ля мож­но кэши­ро­вать — вре­мен­но сохра­нять, напри­мер, в опе­ра­тив­ной памя­ти. Когда от поль­зо­ва­те­ля повтор­но при­дёт запрос, мож­но не обра­щать­ся к сер­ве­ру, а взять инфор­ма­цию из кэша. Это помо­га­ет сни­жать нагруз­ку: если в кэше есть инфор­ма­ция, кото­рая нуж­на поль­зо­ва­те­лю, не при­дёт­ся отправ­лять иден­тич­ный запрос и сно­ва ждать ответ. Стра­ни­ца загру­зит­ся быст­рее.

Как выкатывать высоконагруженные проекты

Обно­вить лич­ный блог или сайт ком­па­нии с парой десят­ков визи­тов в день неслож­но. Даже если во вре­мя обнов­ле­ния сайт не будет досту­пен несколь­ко минут, ниче­го страш­но­го не про­изой­дёт. С нагру­жен­ны­ми про­ек­та­ми всё по-другому — они не могут поз­во­лить себе такую задерж­ку. Что­бы поль­зо­ва­тель во вре­мя исполь­зо­ва­ния тако­го сер­ви­са не наткнул­ся на ошиб­ку или непра­виль­ные дан­ные, суще­ству­ют раз­ные релиз­ные флоу — спо­со­бы выпус­кать новые вер­сии.

👉 Вот что Алек­сандр Тре­гер рас­ска­зы­ва­ет про это:

«Для нача­ла код нуж­но писать так, что­бы все­гда была обрат­ная сов­ме­сти­мость. Это зна­чит, что новая вер­сия кода долж­на уметь рабо­тать с дан­ны­ми и в новом фор­ма­те, и в ста­ром, из преды­ду­щей вер­сии. Слож­ные мигра­ции баз дан­ных нуж­но делать по шагам и неза­ви­си­мо от обнов­ле­ния кода. А такие дей­ствия, как, напри­мер, пере­име­но­ва­ние полей, — прак­ти­че­ски табу.

Когда я рабо­тал в Badoo, мы исполь­зо­ва­ли под­ход, в осно­ве кото­ро­го лежа­ла штат­ная систе­ма авто­за­груз­ки фай­лов в PHP. Каж­дый файл в про­цес­се под­го­тов­ки к выклад­ке полу­ча­ет свою вер­сию, и в каж­дом рели­зе есть кар­та с акту­аль­ны­ми вер­си­я­ми. В продакшен-окружении на каж­дой машине есть symlink-файл — сим­во­ли­че­ская ссыл­ка — кото­рый ука­зы­ва­ет на нуж­ную кар­ту.

Когда все маши­ны полу­чи­ли новый код, мы меня­ем одну ссыл­ку на дру­гую. Для всех новых запро­сов PHP начи­на­ет исполь­зо­вать новую кар­ту и, соот­вет­ствен­но, новые фай­лы.

Минус тако­го под­хо­да в том, что фай­лы посто­ян­но докла­ды­ва­ют­ся, зани­мая место на дис­ке, и их нуж­но пери­о­ди­че­ски чистить. А ещё ста­рый код может ещё рабо­тать в памя­ти, порой по несколь­ко дней. Инфра­струк­ту­ра может силь­но поме­нять­ся, и логи засы­пет ошиб­ка­ми.

В Прак­ти­ку­ме мы исполь­зу­ем внут­рен­нее обла­ко Яндек­са для деп­лоя наших при­ло­же­ний. У нас всё в кон­тей­не­рах, и каж­дое при­ло­же­ние запу­ще­но в несколь­ко экзем­пля­ров. Про­цесс так настро­ен, что под­ни­ма­ет­ся несколь­ко новых экзем­пля­ров, балан­си­ров­щик пус­ка­ет на них тра­фик вме­сто части ста­рых и гасит послед­ние. Так посте­пен­но всё обнов­ля­ет­ся. Это — rolling update.

Есть ещё вари­ант сна­ча­ла пол­но­стью парал­лель­но под­нять нуж­ное коли­че­ство экзем­пля­ров и одно­мо­мент­но на них пере­клю­чить­ся. Такой метод деп­лоя назы­ва­ет­ся blue-green. Что­бы его исполь­зо­вать, нуж­но все­гда иметь в запа­се в два раза боль­ше сво­бод­ных ресур­сов, что не все­гда воз­мож­но».