На Хабре много говорилось о раздувании софта со временем, а также о перегрузке новыми фичами, что приводит к усложнению интерфейса и тому же раздуванию. Разработчики в целом склонны что-то добавлять, а не убирать, даже в ущерб результату. Исследования показали, что люди плохо справляются с поиском простых решений, которые противоречат шаблонному интуитивному мышлению (что-то добавить).

Что тут говорить, если самая простая программа сегодня весит под 100 МБ, как целая операционная система со всем софтом несколько десятилетий назад. Кто-то говорит, что причиной этого является закон Мура и рост производительности процессоров в геометрической прогрессии. В связи с этим даже интересно, каким был бы софт при замедлении CPU в двадцать раз.

Но есть выход из сложившейся ситуации: аккуратное отключение лишних функций в раздувшемся софте.

В докладе на прошлогодней конференции OSDI'23 «Defcon: грациозная деградация функций для предотвращения перегрузки» речь идёт не о предотвращении раздувания, а о защите системы от чрезмерной нагрузки (авторы доклада работают в экстремистской компании Meta). Но методы примерно такие же. Да и в широком смысле, если считать раздувание софта угрозой для его стабильности, то и отключение/деградация функций тоже выглядит как защита.

▍ Искусственная деградация функций


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

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


В первую очередь нужно убедиться, что сервис остаётся работоспособным при отключении любого элемента инфраструктуры (на КДПВ). Например, при отключении доступа к основной базе СУБД данные у клиента по-прежнему загружаются из кэша.

Автор другого доклада «Надёжная грациозная деградация: отказоустойчивость через границы служб» от 2021 года с конференции SREcon21 (CTO австралийского учебного портала StileEducation) называет ряд причин, по которым сервис может упасть «неграциозно»:

  • Случайные зависимости между сервисами
  • Взаимосвязь через рабочие процессы во фронтенде
  • Ошибочный/сломанный код обработки ошибок
  • Взаимозависимость сервисов (conditional coupling)
  • Редкие (необработанные) состояния ошибок:
    • Плохое кэширование DNS
    • Отказ узла базы данных
    • Очень медленные ответы

Рекомендуется заранее тестировать все возможные сценарии сбоя из CI и прогонять тесты после каждого изменения, включая юнит-тесты с клиентов на максимальное количество соединений и интеграционные тесты на минимально живучую систему:



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

▍ Продукты и функции


Любой интернет-сервис состоит из функций. Например, видеосервис включает в себя функции поиска, воспроизведения, рекомендаций и др. Они складываются в иерархическую структуру. Например, функция верхнего уровня (воспроизведение) включает функцию изменения качества видео или наложения субтитров.

Продукты (и, соответственно, функции) работают в центрах обработки данных, распределённых по всей планете. По аналогии с привычной архитектурой фон Неймана, вычисления в планетарном масштабе требуют ввода/вывода (в виде HTTP- и RPC-запросов), вычислений (в виде серверов), межсетевого взаимодействия (сеть), кэширования, хранения и т. д. Операторы сайтов размещают эти ресурсы в географически распределённых ЦОДах, чтобы объём требуемой работы не превышал предоставленных ресурсов, сети, серверов и др.

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

И поэтому иногда приходится прибегать к экстренным мерам, таким как отключение функций. Главная цель — обеспечить доступность продукта, не выделяя дополнительных ресурсов (которых нет).

▍ Система Defcon


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

Например, на диаграмме показана реальная нагрузка на систему в один из дней, измеренная в миллионах инструкций в секунду (MIPS), по сравнению с предыдущим днём (reference). Как видим, 27 октября 2022 года в районе 5 утра начался непредвиденный локальный пик. В 6:35 операторам пришлось вводить в действие систему Defcon, а в 7:15 активировать второй уровень защиты. В 8:00 система была отключена.



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

Все фичи отсортированы по важности и реализованы в виде RPC-запросов.

Для каждой сделан переключатель (knob), чтобы легко включить/выключить функцию:


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

from configs import ConfigReader
disableCommentsRanking = ConfigReader (
	"Feed/DisableCommentsRanking")
comments = fetchComments ()
if (disableCommentsRanking.enabled == False)
	comments.RankUsingModel ()
else #Knob enabled: do less work.
	comments.RankChronologically ()

Есть группы переключателей уровней 1, 2, 3, которые снижают нагрузку на серверы на 20%, 10% и 5%, соответственно.


Интересно, что при отключении функций почти все показатели упали, но некоторые неожиданно выросли (среднее время просмотра видео).


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

▍ Отключение ненужного


Как известно, менеджеры получают бонусы и премии за завершение проектов, то есть за внедрение новых функций в продукт, а не за отключение старых. В любой программе количество фич растёт со временем, а не снижается. Растёт и объём кода. Для примера, количество строк кода в разных версиях Windows:

Версия Год выхода Строк кода (млн)
Windows NT 3.1 1993 4−5
Windows NT 3.5 1994 7−8
Windows NT 4.0 1996 11−12
Windows 2000 2000 более 29
Windows XP 2001 45
Windows 7 2009 40
Windows 10 2015 80
С таким ростом кодовой базы не обойтись только оптимизацией и рефакторингом. Нужно удалять отдельные функции.

В ядре Linux оптимизацией занимается лично Линус Торвальдс. Почти в каждой новой версии он объявляет, что будет удалено. Иногда это довольно неочевидные вещи, как прекращение поддержки процессоров 486 с 6.2.

Удаление лишнего из Linux — стандартная практика, но кодовая база там тоже стабильно растёт:

Версия Год выхода Строк кода
0.01 1991 0,01
2.4.2 2011 2,4
2.6.0 2003 5,2
2.6.32 2009 12,6
3.6 2012 15,9
4.2 2015 20,2
6.6 2023 34,8
Какой из этого выход? В первую очередь нужно понять, что лишние функции — это как технический долг, лишняя нагрузка и на кодовую базу, и на когнитивные способности пользователей. Если какие-то функции использует 0,01% юзеров, то имеет смысл перенести их в плагины/расширения, чтобы основное ядро держать в оптимальном, то есть минимально возможном размере.

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

Но когда процесс раздувания уже необратим, единственной возможностью остаётся только переписать систему с нуля.

▍ Естественная деградация софта


Кроме искусственной деградации функций, существует и естественная деградация, причём она идёт сама собой без дополнительных усилий с нашей стороны. Даже наоборот, нужно прикладывать дополнительные усилия, чтобы её предотвратить. Устранять баги и технический долг, переходить на новые протоколы, производить необходимые обновления и т. д.

Вещи ломаются со временем, это нормально. Нет ничего вечного. И тот же самохостинг надо поддерживать. Довольно много технологий поддерживается не более трёх лет (версии LTS и др.), а то и меньше.

Например, в современном dotnet релиз LTS поддерживается три года, в Nodejs релиз LTS тоже поддерживается три года (6+30 месяцев), Angular поддерживается 12 месяцев, Go поддерживается два релиза.

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

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

▍ Выводы


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

Telegram-канал со скидками, розыгрышами призов и новостями IT ?

Комментарии (3)


  1. strvv
    27.05.2024 12:17

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

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


  1. Keeper10
    27.05.2024 12:17
    +2

    Строк кода

    0,01

    2,4

    [...]

    34,8

    Это в каких единицах?


    1. acsent1
      27.05.2024 12:17

      Наверное млн, как и у windows