Эссе об Elixir. В акведуке все это время была вода. Часть 1

в 12:21, , рубрики: Elixir
Эссе об Elixir. В акведуке все это время была вода. Часть 1 - 1

Раскопал на Medium интересное эссе от разработчика Krzyś про Elixir. Написано так захватывающе и самобытно, что не смог пройти мимо. Хотел чуть-чуть подсократить, но каждый раздел важен, а терять стиль автора не хочется. Поэтому разбиваю его на две части — сегодня делюсь первой.


Я не хотел писать это эссе и не жду, что оно станет популярным, но… Я все же провел за ним несколько вечеров, шагая по комнате — мимо книжной полки, мимо окна, мимо собаки, которая научилась отслеживать эти маршруты с терпеливостью смотрителя маяка.

Зачем? Посмотрите, в какое интересное время мы живем. В вашей ленте новостей только ленивый не пишет, что AGI вот-вот всплывет из глубин и сожрет нас — событие, которое я не хотел бы пропустить по редакторским причинам. Где-то идут войны, и, если уж мы решили отвлечься от кода, то политика предлагает развлечение такого уровня, к которому ни один стриминговый сервис не подберется. Будущее уже на пороге.

И все же. Где-то между книжной полкой и окном меня настигло очень странное чувство вины — и это не обычная писательская вина за то, что черновик не дописан. 

Это какая-то древняя, геологическая вина. Ее корни, я почти уверен, проходят сквозь Пунические войны и дальше, куда-то за динозавров. Древняя, почти видовая неловкость от того, что годами много раз проходил мимо чего-то важного, а оно все это время стояло на виду и прекрасно функционировало. Карфагену хотя бы досталось внимание, прежде чем Рим с ним покончил.

Но то, как я обходился с одной сорокалетней технологией, было хуже завоевания. Это было безразличие. 

Так что поприветствуйте Erlang, а также проявите немного любви к его младшенькому, Elixir… Да здравствует BEAM/OTP.

<..>

Начиналось это эссе, как и бывает с такими вещами, с письма.

I. Письмо, или Во всем виноват читатель

«Это истина, общепризнанная, что разработчик, владеющий серией языков, непременно захочет выучить еще один».

Джейн Остин — вероятно, модератор r/programminglanguages

Полка с надписью «Оккультное», недавно протертая

Полка с надписью «Оккультное», недавно протертая

Это все из-за тебя. Да, из-за тебя — читателя, который где-то в комментариях к моей серии про Rust спросил, что я думаю об Elixir. Это сделал ты. Надеюсь, ты доволен собой. Я потерял из-за тебя месяц.

Немного контекста для всех остальных 

Меня всегда тянуло к функциональному программированию. Так же, как тянет к освещенному окну на той стороне темного двора: оно манит теплом, но наблюдать за ним хочется издалека, без немедленного желания постучаться. 

У меня даже был свой период Haskell. Он бывает у всех: как желание получить диплом по философии или купить мотоцикл. Но в конце концов я решил, что безбрачие не для меня. Язык, в котором для любого побочного эффекта требуется официальное благословение монады, предназначен для душ достойнее моей. Я восхищаюсь монастырем, покупаю монастырский мед, но принимать обет не собираюсь.

В Rust мне нравится именно его подпольный функциональный контрабандный груз: алгебраические типы данных, сопоставление с образцом, Option и Result. Все это с восхитительной бесцеремонностью взяли у Haskell и OCaml, а потом завернули в фигурные скобки, чтобы не пугать публику из мира C++... Elixir же, и особенно Erlang, занимали в моей мысленной библиотеке одну очень конкретную полку: оккультную.

Синтаксис выглядел как заклинание. Вся экосистема BEAM источала отчетливую энергию культа Ктулху, а ее адепты уверяли, что Древний на самом деле очень дружелюбен, если выучить нужные слова. А я, если помните, только что написал целое эссе про мантии и заклинания. Вступать в очередной культ я не собирался.

Но читатель спросил. А я тем временем уже ковырялся с Gleam. Он-то и привел меня к ребятам из Lambda Class, которые пишут о BEAM с энтузиазмом археологов, нашедших древнее сооружение, где до сих пор почему-то горит свет. Так что я поступил отвественно: сначала обратился к Elixir, а потом уже к Erlang, чтобы действительно понимать OTP, а не просто кивать при его упоминании.

И где-то на третьей неделе, читая про дерево супервизоров в час, который мой терапевт назвал бы уж слишком поздним, я захлопнул ноутбук и сказал сам себе вслух на пустой кухне: «Что за?.. Все это уже было. Все это время, прямо под носом».

Мы писали элегии по римским акведукам — вы и я. Хватило на две статьи. Потерянное знание, забытая инженерия, цивилизация, которая уже и не помнит, как по ней текла вода. Так вот, оказывается, один акведук так и не рухнул. Он гонит воду с 1986 года, полностью задокументирован, с 1998 года находится в опенсорсе и даже поддерживается. Мы не потеряли знание — мы просто построили города в другом месте и придумали, причем с колоссальными затратами, бутилированную воду.

Это эссе — выставленный нам счет. А это эссе — признание ошибки.

II. Горилла, держащая банан

«Вы хотели банан, а получили гориллу, держащую банан, и все джунгли в придачу».

Джо Армстронг, на самом деле описывая объектно ориентированное программирование

1986 год на проводе. Буквально...

1986 год на проводе. Буквально...

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

На дворе 1986 год, компания Ericsson. Задача — телефонные коммутаторы. Держите ее в голове, потому что она совсем не похожа на те задачи, что формировали языки, на которых мы с вами выросли. 

Телефонный коммутатор обрабатывает сотни тысяч одновременных вызовов, каждый независим, у каждого свое состояние. Коммутатор не может «лечь» или остановиться — не в том смысле, что мы стремимся к минимальному простою, нет. В буквальном: не может. Это инфраструктура, через которую звонят в экстренные службы. Его нельзя остановить ради деплоя или обновления до новой версии, потому что нет такого окна обслуживания, в которое никому в Швеции не надо никуда звонить. И один сбой ни при каких обстоятельствах не должен валить соседние. Например, ваш прерванный телефонный звонок с тетей не должен оставить всю больницу без связи.

Джо Армстронг, Роберт Вирдинг и Майк Уильямс не ставили себе целью придумать красивый язык. Они пытались выжить в рамках этой задачи, а язык — это просто окаменевшая летопись выживания. Высокий уровень параллельности, потому что и вызовов тоже много. Изоляция, потому что эти вызовы независимы. Устойчивость к сбоям как основа дизайна — не библиотека, не паттерн, не глава в книге по паттернам, а несущая стена. Горячее обновление кода, потому что коммутатор остается в строю, пока вы его чините. Напоминает замену двигателя у самолета, которому запрещено садиться.

Каждый язык отвечает на какой-то вопрос. Язык C ответил нам, как писать операционную систему на железе размером со шкаф. JavaScript — как заставить обезьянку танцевать на веб-странице к пятнице. А Erlang ответил, как построить систему, которая продолжает работать, пока ее компоненты выходят из строя, бесконечно, под нагрузкой, без права даже на крошечную остановку.

И вот, собственно, одно неприятное наблюдение, вокруг которого крутится это эссе: где-то около 2010 года вопрос всей отрасли стал вопросом для Erlang — распределенные системы, миллионы одновременных соединений, сервисы, которые должны работать постоянно, независимые сбои, каскадирование которых нельзя допустить.

III. Почему это похоже на культ (генеалогическая защита)

«Самая древняя и сильная эмоция человечества — страх, а самый древний и сильный вид страха — страх перед неизвестным».

Г. Ф. Лавкрафт, объясняя мою реакцию на -spec при код-ревью

ph’nglui mglw’nafh BEAM R’lyeh wgah’nagl fhtagn (это значит «девять девяток»)

ph’nglui mglw’nafh BEAM R’lyeh wgah’nagl fhtagn (это значит «девять девяток»)

Теперь давайте разберем по винтикам мое собственное предубеждение.

Erlang выглядит оккультно. И все. Запятые, точки с запятой, точки в конце блоков функций, словно строки из церковной литургии. Переменные, которые обязаны начинаться с заглавной буквы, атомы, прячущиеся в нижнем регистре. Ощущается это так, словно код не столько пишут, сколько переписывают с чего-то более древнего. Покажите модуль Erlang разработчику на JavaScript и посмотрите, как он начнет креститься на точку с запятой.

Но генеалогия языка меняет все. Первый Erlang был реализован на Prolog. Армстронг прототипировал его как метаинтерпретатор Prolog, и синтаксис здесь — это не эстетический выбор, а вынужденное наследие. Эти точки в конце ветвей, этот мир, где в основе — сначала сопоставление с образцом, а уже потом все остальное, этот логико-программный скелет под функциональной оболочкой…

Erlang — это то, что получается, когда логический язык взрослеет в телекоммуникационной лаборатории. В общем, мантии выбирали не ради эффекта — они достались по наследству. Буквально как мы с вами наследуем бабушкин рецепт борща и метод мыть посуду.

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

Лавкрафтовская рамка оказалась вернее, чем я думал, только наоборот. У Лавкрафта ужас в том, что древнее нечто на дне моря реально существует и полностью к вам равнодушно. Здесь же другая ситуация: древнее нечто под толщей воды реально, благожелательно, подробно задокументировано и все это время держало на своих плечах заметную долю мировой телеком- и мессенджер-инфраструктуры, пока мы на поверхности проводили тысячи конференций по отказоустойчивости.

IV. Переворот стола: ничто никому не принадлежит

«Хорошие заборы — залог хороших соседей».

Роберт Фрост о том, как устроена память

Общая земля закрыта на бессрочный ремонт

Общая земля закрыта на бессрочный ремонт

Теперь мы подходим к той части истории, которая адресована лично тебе — моему читателю из серии про Rust. Потому что речь пойдет о драконе, с которым мы с вами годами учились договариваться: общем изменяемом состоянии.

Любой распространенный подход к конкурентности — это набор правил управления общим пространством: одна большая куча, множество действующих лиц и вечный вопрос о том, кто, когда и к чему может прикасаться. Рассмотрим три школы.

Rust…

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

И это работает. Притом безопасно. Но вся эта история, если честно, юридически изнурительна: целая система, возведенная ради того, чтобы совместное использование памяти просто работало.

Go…

…нанимает уборщика и вешает вежливую табличку: «Делитесь памятью через общение». Хорошая табличка. Но мьютексы все еще лежат в ящике, табличка скорее пожелание, чем архитектура, а детектор гонок стоит в коридоре как алкотестер на корпоративе. Он там именно потому, что соблюдать правила изначально необязательно.

BEAM…

…еще в 1986 году посмотрел на идею общей памяти — и отверг саму ее основу. Никакой общей памяти нет. Стол перевернут, совещание окончено. Каждый процесс при запуске занимает меньше трех килобайт, меньше большинства объектов. И получает собственную приватную кучу, собственный стек, собственный сборщик мусора и почтовый ящик у двери своей кельи. 

Обмен идет через копирование: отправленное сообщение становится дубликатом в мире получателя. Гонка данных не запрещена. Гонка данных грамматически невозможна: у двух глаголов просто нет общего существительного, за которое можно было бы бороться. Rust делает беспорядок незаконным. Erlang делает так, что беспорядок не может возникнуть. Это как разница между отлично работающей полицией и миром, где нечего красть.

Из этого вытекают два последствия, и они — ядро всего эссе.

Во-первых, великие войны сборщиков мусора — десятилетие инженерного героизма вокруг пауз, появление G1, ZGC и победы в виде задержек меньше миллисекунды — здесь просто не происходят.

Здесь нет stop-the-world, потому что нет единого «мира». Есть миллионы маленьких миров. В каждом уборка мусора происходит отдельно, за микросекунды, пока остальные продолжают работать. Отрасль десять лет оптимизировала проблему, которую BEAM успел устранить еще до того, как людей, впоследствии обнаруживших эту проблему, вообще приняли на работу.

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

Оговорка, чтобы все было честно, как того требуют правила дома: от чистоты здесь намеренно отступают. Копирование больших сообщений обходится недешево, поэтому большие бинарные данные (свыше 64 байт) на самом деле разделяются под капотом через подсчет ссылок — тихая победа прагматики над догмой. А таблицы ETS — это официальная исповедальня экосистемы, которая признает, что иногда разделяемое состояние все же нужно. Но оно подается через контролируемый механизм, а не лежит на столе. Модель гнется ровно там, где должна, и сама говорит, где именно гнется.

V. Второй переворот стола: процессор тоже никому не принадлежит

«Не думайте, что вы в чем-то особенны».

Закон Янте, теперь уже в качестве политики планирования

Эссе об Elixir. В акведуке все это время была вода. Часть 1 - 6

Изолированная память дает безопасность. Но сама по себе она не дает стабильности, потому что есть еще один общий ресурс, о котором все забывают: время. Процесс может и не иметь доступа к вашей памяти, но при этом отнимать у вас все процессорное время. Для этого BEAM переворачивает второй стол, и вот это настоящая киллер-фича.

Механизм до обидного прост. У каждого процесса есть бюджет редукций — несколько тысяч абстрактных единиц работы. Потратил бюджет — и тебя выводят из планирования. Не «когда будет удобно». Не «на следующем await, если ты до него дойдешь, конечно». Не «когда закончится цикл». Сейчас

Планировщик — как вышибала в приличном заведении. Ему все равно, что вы VIP-процесс, обрабатывающий платежи. Редукции закончились — чемодан, вокзал, домой. Предвосхищающее вытеснение в BEAM — не любезность, а конституционный принцип.

И есть что-то особенно вкусное в том, что Erlang — шведский, потому что это закон Янте, скомпилированный в виртуальную машину: скандинавский социальный принцип «Не воображай себя особенным» на уровне рантайма. Ни один процесс не особенный. Ни один не заслуживает больше времени или ресурсов. 

Миллионы процессов, каждый получает свой скромный, в стиле lagom, кусочек машины. Равенство как деталь реализации.

А теперь сравним соседей в том же духе, что и в прошлом разделе.

Node.js…

…работает на кооперативном планировании, то есть на хороших манерах. Один event loop — и любая функция, которая забыла о приличиях (тяжелый JSON.parse, синхронный вызов криптографии, невинный на вид regexp с катастрофическим бэктрекингом), держит весь зал в заложниках. Устойчивость зависит от личной вежливости каждой функции в каждой зависимости из папки node_modules.

Rust async…

…тоже кооперативный. Отсюда народная заповедь: «Не блокируй исполнителя». Ее передают новичкам как предупреждение о мистическом болоте за деревней. Rust приручил пространство конституцией. Время по-прежнему живет на джентльменском соглашении с рантаймом, который сам язык даже не поставляет.

Go…

…исторически был кооперативным в безопасных точках. Но после нескольких лет борьбы с плотными циклами в Go 1.14 добавили асинхронное вытеснение через сигналы. В контексте нашей метафоры это означает вот что: он нанял вышибалу после нескольких вечеринок, которые плохо закончились. Мое уважение за смирение. Небольшой минус в карму за тайминг и сроки.

И вот почему вытеснение — это именно стабильность, а не просто приятное свойство. Благодаря ему BEAM деградирует равномерно и плавно. Под нагрузкой система не срывается от 500 мс к апокалипсису по тайм-аутам. Все процессы замедляются пропорционально, понемногу и предсказуемо. Хвостовые задержки остаются хвостовыми, а soft real-time — это не лозунг, а арифметика бюджета. 

И еще одна честная оговорка: зона ответственности вышибалы заканчивается там, где начинается нативный код. Редукции учитываются только в коде BEAM — плохо написанный NIF блокирует планировщик так же грубо, как тяжелая операция блокирует Node.js. Поэтому к нативному коду экосистема относится с осторожностью метрдотеля, который встречает шумную компанию с мальчишника. И для тех, кто не умеет себя вести, существуют dirty schedulers — грязные планировщики. Вышибала охраняет зал, а не кухню.

Запомните это: пригодится, когда дойдем до второй профессии Rust.

VI. Пусть падает: стоицизм как среда выполнения

«Наилучшим образом распорядись тем, что в твоей власти, а остальное принимай как есть».

— Эпиктет, чей «Энхиридион» можно считать самым кратким печатным руководством по OTP

…memento mori для каждого PID…

…memento mori для каждого PID…

Сначала пространство, потом время. Наконец — смерть. И здесь мы подходим к разделу, который мои постоянные читатели наверняка предвидели еще по заголовку. Потому что let it crash — самая откровенно философская инженерная доктрина из всех, что мне встречались в реальных системах. И, по счастливому совпадению, это и моя философия, которую я уже запустил в проде.

Давайте посмотрим, что с психологической точки зрения представляет собой традиционная обработка ошибок. 

Это отрицание, облеченное в синтаксис.

Защитное программирование хочет, чтобы мы предусмотрели все. Проверили все. Обернули все в try/catch. Обработали ошибку именно там, где она возникла, — глубоко в стеке вызовов, где меньше всего контекста и больше всего паники.

За этим — негласное убеждение: если быть достаточно бдительным, то сбоя можно избежать, что параноидальная функция способна достичь бессмертия. За двадцать лет работы с продакшен-системами я не раз видел, чем заканчивалась эта идея. Обычно — в три часа ночи.

Доктрина Erlang — это стоическая инверсия. Эпиктет начинает «Энхиридион» с дихотомии контроля: одни вещи зависят от нас, другие — нет, а несчастными нас делает привычка путать первые со вторыми.

В переводе на язык систем это звучит так: столкнется ли конкретный процесс с неисправимым состоянием, чаще всего от вас не зависит. Аппаратный сбой, космическое излучение, API соседней команды, внезапно исполнившее черт пойми что… Всего не предусмотришь.

Но от вас зависит реакция: чистая смерть процесса, ограниченная область поражения и наличие плана о том, что делать дальше.

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

Именно это, кстати, и есть худший сценарий. Не тот, который упал, а тот, который выжил и теперь лжет.

Процесс умирает честно — при первом же признаке бессмыслицы. Memento mori для каждого PID.

И это возможно — здесь все части эссе наконец соединяются — только благодаря двум предыдущим переворотам стола. Процесс может позволить себе умереть именно потому, что его куча изолирована, а смерть не повредит другим. Его исчезновение не лишит остальные процессы процессорного времени.

Стоицизм здесь не прикручен к архитектуре сверху. Он естественным образом из нее вырастает. Непривязанность на уровне аллокатора порождает невозмутимость на уровне всей системы.

Моя полка с даосскими трактатами тоже хочет высказаться: процесс, который не цепляется за свое состояние, способен уйти чисто. Все тот же образ пустого сосуда — только сосуд занимает 2,7 килобайта и перезапускается за микросекунды.

Найдется здесь место и для нашего уголка когнитивно-поведенческой терапии. Защитное программирование — это одновременно классическая катастрофизация и классический сверхконтроль: тревожное убеждение, что необходимо предусмотреть абсолютно все, иначе конец.

Let it crash предлагает сделать терапевтическую переоценку ситуации: вы не можете контролировать причину сбоя, но можете контролировать реакцию на него. Спроектируйте эту реакцию один раз — в супервизоре, у которого есть весь необходимый контекст, — и перестаньте репетировать катастрофу внутри каждой функции.

И здесь возникает очевидный вопрос: а кто, собственно, такой этот супервизор?

Рад, что вы спросили.

VII. Что такое OTP на самом деле, или та самая часть, где я сказал «Что за…» пустой кухне

«Мне жаль, что когда-то я придумал для этой темы термин “объекты”: из-за него многие сосредоточились на менее важной идее. Главная идея — обмен сообщениями».

— Алан Кэй, создатель объектно-ориентированного программирования, в письме, которое индустрия предпочла не читать

…четырнадцать строк, семь диалектов YAML, одна мораль…

…четырнадцать строк, семь диалектов YAML, одна мораль…

OTP — Open Telecom Platform. Название настолько демонстративно непривлекательное, что аж напоминает маскировку. Именно здесь философия превращается в работающий механизм.

OTP — это стандартная библиотека поведений: проверенные в бою каркасы для типовых компонентов долгоживущих систем, собранные из двух десятилетий неудач телекоммуникационной отрасли. Для нашего разговора особенно важны два из них: GenServer и Supervisor.

Вот серверный процесс с состоянием на Elixir — счетчик, своеобразный «Hello, World!» для работы с состоянием — и с комментариями:

defmodule Counter do
  use GenServer  # наследуем двадцать лет ошибок Ericsson -- уже исправленных

  # Клиентский API: что видит внешний мир
  def start_link(initial),
    do: GenServer.start_link(__MODULE__, initial, name: MODULE)

  def increment, do: GenServer.cast(__MODULE__, :increment)  # отправить и забыть
  def value,     do: GenServer.call(__MODULE__, :value)      # спросить и дождаться

  # Серверные колбеки: что происходит на самом деле, по одному сообщению за раз
  def init(initial), do: {:ok, initial}

  def handle_cast(:increment, count),
    do: {:noreply, count + 1}

  def handle_call(:value, _from, count),
    do: {:reply, count, count}

  # Никаких блокировок, мьютексов и атомарных операций.
  # Почтовый ящик и есть механизм синхронизации:
  # сообщения обрабатываются по одному, поэтому изменения состояния
  # не могут вклиниться друг в друга.
  #
  # Конкурентность без единого примитива конкурентности в поле зрения.
end

А теперь — та самая часть, из-за которой я начал разговаривать со своей кухней. Супервизор:

defmodule MyApp.Supervisor do
  use Supervisor

  def start_link(_),
    do: Supervisor.start_link(__MODULE__, :ok, name: MODULE)

  def init(:ok) do
    children = [
      Counter,  # если умрет -- воскресить. Все. Это вся настройка.
      MyApp.PaymentWorker,
      MyApp.CacheWarmer
    ]

    Supervisor.init(children, strategy: :one_for_one)

    # :one_for_one  -- перезапустить только умершего
    # :one_for_all  -- умер один, перезапустить всю семью
    #                 (общая судьба, объявленная честно)
    # :rest_for_one -- перезапустить умершего и всех, кто зависит от него
  end
end

Четырнадцать строк.

А теперь перечислим, что именно заключено в этих четырнадцати строках, если перевести их на язык современного технологического стека: 

  • проверка работоспособности; 

  • политика перезапуска; 

  • запуск компонентов в порядке зависимостей;

  • определение области распространения сбоя;

  • маршрут эскалации.

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

В облачно-нативном мире для этого понадобились бы манифест развертывания, liveness и readiness probe, PodDisruptionBudget, библиотека circuit breaker, сайдкар для повторных попыток и сервис, который ищет другие сервисы. Семь диалектов YAML, пять проектов CNCF и один сертификат. 

А здесь это просто структура данных. Внутри языка. С 1998 года.

Вот тогда я и сказал: «Что за…» Не потому, что BEAM умна, — умных технологий много. А потому, что дерево супервизоров содержит всю концептуальную суть кластера Kubernetes, выраженную четырнадцатью строками кода и появившуюся на два десятилетия раньше.

Мы все вместе посмотрели на это, сказали: «Да, но синтаксис какой-то странный», — и отправились заново изобретать ту же систему на YAML.

И еще один артефакт телекоммуникационного происхождения — последний элемент троицы стабильности: горячая замена кода.

BEAM умеет загружать новую версию модуля прямо в работающую систему. Процессы заканчивают обработку текущего сообщения на старом коде, а следующее обрабатывают уже на новом. Состояние переносится через специальный колбэк — без перезапуска и оборванных звонков.

Коммутатор продолжает работать, пока вы меняете двигатель.

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

Но вдумайтесь, о чем говорит само существование этого механизма. Создатели платформы считали требование «система не должна останавливаться никогда» настолько обыденным, что решили эту задачу уже в первой версии — как нечто само собой разумеющееся.

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

VIII. Девять девяток и другие легенды

«Есть три вида лжи: ложь, наглая ложь и статистика доступности».

— приписывается Дизраэли, отрефакторено каждым SRE в истории

…тридцать одна миллисекунда в год. По крайней мере, так говорят…

…тридцать одна миллисекунда в год. По крайней мере, так говорят…

У каждой веры есть своя история о чуде. У BEAM это AXD301 — ATM-коммутатор Ericsson, который, по имеющимся у меня данным, достиг доступности 99,9999999%.

Девять девяток.

Это всего тридцать одна миллисекунда простоя в год — настолько абсурдная цифра, что ощущаешь себя от нее примерно как от презентации вечного двигателя.

Поэтому разберемся с ней честно, как того требуют наши правила. Цифра получена во время испытаний British Telecom и относится к конкретному периоду измерений и конкретному определению простоя. Ее неоднократно оспаривали, дополняли контекстом и снабжали примечаниями — в том числе люди, вполне благосклонные к Erlang. Даже сам Армстронг говорил о ней куда осторожнее, чем принято в версии для рекламного буклета.

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

Но я все равно включил эту легенду в рассказ. Потому что механизм, который она рекламирует, реален.

Уберите маркетинговые девятки и спросите: что должно оказаться правдой, чтобы система хотя бы теоретически могла претендовать на такой результат?

Ответ — та троица, которую мы только что разобрали: сбои изолируются благодаря приватным кучам, задержки сглаживаются вытесняющим планированием, восстановлением управляют супервизоры, а обновления выполняются прямо во время работы.

История о чуде, возможно, преувеличена. Но физика, на которой она держится… Это предыдущие четыре раздела моего эссе.

В сущности, именно так вера и должна соотноситься со своими чудесами: история собирает толпу, а архитектура выполняет работу.

Тем временем чудеса моей собственной церкви устроены ровно наоборот. Мы рассказываем героические истории о том, как пережили собственную инфраструктуру: развертывание, лишившее меня выходных. Каскадный отказ, по которому написали постмортем размером с повесть. Шторм повторных запросов, которым мы сами устроили себе DDoS.

Наши легенды — о героизме.

Их легенды — о скуке.

И я начинаю подозревать, что скука — более совершенная технология.


Продолжение в следующей части.

Автор: sir-off

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js