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

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

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

Общие вопросы

  1. Каковы бизнес-цели и достигаем ли мы их в настоящее время?
  2. Каковы ожидания роста данных в следующие 12 месяцев для этого приложения?
  3. Профилируется ли приложение для производительности? Если да, то что используется и что он измеряет?
  4. Существуют ли какие-либо стресс-тесты, чтобы определить, где и когда система сломается? Например) Сколько одновременных пользователей могут выполнять действия, и какие действия, скорее всего, сломают систему под нагрузкой и т. д.
  5. Каково впечатление пользователей, когда система находится под нагрузкой? Очевидно ли для пользователей, что есть проблемы? Насколько это хорошо или плохо?
  6. Каковы ваши внутренние предчувствия относительно того, как система будет работать через 12 месяцев? Насколько это хорошо или плохо, по их мнению?
  7. Веб-серверы просто возвращают статический HTML, а все данные загружаются на стороне клиента? Или мы динамически генерируем HTML на сервере в зависимости от контекста запроса?
  8. Есть ли у нас какие-либо API и генерируют ли они JSON или что-то более тяжелое?

Доступность системы

  1. Выполняем ли мы какие-либо проверки работоспособности наших систем, и действительно ли эти проверки подтверждают работоспособность системы?
  2. Ставим ли мы в очередь всю работу, которая может занять много времени и не требует немедленных действий? Как долго мы можем поставить его в очередь, прежде чем он должен быть обработан? Нужен ли нам какой-то приоритет для этих элементов в очереди?
  3. Помимо базы данных, есть ли у нас какие-либо другие точки отказа, которые могут вывести систему из строя? Может быть, сторонняя служба, которая не масштабируется, или что-то в этом роде. Возможно ли, что мы можем запретить нашему приложению пытаться получить к нему доступ во время типичного HTTP-запроса, сделанного пользователем. Опять сводится к очереди.
  4. Когда система становится неработоспособной, мы немедленно предупреждены? Или наши клиенты видят, что система потенциально не работает, прежде чем мы узнаем об этом?
  5. Является ли наша система монолитом? Другими словами, когда часть системы выходит из строя, все приложение становится непригодным для использования? И легко ли разбить этот монолит на более мелкие и простые микросервисы?
  6. Если система выходит из строя и требуется исправление ошибки, сколько времени требуется для развертывания исправления? Есть ли у нас возможность войти на серверы и развернуть код вручную в экстренных ситуациях?
  7. Используем ли мы виртуальные машины, Docker или бессерверный код? Виртуальные машины долго загружаются и отключаются. Docker легче и быстрее загружается и отключается, но для предварительной настройки требуется больше работы. Бессерверный код требует меньше работы, чем Docker, и также является легким, но код вашего приложения не должен требовать сеансов (по крайней мере, лучше, если вы не пытаетесь реализовать сеансы).
  8. Если это веб-сервер, обслуживаем ли мы статические файлы? Должны ли мы вместо этого перенести их в CDN? Если нас не волнуют другие части мира, мы могли бы просто использовать какое-то хранилище BLOB-объектов.
  9. Если это веб-сервер, обслуживаем ли мы контент по HTTP2? HTTP2 лучше использует соединения, поэтому маловероятно, что у вас закончатся одновременные соединения.
  10. Гарантируем ли мы существование нескольких экземпляров нашего приложения и их географическую избыточность? Если один дата-центр выйдет из строя, наше приложение все равно будет работать.

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

  1. Можем ли мы масштабировать приложение на несколько экземпляров с помощью балансировщика нагрузки или у нас есть единая точка отказа?
  2. Если один из серверов выйдет из строя и перейдет в неработоспособное состояние, можем ли мы быстро вывести его из балансировщика нагрузки и заменить? Как быстро мы можем это сделать?
  3. Есть ли у нас стратегия развертывания для наших кластерных серверов. Например) сине-зеленое развертывание, непрерывное развертывание и т. д.
  4. Требует ли наше приложение сеансов? Если да, то требуются ли сеансы, хранящиеся в памяти, липких сеансов ИЛИ можем ли мы использовать сервер состояний или базу данных сеансов?

Целостность данных и производительность

  1. Все наши данные хранятся в одной централизованной базе данных? Если да, то нужно ли это? Можем ли мы разделить базы данных на более мелкие для разных целей, или это повлияет на ссылочную целостность?
  2. Возвращает ли какой-либо из наших запросов больше данных, чем необходимо (больше данных по сети), и/или мы присоединяемся к таблицам, которые не нужны (ненужные объединения и т. д.)
  3. Используем ли мы хранимые процедуры или специальные запросы (ORM) для реляционных баз данных? Если специальные, то эффективны ли запросы?
  4. Есть ли в базе данных правильно определенная индексация? Индексы не очень хороши, если у вас много операций записи, но хороши, если у вас много операций чтения. Являются ли индексы, охватывающие поля в предложениях where и т. д. для чтения.
  5. Можем ли мы уменьшить количество операций чтения в нашей базе данных с помощью кэширования и аннулировать кеш (или напрямую записывать в кеш) при внесении изменений.
  6. Выполняем ли мы интенсивные отчеты по текущей базе данных? Если да, то это потому, что мы запрашиваем исторические данные? Можем ли мы перенести исторические данные? Можем ли мы вместо этого складировать его?
  7. Используем ли мы CQRS (разделение ответственности за запросы команд), чтобы отделить записи в базу данных от наших операций чтения? Можем ли мы иметь базу данных для чтения и записи?
  8. Хранятся ли данные в реляционной базе данных, но являются ли они иерархическими? Например, вместо этого данные могут быть встроены с использованием базы данных документов.
  9. Выполняем ли мы поисковые запросы к данным в базе данных. Можем ли мы вместо этого проиндексировать результаты в поисковом индексе и запросить его вместо этого?
  10. Можем ли мы масштабировать базы данных, которые у нас есть сейчас. Другими словами, можно ли его повторить? Будет ли возможная согласованность проблемой для этой системы?
  11. Наши запросы к базе данных сложны (много объединений и т.д.). Можем ли мы вместо этого использовать материализованные представления, чтобы проекции данных не попадали в базу данных?
  12. Можем ли мы разделить базу данных на более мелкие разделы? Это может понадобиться.

Отказоустойчивость системы

  1. Если что-то пойдет не так, данные согласуются (транзакции либо фиксируются, либо откатываются и т. д.). Является ли система ACID и должна ли она быть такой?
  2. Выполняем ли мы правильный логический шаблон повторных попыток? Не только количество повторных попыток, но и период задержки перед следующей попыткой.
  3. Невелики ли тайм-ауты сети и базы данных? Несмотря на то, что большинство разработчиков боятся делать их низкими из-за производительности, не делая этого, мы скрываем потенциальные проблемы с производительностью.
  4. В случае проблем с сетью и проблем с тайм-аутом, реализуем ли мы шаблон автоматического выключателя. Программируем ли мы оборонительно, когда системы выходят из строя? Какую стратегию мы используем в этом случае и почему?
  5. Если мы автоматически масштабируем наше приложение, при каких обстоятельствах мы автоматически масштабируемся? Это зависит только от памяти и процессора? Что если у нас есть очередь запросов или сетевая задержка?
  6. Есть ли у нас географическая избыточность для всех наших сервисов? Балансируем ли мы нагрузку на наши серверы в нескольких центрах обработки данных на случай, если один из центров обработки данных выйдет из строя?

Техническое обслуживание, диагностика и аналитика

  1. Применяем ли мы достаточное ведение журнала приложений, и ведется ли ведение журнала на сервере, на котором выполняется код, или на наборе серверов журналов? Планируется ли централизованное ведение журнала?
  2. Можем ли мы в режиме реального времени сообщать о работоспособности сервера или группы серверов в кластере? Есть ли у нас оповещения, информирующие нас о потенциальных проблемах?
  3. Мы исправляем виртуальные машины сами (IAS) или используем облачные (PAS) системы? Позволяет ли система PAS увидеть его здоровье?
  4. Нужны ли нам виртуальные машины, потому что у нас есть собственные лицензии?
  5. Нужны ли нам виртуальные машины из-за зависимостей кода? Можем ли мы обновить эти сервисы или нам нужно переписать наше приложение, чтобы в конечном итоге их исключить?
  6. Реализуем ли мы какие-либо оповещения на основе ошибок в системе. Если да то что и почему? Если нет, то о чем мы должны предупреждать и почему?
  7. Собираем ли мы какую-либо телеметрию в нашем приложении? И если да, то можем ли мы сообщать о такой телеметрии? Почему или почему нет?
  8. Получаем ли мы оповещения, когда определенные части системы работают медленно? Если да, то являются ли измеренные условия точными?

Безопасность системы

  1. Требуется ли приложение для соблюдения набора документов о соответствии PCI?
  2. Выявляет ли код какие-либо XSS-уязвимости?
  3. Защищает ли код от CSRF-атак?
  4. Гарантирует ли код параметризацию всех запросов к базе данных?
  5. Есть ли у системы в целом собственный поставщик удостоверений для единого входа и федеративного доступа? Или он использует одну или несколько сторонних служб аутентификации (например, Auth0, Twitter, Facebook, Github и т. д.)? Или делает и то, и другое? Где точки интеграции для этого?
  6. Как и в предыдущем пункте, все ли системы защищены аутентификацией на основе токенов? Используем ли мы токены доступа и обновления? Это JWT, SAML или что-то еще? Как долго действует токен обновления, прежде чем пользователю потребуется повторная аутентификация?
  7. Все ли URL-адреса доступны только по HTTPS? Если нет, то почему?
  8. Все ли файлы cookie помечены как HTTP Only? Если да, то почему бы и нет?
  9. Если в нашей системе есть учетные данные пользователя, хешируются ли пароли? Если да, то они соленые, и каков алгоритм хеширования?
  10. Все ли не общедоступные серверы надежно защищены демилитаризованной зоной в частных подсетях, и все ли таблицы маршрутов и брандмауэры настроены на предоставление минимального доступа?
  11. Используем ли мы серверы Bastion, чтобы сократить количество подключенных к Интернету нескольких серверов?
  12. Есть ли у нас защищенный VPN-доступ к серверам Bastion для работы вне офиса?
  13. Есть ли у нас какие-либо локальные зависимости, и если да, то является ли шлюз между этими серверами и серверами в облаке безопасным?

Производительность кода

  1. Можно ли запустить наш код в дистрибутивах Linux (еще лучше в Docker). Поскольку Linux легковесен, а Docker еще легче.
  2. Пишем ли мы производительный код? Например, гарантируем ли мы, что мы не блокируем потоки запросов при выполнении операций ввода-вывода для получения данных из внешних систем. Если мы используем ORM, не хотим ли мы слишком много загружать для определенных запросов? Если мы используем ленивую загрузку, мы слишком много ленивой загрузки? Опять же, можем ли мы просто полностью отказаться от реляционных данных и вместо этого использовать хранилище документов и получать все за один раз?
  3. Используем ли мы параллелизм в нашем приложении. Если да, то почему? Не принимаем ли мы параллелизм за то, что должно быть асинхронной обработкой? Отрывать темы по своему желанию нехорошо.
  4. Правильно ли мы фиксируем ошибки в нашем приложении и возвращаем правильные ответы? Следим ли мы за тем, чтобы не проглатывать (или не скрывать) исключения приложений?

Другие зависимости

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

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

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

Спасибо за чтение.