Deep Engineering

SRE · Подготовка к собеседованию

Вопросы на собеседовании SRE: короткие ответы

Короткий ответ из каждого урока линии — тот же текст, что в уроке, только без подписи «Короткий ответ:», — и вопросы из его раздела «Дальше спросят». Ответы на эти вопросы, механизм и замеры, на которых всё это стоит, — в уроке по ссылке.

  1. 01

    Сигналы и PID 1

    У процесса с номером 1 в своём пространстве имён умолчательные действия сигналов не выполняются, поэтому SIGTERM без обработчика для него не делает ничего — оркестратор ждёт весь льготный срок и добивает SIGKILL, а в отчёте остаётся код 137, то есть 128 + 9. Зомби при этом — не процесс, а запись о его смерти: она держится ради кода выхода и занимает слот в таблице процессов, а убирает её wait, а не время.

    Полный ответ — в уроке →

    Дальше спросят

  2. 02

    cgroups и OOM

    Лимит памяти ставится группе процессов, и когда потребление упирается в него, ядро сначала пытается освободить память внутри группы, а если не выходит — убивает одного из её процессов сигналом SIGKILL. Поэтому в логе приложения пусто, а снаружи видно 137 — это 128 + 9. Потребление при этом за лимит не улетает: в измеренном прогоне пик группы дошёл ровно до лимита и остановился.

    Полный ответ — в уроке →

    Дальше спросят

  3. 03

    Лимит дескрипторов

    EMFILE — это лимит на число дескрипторов конкретного процесса, и считаются в нём не файлы, а все открытые объекты — сокеты, каналы, epoll, плюс три, которые процесс получил при рождении. Лимитов два: мягкий ядро проверяет при открытии очередного дескриптора, а жёсткий ограничивает то, насколько высоко процесс может поднять себе мягкий, — и поднять мягкий он может сам, без перезапуска.

    Полный ответ — в уроке →

    Дальше спросят

  4. 04

    Page cache и fsync

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

    Полный ответ — в уроке →

    Дальше спросят

  5. 05

    Очередь accept

    Между connect клиента и accept сервера стоит очередь ядра, и соединение в ней уже установлено — договорённость провело ядро, а не приложение. Поэтому занятый сервер выглядит для клиента работающим, а при переполнении очереди клиент получает не отказ, а таймаут: пакет молча отбрасывается, и TCP его повторяет.

    Полный ответ — в уроке →

    Дальше спросят

  6. 06

    Таймауты и дедлайны

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

    Полный ответ — в уроке →

    Дальше спросят

  7. 07

    Ретраи и джиттер

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

    Полный ответ — в уроке →

    Дальше спросят

  8. 08

    Graceful shutdown

    Graceful shutdown — это два действия по порядку: перестать принимать новые соединения и доработать уже принятые; и работает он только потому, что SIGTERM перехватывается. Измерено на одном и том же сервере под одинаковой нагрузкой: без обработчика оборвано 20 запросов из 20, с дренажем — ноль, а цена дренажа — 164 мс против 2, то есть остаток уже начатой работы.

    Полный ответ — в уроке →

    Дальше спросят

  9. 09

    Очередь и хвост

    Время в системе — это обслуживание плюс ожидание, и с ростом загрузки растёт ожидание, а не обслуживание. Поэтому зависимость непропорциональна: в модели рост загрузки с 0,80 до 0,95 — это плюс 19 %, а время выросло в 4,1 раза при неизменных 10 мс работы на запрос.

    Полный ответ — в уроке →

    Дальше спросят

  10. 10

    SLO и бюджет

    SLO — это цель по метрике плюс окно, а бюджет ошибок — то, сколько плохого эта цель разрешает в этом окне; считается он в тех же единицах, в которых считается сама метрика. 99,9 % за 30 дней при 1000 запросов в секунду и доступности, считаемой по запросам, — это 2 592 000 неуспешных запросов, что при полной недоступности равно 43,2 минуты; те же 99,9 % за сутки — 1,4 минуты.

    Полный ответ — в уроке →

    Дальше спросят

  11. 11

    Health-checks

    Проб три, и различаются они последствием — liveness перезапускает, readiness выводит из ротации, startup откладывает liveness на время запуска. Поэтому вопрос liveness звучит не «жив ли процесс», а «поможет ли перезапуск этого процесса»: внутрь пробы попадает только то, что чинится перезапуском, а зависимости — в readiness.

    Полный ответ — в уроке →

    Дальше спросят

  12. 12

    Выкатка и откат

    Ущерб от плохой выкатки зависит от того, сколько трафика и как долго обслуживает дефектная версия, и от тяжести дефекта, а не от названия стратегии. При постоянных потоке и долях число испорченных запросов — это поток × доля трафика на новой версии × доля запросов, которые ломает дефект, × суммарное время воздействия, а время до тревоги, решение и откат в этом времени складываются. Поэтому канарейке нужен детектор, способный заметить проблему на маленькой выборке: в модели урока та же канарейка задела 645 запросов при детекторе, ждущем 200 ошибок, и 29 при детекторе по доле ошибок — разница в 22 раза.

    Полный ответ — в уроке →

    Дальше спросят

  13. 13

    Разрешение имени

    Приложение обычно зовёт не DNS, а системную функцию разрешения имён (getaddrinfo в Linux), и та идёт по источникам в порядке из nsswitch.conf — часто сначала файл /etc/hosts, потом сервер имён. Поэтому ответ может прийти вообще без сети, а длительность этого шага задают настройки резолвера: в замере урока ненайденное имя стоило 12,0 секунды. Ограничит ли её таймаут клиента, зависит от API: таймаут сокета, поставленный после резолва, как у socket.create_connection в Python, блокирующий резолв не покрывает, а дедлайн на весь вызов покрывает — net.DialTimeout в Go включает разрешение имени в свой бюджет.

    Полный ответ — в уроке →

    Дальше спросят

  14. 14

    TLS-рукопожатие

    Рукопожатие стоит не работой процессора, а кругами — полётами до сервера и обратно, — и платится оно один раз за соединение, а не за запрос. Сколько именно кругов, зависит от версии: TLS 1.3 — один, TLS 1.2 — два. Измерено на звене с известным кругом: 43,6 мс против 84,7 мс при полном рукопожатии. Поэтому «первый запрос медленный» лечится переиспользованием соединения, а не отключением шифрования.

    Полный ответ — в уроке →

    Дальше спросят

  15. 15

    TIME_WAIT и порты

    TIME_WAIT — нормальный конец соединения, а не утечка. Закрывшая сторона ещё некоторое время держит свою пару адрес-порт, чтобы задержавшиеся сегменты старого соединения не были приняты новым соединением с теми же адресами и портами. Проблемой это становится у клиента, который открывает соединение на каждый запрос: у него кончаются не память и не дескрипторы, а номера портов. Измерено: при диапазоне в 50 номеров ровно 50 соединений и EADDRNOTAVAIL на пятьдесят первом.

    Полный ответ — в уроке →

    Дальше спросят

  16. 16

    Балансировка

    Круговой перебор раздаёт поровну число запросов, а не работу, поэтому он проигрывает, как только запросы неоднородны. Опрос двух случайных серверов забирает заметную часть выигрыша полного опроса, но его цена не растёт с размером парка. Модель: p99 ожидания 582,4 мс у кругового перебора, 123,6 у опроса двух и 42,9 у опроса всех.

    Полный ответ — в уроке →

    Дальше спросят

  17. 17

    Консистентное хеширование

    Деление по модулю привязывает владельца ключа к числу узлов, поэтому любое изменение состава пересчитывает всё; кольцо привязывает владельца к позиции ключа, поэтому меняются только ключи рядом с изменением. Посчитано на 100 000 ключей: добавление девятого узла к восьми переносит 88,9 % ключей при модуле и 11,5 % на кольце с одной точкой на узел.

    Полный ответ — в уроке →

    Дальше спросят

  18. 18

    Идемпотентность

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

    Полный ответ — в уроке →

    Дальше спросят

← Карта линии и итоговая проверка