Существует множество факторов, которые приводят к зависанию, низкой производительности или сбоям в работе приложений. Опрошенные порталом InformationWeek эксперты рассказывают, как всего этого избежать.

Agile-разработка, DevOps, непрерывная интеграция/непрерывная доставка (CI/CD), непрерывное тестирование и многое другое. Все эти практики направлены на повышение качества ПО и сокращение времени его выхода на рынок. А благодаря всем инструментам, доступным разработчикам, тестировщикам, архитекторам, инженерам инфраструктуры и другим специалистам, может показаться, что добиться безотказной работы будет проще, чем раньше. Однако растущая сложность ПО и наш опыт как потребителей и бизнес-пользователей часто говорят о другом.

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

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

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

«Долгое время я не пользовался Instagram (проект компании Meta, деятельность которой в России запрещена), но много слышал о том, что это чудесное, волшебное приложение, — говорит Белов. — Потом, когда я его установил, я был очень разочарован. Дизайн и юзабилити очень плохие, а производительность — очень низкая».

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

1. Поймите, какой уровень надежности требуется для приложения или сервиса

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

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

2. Избегайте придания качеству второстепенного значения

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

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

3. Не стоит недооценивать сложность реальных сред

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

«За свою карьеру, включая руководство революционными проектами в General Motors и консультирование компаний из списка Fortune 200, я понял, что одна из самых больших ошибок разработчиков — недооценка сложности реальных пользовательских сред, — говорит Тимоти Бейтс, профессор Мичиганского университета и бывший технический директор Lenovo. — Всестороннее нагрузочное тестирование и учет крайних случаев имеют решающее значение. По моему опыту, самые слабые звенья часто кроются в неадекватной обработке ошибок и отсутствии планирования масштабируемости. Мой совет: всегда проектируйте с учетом масштабируемости и отказоустойчивости, чтобы обезопасить свои приложения на будущее».

4. Подумайте об отказоустойчивости, пока не стало слишком поздно

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

«Лучший способ предотвратить проблемы с производительностью — это изначально правильно подобрать размер среды. Это означает понимание моделей использования, понимание сезонности вашего бизнеса и трату дополнительного времени и денег на избыточное резервирование, — говорит Маркус Меррелл, главный стратег по тестированию компании Sauce Labs. — Следующий лучший способ обеспечить стабильную производительность — это иметь план резервного копирования. Вам нужна отказоустойчивая среда (или облачный регион). Ваш мониторинг производительности приложений должен быть настроен таким образом, чтобы он обнаруживал признаки сбоя на ранней стадии и позволял переключиться на альтернативную среду без особых проблем».

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

5. Не слишком полагайтесь на автоматизацию

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

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

6. Не относитесь к безопасности как к чему-то второстепенному

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

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

7. Остерегайтесь зараженного открытого исходного кода

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

«ПО с открытым исходным кодом становится основным вектором атак на приложения и среды разработки, — говорит Никастро. — Такие вещи, как путаница в пространстве имен и атаки на зависимости, например бэкдор XZ, могут привести к тому, что разработчик может подвергнуть организации риску, случайно поставив не тот пакет. Понимание гигиены Open Source-пакетов и проверка всех пакетов перед их внедрением в продукт являются обязательными».

8. Будьте способны определить приоритетность дефектов ПО

Ошибки безопасности, надежности и производительности встречаются слишком часто. По словам Дэвида Брумли, профессора кибербезопасности Университета Карнеги-Меллона, при попытке добиться устойчивой производительности приложения речь идет не об устранении всех ошибок, а об исправлении тех, которые возникают часто и оказывают наиболее существенное влияние.

«Расстановка приоритетов имеет решающее значение не только для команд разработчиков, но и для различных функций. Это означает, что команды разработчиков должны создавать продукты, ориентируясь на клиента, и удовлетворять его потребности, — говорит он. — Разработка на основе тестирования и такие практики, как интегрированная безопасность („secure by design“), могут помочь достичь этого, установив критерии приемлемости в самом начале разработки. С технической точки зрения разработчики должны использовать методы состязательного тестирования — писать модульные тесты для „счастливого пути“ и использовать такие подходы, как фаззинг-тестирование или хаос-инженерия, для проверки „что если“ и крайних случаев».

9. Не ограничивайтесь очевидными ошибками

По словам Мэтта Мачуги, старшего директора по инженерии компании Oyster, чтобы обеспечить высокую доступность сервиса и удовлетворенность пользователей, командам и компаниям крайне важно постоянно задаваться вопросом «А что, если?». «Например, что если собственный или сторонний сервис выйдет из строя? Вместо того чтобы показывать стандартную страницу ошибки и заставлять пользователей терять свою работу, подумайте, не предпочтут ли они автоматическую повторную попытку от их имени. Если и это не поможет, подумайте о том, как сохранить их состояние, дать им понять, что что-то не так и что вы повторите попытку позже», — поясняет он.

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

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

10. «Счастливый путь» может вести в ловушку

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

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

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

11. Проектирование для обеспечения бесперебойной работы

Максимальная доступность крайне важна для любого программного приложения, чтобы обеспечивать бесперебойную работу, поддерживать удовлетворенность клиентов и максимизировать возможности получения дохода. 98% компаний сталкиваются с финансовыми потерями из-за простоя приложений, превышающими 100 тыс. долл. в час. Кроме того, каждый шестой простой приводит к потерям, превышающим 1 млн. долл. Они связаны исключительно с производительностью и потерей данных. Еще большие потери могут быть связаны с репутационным ущербом и оттоком клиентов. Поэтому, по словам Лукмана Саида, эксперта по Jakarta EE компании Payara Services, поставщика серверов приложений с открытым исходным кодом, максимальное время безотказной работы играет ключевую роль в определении успеха бизнеса.

«Высокая доступность приложений должна рассматриваться на ранней стадии проектирования, в соответствии с принципами интегрированного качества („quality by design“), — говорит он. — Эксперты в предметной области (SME) должны определить ключевые функции и возможности, которые должны быть включены, а также подходящие стратегии снижения времени простоя. На этом этапе очень важно учитывать бизнес-требования, которым должно удовлетворять приложение, а также условия эксплуатации».

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

12. Применяйте правильную практику DevOps

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

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