Привет 👋, товарищ инженер-программист !!

Добро пожаловать в мою серию, где я делюсь тем, что узнал из своей работы и книг, которые я прочитал. Говоря о книгах, вы читали «Проектирование приложений, интенсивно использующих данные»? Это действительно одна из лучших и наиболее полных книг. Но хватит о книгах, поговорим о нас.

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

Если у вас есть какие-либо отзывы или вы хотите начать обсуждение, свяжитесь со мной в моем Твиттере @_imnaren или в LinkedIn. Я всегда готов поболтать.

Давайте начнем с основного вопроса — что такое дизайн системы и почему это важно.

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

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

При обсуждении дизайна вы бы столкнулись с такими аргументами, как

«это не ремонтопригодно, требуется слишком много шагов для адаптации»

«Как бы вы это масштабировали? Ожидается, что рабочая нагрузка вырастет в 10 раз к концу года»

«есть единая точка отказа, это не отказоустойчивость»

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

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

Надежность

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

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

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

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

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

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

  • Избыточность. Одним из распространенных методов повышения надежности системы является избыточность. Это включает в себя дублирование критически важных компонентов или подсистем, так что в случае отказа одной из них ее может взять на себя другая. Существуют различные типы резервирования, такие как «горячий» резерв, «холодный» резерв и активно-активное резервирование, в зависимости от уровня резервирования и стоимости его обслуживания.
  • Тестирование и проверка. Еще одним ключевым методом обеспечения надежности системы является тестирование и проверка. Это включает в себя тестирование системы в различных условиях, включая нормальные и ненормальные сценарии, чтобы убедиться, что она ведет себя так, как ожидалось. Существуют различные типы тестирования, такие как модульное тестирование, интеграционное тестирование и системное тестирование, каждое из которых фокусируется на разных уровнях системы и типах функциональности.
  • Отказоустойчивая конструкция. Отказоустойчивая конструкция предполагает проектирование системы, которая способна продолжать работу даже при наличии сбоев или ошибок. Это может включать в себя такие методы, как обнаружение ошибок, исправление ошибок и плавная деградация, которые позволяют системе продолжать функционировать, даже если некоторые компоненты работают неправильно.
  • Мониторинг и восстановление. Методы мониторинга и восстановления включают постоянный мониторинг системы на наличие потенциальных сбоев или ошибок и принятие корректирующих действий по мере необходимости. Это может включать такие методы, как ведение журнала, оповещение и автоматическое восстановление, которые могут минимизировать время простоя и обеспечить доступность и надежность системы.
  • Безопасность и контроль доступа. Обеспечение безопасности и контроля доступа к системе — еще один важный метод повышения надежности. Это включает в себя защиту системы на разных уровнях, таких как сеть, приложение и хранилище данных, а также реализацию контроля доступа для предотвращения несанкционированного доступа или модификации системы.

KPI для измерения и отслеживания надежности системы:

  • Среднее время наработки на отказ (MTBF): этот показатель измеряет среднее время наработки на отказ системы. Более высокое среднее время безотказной работы указывает на более надежную систему.
  • Среднее время до отказа (MTTF): этот показатель измеряет среднее время до первого отказа системы. Более высокое значение MTTF указывает на более надежную систему.
  • Среднее время восстановления (MTTR): этот показатель измеряет среднее время, необходимое для устранения сбоя системы. Более низкий показатель MTTR указывает на более надежную систему.
  • Доступность. Этот показатель измеряет процент времени, в течение которого система доступна и работает правильно. Более высокая доступность указывает на более надежную систему.
  • Коэффициент ошибок. Этот показатель измеряет процент транзакций или операций, которые приводят к ошибкам или сбоям. Более низкая частота ошибок указывает на более надежную систему.
  • Отказоустойчивость. Этот показатель измеряет способность системы продолжать работу даже в условиях частичных сбоев или ошибок. Более высокий уровень отказоустойчивости указывает на более надежную систему.
  • Целевое время восстановления (RTO): этот показатель измеряет количество времени, необходимое для восстановления после системного сбоя и восстановления нормальной работы. Более низкий RTO указывает на более надежную систему.
  • Цель точки восстановления (RPO). Этот показатель измеряет допустимый объем потери данных в случае сбоя системы. Более низкий RPO указывает на более надежную систему.

Масштабируемость

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

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

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

Производительность, с другой стороны, относится к тому, насколько хорошо система или приложение соответствует ожидаемым целям и требованиям. Производительность можно измерять различными способами, такими как время отклика, пропускная способность или частота ошибок. Наиболее рекомендуемая практика измерения производительности с точки зрения медианы не означает. Среднее значение не говорит вам, сколько пользователей действительно столкнулись с этой задержкой. Процентили 95, 99 и 99,9 (p95, p99 и p999) хороши, чтобы выяснить, насколько плохи ваши планировщики.

Вот несколько методов, которые можно использовать для разработки масштабируемой системы:

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

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

KPI для измерения и отслеживания надежности системы:

  • Время отклика. Этот показатель измеряет время, необходимое системе для ответа на запрос пользователя или транзакцию. Меньшее время отклика указывает на более масштабируемую систему.
  • Пропускная способность. Этот показатель измеряет количество транзакций или запросов, которые система может обработать за определенный период времени. Более высокая пропускная способность указывает на более масштабируемую систему.
  • Использование ресурсов. Этот показатель измеряет количество ресурсов, таких как ЦП, память и диск, которые использует система. Меньшее использование ресурсов указывает на более масштабируемую систему.
  • Параллелизм. Этот показатель измеряет количество пользователей или транзакций, которые система может обрабатывать одновременно. Более высокий параллелизм указывает на более масштабируемую систему.
  • Эластичность. Этот показатель измеряет способность системы автоматически увеличивать или уменьшать масштаб в ответ на изменения спроса или рабочей нагрузки. Более высокий уровень эластичности указывает на более масштабируемую систему.
  • Задержка. Этот показатель измеряет задержку или время ожидания между запросом пользователя и ответом системы. Более низкая задержка указывает на более масштабируемую систему.

Ремонтопригодность

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

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

  • Модульность. Модульная конструкция – это метод разбиения сложной системы на более мелкие, более управляемые части или модули. Это позволяет разработчикам работать над разными частями системы независимо, не затрагивая остальную часть системы. Модульная конструкция упрощает поиск и исправление ошибок или внесение изменений в определенные части системы, не затрагивая всю систему.
  • Абстракция. Абстракция – это метод сокрытия деталей реализации и раскрытия только основных функций системы или модуля. Этот метод помогает уменьшить сложность системы, упрощая ее обслуживание и понимание.
  • Инкапсуляция. Инкапсуляция – это метод группировки данных и методов, которые работают с этими данными, в единый блок или класс. Этот метод помогает скрыть внутренние детали модуля или компонента от других частей системы, снижая риск непреднамеренных изменений и упрощая обслуживание.
  • Стандартизация. Стандартизация включает определение и соблюдение набора стандартов кодирования, передовых методов и соглашений для разработки программного обеспечения. Это помогает обеспечить согласованность и предсказуемость системы, облегчая ее обслуживание с течением времени.
  • Документация. Документация является важным аспектом поддержки программной системы. Это включает в себя создание и поддержание четкой, краткой и актуальной документации по дизайну, архитектуре, коду и процессам системы. Хорошая документация облегчает разработчикам понимание и поддержку системы с течением времени.

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

KPI для измерения и отслеживания ремонтопригодности системы:

  • Среднее время восстановления (MTTR). Этот ключевой показатель эффективности измеряет среднее время, необходимое для исправления системы после возникновения сбоя. Низкий показатель MTTR указывает на то, что систему легко диагностировать и ремонтировать, что является признаком хорошей ремонтопригодности.
  • Среднее время наработки на отказ (MTBF). Этот KPI измеряет среднее время наработки на отказ системы. Высокая наработка на отказ указывает на то, что система надежна и хорошо обслуживается.
  • Сложность кода. Сложность кода измеряет степень сложности понимания и поддержки кода системы. Высокая сложность кода может указывать на то, что систему сложно поддерживать.
  • Дублирование кода. Дублирование кода измеряет количество дублированного кода в системе. Высокий уровень дублирования кода может указывать на плохой дизайн и ремонтопригодность.
  • Покрытие тестами. Покрытие тестами измеряет процентную долю системы, покрытой автоматическими тестами. Высокий охват тестами может указывать на то, что система хорошо протестирована и ее легче поддерживать.
  • Технический долг. Технический долг измеряет стоимость обслуживания системы с течением времени. Высокий уровень технического долга может указывать на плохой дизайн и ремонтопригодность.

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