Учебник по нагрузочному тестированию вашего сервера socket.io WebSockets

Вы поставляете масштабируемую серверную часть в реальном времени? В этой статье содержится руководство по нагрузочному тестированию вашего сервера WebSocket на базе socket.io для моделирования производственной нагрузки и выявления узких мест производительности или проблем с масштабируемостью .

Socket.io - это фреймворк, построенный на основе протокола WebSocket, который обновляет HTTP-соединение с помощью заголовка Upgrade: websocket, инициируя рукопожатие WebSocket.

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

socket.io добавляет к этому дополнительные функции, такие как усиление поддержки вашего приложения браузером и устройствами, предоставляя возможность отката к запросам Ajax при использовании клиента, который не поддерживает WebSockets, или клиента в сети, который ограничивает обновить HTTP-заголовок или изменения протокола.

Настраивать

Чтобы следовать этому руководству, вы можете либо клонировать и запустить демонстрационный репозиторий локально (предлагается), либо вы можете использовать версию, размещенную мной на Heroku.

Если вы решите запустить приложение локально, вам нужно будет клонировать репозиторий и установить необходимые зависимости с помощью npm. Сценарий npm start запустит приложение на вашем настроенном PORT или 8080 по умолчанию.

Сначала познакомимся с приложением. После запуска приложение должно работать, как показано ниже.

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

Ниже приведен пример двух разных пользователей, отправляющих и получающих сообщения в реальном времени - отлично!

Нагрузочное тестирование

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

Чтобы установить набор инструментов Artillery.io глобально:

$ npm install artillery -g

Далее нам нужно создать конфигурационный файл YAML, в котором будут указаны конфигурация теста и сценарии.

simple-test.yaml

config:
  target: "wss://socketio-loadtest.herokuapp.com"
  socketio:
    transports: ["websocket"]
  phases:
    - duration: 10 # Run scenario for 10 seconds
      arrivalCount: 20 # Create 20 virtual users per scenario
scenarios:
  - engine: "socketio"
    flow:
      - emit:
          channel: "add user"
          data: "John Doe"
      - emit:
          channel: "new message"
          data: "Hello! {{ $randomString() }}"
      - think: 5 # do nothing for 5 seconds, then disconnect

В приведенном выше файле конфигурации мы указываем наш целевой URL и движок Socket.IO. Мы настраиваем наш раздел phases, чтобы указать количество виртуальных пользователей, которых мы будем эмулировать, и продолжительность теста. Изначально это низкие цифры.

В разделе scenarios мы указываем, какие события WebSocket мы хотим, чтобы клиент artillery.io отправлял на сервер.

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

Чтобы запустить приведенный выше сценарий, мы будем использовать команду artillery run.

$ artillery run load-test/simple-test.yaml

Если мы просматриваем наше приложение в браузере (локально или на https://socketio-loadtest.herokuapp.com), можно увидеть, как виртуальные пользователи присоединяются к чату и оставляют сообщения.

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

Утверждения

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

Мы можем установить максимально допустимую задержку в миллисекундах для min, max, median, p95 и p99 или максимальный процент отказов. Их можно настроить для повторного тестирования определенных бизнес-правил или SLO.

Чтобы настроить вышеуказанное, мы добавляем запись ensure в нашу конфигурацию. Дополнительные примеры можно найти в документации artillery.io.

config:
  target: "ws://localhost:8080"
  ensure:
    maxErrorRate: 1 # fail if error rate exceeds 1%
    max: 500 # fail if max response time exceeds 500ms

Расширенная конфигурация

В расширенном примере динамические переменные используются для моделирования сценария, который ближе к тому, как приложение будет использоваться в производственной среде (реальные данные). Это делается с помощью модуля npm faker внутри специального процессора, который позволяет нам запускать наш собственный код.

Фаза загрузки настроена для увеличения скорости поступления с 10 до 50 пользователей в течение двух минут, за которыми следуют 10 минут со скоростью 50 новых пользователей в секунду.

advanced-test.yaml

config:
  target: "ws://localhost:8080"
  ensure:
    max: 500 # fail if max response time exceeds 500ms
    maxErrorRate: 1 # fail if error rate exceeds 1%
  socketio:
    transports: ["websocket"]
  processor: "./custom.js" # set a processor for dynamic variables
  phases:
    - duration: 120
      arrivalRate: 10
      rampTo: 50
      name: "Warm up phase"
    - duration: 600
      arrivalRate: 50
      name: "Sustained max load"
scenarios:
  - engine: "socketio"
    flow:
      - function: "getChatData" # load variables
      - emit:
          channel: "add user"
          data: "{{ name }}"
      - emit:
          channel: "new message"
          data: "{{ greeting }}"
      - think: 10 # stay connected for 10 seconds
      - emit:
         channel: "new message"
         data: "{{ goodbye }}"

Запуск артиллерии с помощью файла advanced-test.yaml

$ artillery run load-test/advanced-test.yaml

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

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

Резюме

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

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

Следующим в серии блогов Socket.IO будет руководство по отладке утечек памяти в приложениях Socket.IO. Если у вас есть идеи на похожие темы, которые вас интересуют, не стесняйтесь обращаться к ним.