Учебное пособие по WebSocket «IM Series»: как использовать JMeter для стресс-тестирования
Учебное пособие по WebSocket «IM Series»: как использовать JMeter для стресс-тестирования

JMeter

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

Установить

Адрес загрузки: https://jmeter.apache.org/download_jmeter.cgi.

Windows может напрямую загрузить двоичный файл

Файлы для скачиваниякопировать/Перейти в локальный каталог。Я здесь прямокопироватьприезжатьDтарелка,D:\apache-jmeter-5.4.1

Установить пакет плагина Websocket

Адрес загрузки: https://bitbucket.org/pjtr/jmeter-websocket-samplers/downloads/

Файлы для скачиваниякопировать/двигатьсяприезжатьD:\apache-jmeter-5.4.1\lib\extв каталоге

Запустить Jmeter

Введите каталог исполняемого файлаD:\apache-jmeter-5.4.1\binНайти командный файлjmeter.bat

Первыйдобавить вгруппа потоковTinywan Thread Group,Нажмите еще раздобавить вsampler, вы можете увидеть информацию о веб-сокете

На приведенном выше снимке экрана показано, что установка плагина прошла успешно.

Напишите план тестирования

Здесь вы можете заполнить соответствующие параметры согласно предыдущему уроку.

Язык кода:javascript
копировать
var ws = new WebSocket("ws://127.0.0.1:8783");

План тестирования малого стека технологии с открытым исходным кодом.jmx

1. Подключитесь

Выберите протоколws/wss,входитьipпортпутьПараметры запроса(Если параметров нет, оставьте их пустыми.)

2.0 Присоединиться к групповому чату

JMeter

Язык кода:javascript
копировать
let $_content = {
  "event": "join",
  "mode": 2,
  "group_id": 100,
  "from_user_id": "10086",
  "from_username": «Аксу»,
  "to_user_id": "10000",
  "content": «Присоединиться к разговору»,
};
console.log(JSON.stringify($_content))

JSON.stringify() метод преобразует JavaScript Объект или значение, преобразованное в JSON нить.

Разберите приведенное выше в строку JSON.

Язык кода:javascript
копировать
{"event":"join","mode":2,"group_id":100,"from_user_id":"10086","from_username":«Аксу»,"to_user_id":"10000","content":"Присоединиться к беседе"}

3.0 Обсуждение

Запросить контент для отправки

Язык кода:javascript
копировать
let content = {
      "event": "speak",
      "mode": 2,
      "group_id": 100,
      "from_user_id": "10086",
      "from_username": «Аксу»,
      "to_user_id": "10000",
      "content": "WebSocketУчебное пособие: Реализация и применение сохраняемости сообщений",
   }
console.log(JSON.stringify(content))

JSON.stringify() метод преобразует JavaScript Объект или значение, преобразованное в JSON нить.

Разберите приведенное выше в строку JSON.

Язык кода:javascript
копировать
{"event":"speak","mode":2,"group_id":100,"from_user_id":"10086","from_username":«Аксу»,"to_user_id":"10000","content":"WebSocketУчебное пособие: Реализация и применение сохраняемости сообщений"}

4. Сердцебиение

Создайте контроллер цикла

Добавить сэмплер WebSocket

Запросить контент

Язык кода:javascript
копировать
{"event":"ping","content":"ping heartbeat"}

5. Добавить дерево результатов просмотра

На рисунке выше показано дерево просмотра результатов выполнения. В правом окне вы можете увидеть результаты выборки, запросы и ответы. Запрос — это запрос, отправленный клиентом на сервер, а данные ответа — это возвращаемый результат. сервером после получения запроса. Вы можете выбрать различные методы просмотра результатов, включая json, html, xpath и т. д.

6. Добавьте агрегированные отчеты

Запустите JMeter

1.0 Подключение

Запросить данные

данные ответа

2.0 Обсуждение

Запросить данные

данные ответа

Совокупные отчеты, чтобы увидеть производительность

  • Выборки: общее количество выборок, равное общему количеству потоков * количеству циклов.
  • Среднее: Среднее время обработки запроса (миллисекунды), которое является одним из основных показателей стресс-теста.
  • Медиана: медианное время обработки запроса (мс). Половина времени обработки по количеству выборок превышает это значение, а половина времени обработки ниже этого значения.
  • 90%Line,95%Line,99%Line: какой процент времени обработки в выборке находится ниже этого значения.,Является одним из основных показателей стресс-теста.
  • Мин. Время запроса, которое занимает наименьшее количество времени.
  • Макс: Запрос, который занимает больше всего времени.
  • Error%: процент ошибок.
  • Пропускная способность: Пропускная способность, количество запросов, которые сервер обрабатывает в секунду.
  • КБ/сек: количество байтов, запрашиваемых сервером в секунду.

другой

Скрипт стресс-теста JMeter

Скачать адрес:https://github.com/Tinywan/webman-admin/blob/main/db/План тестирования малого стека технологии с открытым исходным кодом.jmx

План тестирования малого стека технологии с открытым исходным кодом.jmx

Язык кода:javascript
копировать
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.4.1">
  <hashTree>
    <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Стек технологий с открытым исходным кодом План тестирования" enabled="true">
      <stringProp name="TestPlan.comments"></stringProp>
      <boolProp name="TestPlan.functional_mode">false</boolProp>
      <boolProp name="TestPlan.serialize_threadgroups">true</boolProp>
      <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
        <collectionProp name="Arguments.arguments">
          <elementProp name="username" elementType="Argument">
            <stringProp name="Argument.name">username</stringProp>
            <stringProp name="Argument.value">Tinywan</stringProp>
            <stringProp name="Argument.metadata">=</stringProp>
          </elementProp>
          <elementProp name="password" elementType="Argument">
            <stringProp name="Argument.name">password</stringProp>
            <stringProp name="Argument.value">xxxx</stringProp>
            <stringProp name="Argument.metadata">=</stringProp>
          </elementProp>
        </collectionProp>
      </elementProp>
      <stringProp name="TestPlan.user_define_classpath"></stringProp>
    </TestPlan>
    <hashTree>
      <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Im Websocket Испытание давлением" enabled="true">
        <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
        <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Контроллер цикла" enabled="true">
          <boolProp name="LoopController.continue_forever">false</boolProp>
          <stringProp name="LoopController.loops">500</stringProp>
        </elementProp>
        <stringProp name="ThreadGroup.num_threads">1</stringProp>
        <stringProp name="ThreadGroup.ramp_time">1</stringProp>
        <boolProp name="ThreadGroup.scheduler">false</boolProp>
        <stringProp name="ThreadGroup.duration"></stringProp>
        <stringProp name="ThreadGroup.delay"></stringProp>
        <boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
      </ThreadGroup>
      <hashTree>
        <CriticalSectionController guiclass="CriticalSectionControllerGui" testclass="CriticalSectionController" testname="контроллер критической секции" enabled="false">
          <stringProp name="CriticalSectionController.lockName">global_lock</stringProp>
        </CriticalSectionController>
        <hashTree/>
        <eu.luminis.jmeter.wssampler.OpenWebSocketSampler guiclass="eu.luminis.jmeter.wssampler.OpenWebSocketSamplerGui" testclass="eu.luminis.jmeter.wssampler.OpenWebSocketSampler" testname="1.0 Подключение" enabled="true">
          <boolProp name="TLS">false</boolProp>
          <stringProp name="server">127.0.0.1</stringProp>
          <stringProp name="port">8783</stringProp>
          <stringProp name="path">/?sign=ca7a2df4c9850239ded1974f5abe8fc7&amp;ws_timestamp=1636079196</stringProp>
          <stringProp name="connectTimeout">20000</stringProp>
          <stringProp name="readTimeout">6000</stringProp>
        </eu.luminis.jmeter.wssampler.OpenWebSocketSampler>
        <hashTree/>
        <eu.luminis.jmeter.wssampler.RequestResponseWebSocketSampler guiclass="eu.luminis.jmeter.wssampler.RequestResponseWebSocketSamplerGui" testclass="eu.luminis.jmeter.wssampler.RequestResponseWebSocketSampler" testname="2.0 Присоединиться к групповому чату" enabled="true">
          <boolProp name="createNewConnection">false</boolProp>
          <boolProp name="TLS">false</boolProp>
          <stringProp name="server"></stringProp>
          <stringProp name="port">80</stringProp>
          <stringProp name="path"></stringProp>
          <stringProp name="connectTimeout">20000</stringProp>
          <boolProp name="binaryPayload">false</boolProp>
          <stringProp name="requestData">{&quot;event&quot;:&quot;join&quot;,&quot;mode&quot;:2,&quot;group_id&quot;:100,&quot;from_user_id&quot;:&quot;10086&quot;,&quot;from_username&quot;:&quot;Аксу&quot;,&quot;to_user_id&quot;:&quot;10000&quot;,&quot;content&quot;:&quot;Присоединиться к разговору&quot;}</stringProp>
          <stringProp name="readTimeout">6000</stringProp>
          <boolProp name="loadDataFromFile">false</boolProp>
          <stringProp name="dataFile"></stringProp>
        </eu.luminis.jmeter.wssampler.RequestResponseWebSocketSampler>
        <hashTree/>
        <eu.luminis.jmeter.wssampler.RequestResponseWebSocketSampler guiclass="eu.luminis.jmeter.wssampler.RequestResponseWebSocketSamplerGui" testclass="eu.luminis.jmeter.wssampler.RequestResponseWebSocketSampler" testname="3.0 Обсуждение" enabled="true">
          <boolProp name="createNewConnection">false</boolProp>
          <boolProp name="TLS">false</boolProp>
          <stringProp name="server"></stringProp>
          <stringProp name="port">80</stringProp>
          <stringProp name="path"></stringProp>
          <stringProp name="connectTimeout">20000</stringProp>
          <boolProp name="binaryPayload">false</boolProp>
          <stringProp name="requestData">{&quot;event&quot;:&quot;speak&quot;,&quot;mode&quot;:2,&quot;group_id&quot;:100,&quot;from_user_id&quot;:&quot;10086&quot;,&quot;from_username&quot;:&quot;Аксу&quot;,&quot;to_user_id&quot;:&quot;10000&quot;,&quot;content&quot;:&quot;WebSocketУчебное пособие:Реализация и применение сохранения сообщений&quot;}</stringProp>
          <stringProp name="readTimeout">6000</stringProp>
          <boolProp name="loadDataFromFile">false</boolProp>
          <stringProp name="dataFile"></stringProp>
        </eu.luminis.jmeter.wssampler.RequestResponseWebSocketSampler>
        <hashTree/>
        <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="Просмотреть дерево результатов" enabled="true">
          <boolProp name="ResultCollector.error_logging">false</boolProp>
          <objProp>
            <name>saveConfig</name>
            <value class="SampleSaveConfiguration">
              <time>true</time>
              <latency>true</latency>
              <timestamp>true</timestamp>
              <success>true</success>
              <label>true</label>
              <code>true</code>
              <message>true</message>
              <threadName>true</threadName>
              <dataType>true</dataType>
              <encoding>false</encoding>
              <assertions>true</assertions>
              <subresults>true</subresults>
              <responseData>false</responseData>
              <samplerData>false</samplerData>
              <xml>false</xml>
              <fieldNames>true</fieldNames>
              <responseHeaders>false</responseHeaders>
              <requestHeaders>false</requestHeaders>
              <responseDataOnError>false</responseDataOnError>
              <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
              <assertionsResultsToSave>0</assertionsResultsToSave>
              <bytes>true</bytes>
              <sentBytes>true</sentBytes>
              <url>true</url>
              <threadCounts>true</threadCounts>
              <idleTime>true</idleTime>
              <connectTime>true</connectTime>
            </value>
          </objProp>
          <stringProp name="filename"></stringProp>
        </ResultCollector>
        <hashTree/>
        <ResultCollector guiclass="SummaryReport" testclass="ResultCollector" testname="Сводный отчет" enabled="true">
          <boolProp name="ResultCollector.error_logging">false</boolProp>
          <objProp>
            <name>saveConfig</name>
            <value class="SampleSaveConfiguration">
              <time>true</time>
              <latency>true</latency>
              <timestamp>true</timestamp>
              <success>true</success>
              <label>true</label>
              <code>true</code>
              <message>true</message>
              <threadName>true</threadName>
              <dataType>true</dataType>
              <encoding>false</encoding>
              <assertions>true</assertions>
              <subresults>true</subresults>
              <responseData>false</responseData>
              <samplerData>false</samplerData>
              <xml>false</xml>
              <fieldNames>true</fieldNames>
              <responseHeaders>false</responseHeaders>
              <requestHeaders>false</requestHeaders>
              <responseDataOnError>false</responseDataOnError>
              <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
              <assertionsResultsToSave>0</assertionsResultsToSave>
              <bytes>true</bytes>
              <sentBytes>true</sentBytes>
              <url>true</url>
              <threadCounts>true</threadCounts>
              <idleTime>true</idleTime>
              <connectTime>true</connectTime>
            </value>
          </objProp>
          <stringProp name="filename"></stringProp>
        </ResultCollector>
        <hashTree/>
        <ResultCollector guiclass="StatVisualizer" testclass="ResultCollector" testname="Агрегационный отчет" enabled="true">
          <boolProp name="ResultCollector.error_logging">false</boolProp>
          <objProp>
            <name>saveConfig</name>
            <value class="SampleSaveConfiguration">
              <time>true</time>
              <latency>true</latency>
              <timestamp>true</timestamp>
              <success>true</success>
              <label>true</label>
              <code>true</code>
              <message>true</message>
              <threadName>true</threadName>
              <dataType>true</dataType>
              <encoding>false</encoding>
              <assertions>true</assertions>
              <subresults>true</subresults>
              <responseData>false</responseData>
              <samplerData>false</samplerData>
              <xml>false</xml>
              <fieldNames>true</fieldNames>
              <responseHeaders>false</responseHeaders>
              <requestHeaders>false</requestHeaders>
              <responseDataOnError>false</responseDataOnError>
              <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
              <assertionsResultsToSave>0</assertionsResultsToSave>
              <bytes>true</bytes>
              <sentBytes>true</sentBytes>
              <url>true</url>
              <threadCounts>true</threadCounts>
              <idleTime>true</idleTime>
              <connectTime>true</connectTime>
            </value>
          </objProp>
          <stringProp name="filename"></stringProp>
        </ResultCollector>
        <hashTree/>
        <LoopController guiclass="LoopControlPanel" testclass="LoopController" testname="Контроллер цикла" enabled="true">
          <boolProp name="LoopController.continue_forever">true</boolProp>
          <stringProp name="LoopController.loops">500</stringProp>
        </LoopController>
        <hashTree>
          <ConstantTimer guiclass="ConstantTimerGui" testclass="ConstantTimer" testname="Фиксированный таймер" enabled="true">
            <stringProp name="ConstantTimer.delay">10000</stringProp>
          </ConstantTimer>
          <hashTree/>
          <eu.luminis.jmeter.wssampler.RequestResponseWebSocketSampler guiclass="eu.luminis.jmeter.wssampler.RequestResponseWebSocketSamplerGui" testclass="eu.luminis.jmeter.wssampler.RequestResponseWebSocketSampler" testname="ws-сердцебиение Обнаружение" enabled="true">
            <boolProp name="createNewConnection">false</boolProp>
            <boolProp name="TLS">false</boolProp>
            <stringProp name="server"></stringProp>
            <stringProp name="port">80</stringProp>
            <stringProp name="path"></stringProp>
            <stringProp name="connectTimeout">20000</stringProp>
            <boolProp name="binaryPayload">false</boolProp>
            <stringProp name="requestData">{&quot;event&quot;:&quot;ping&quot;,&quot;content&quot;:&quot;ping heartbeat&quot;}</stringProp>
            <stringProp name="readTimeout">6000</stringProp>
            <boolProp name="loadDataFromFile">false</boolProp>
            <stringProp name="dataFile"></stringProp>
          </eu.luminis.jmeter.wssampler.RequestResponseWebSocketSampler>
          <hashTree/>
        </hashTree>
      </hashTree>
    </hashTree>
  </hashTree>
</jmeterTestPlan>
boy illustration
Углубленный анализ переполнения памяти CUDA: OutOfMemoryError: CUDA не хватает памяти. Попыталась выделить 3,21 Ги Б (GPU 0; всего 8,00 Ги Б).
boy illustration
[Решено] ошибка установки conda. Среда решения: не удалось выполнить первоначальное зависание. Повторная попытка с помощью файла (графическое руководство).
boy illustration
Прочитайте нейросетевую модель Трансформера в одной статье
boy illustration
.ART Теплые зимние предложения уже открыты
boy illustration
Сравнительная таблица описания кодов ошибок Amap
boy illustration
Уведомление о последних правилах Points Mall в декабре 2022 года.
boy illustration
Даже новички могут быстро приступить к работе с легким сервером приложений.
boy illustration
Взгляд на RSAC 2024|Защита конфиденциальности в эпоху больших моделей
boy illustration
Вы используете ИИ каждый день и до сих пор не знаете, как ИИ дает обратную связь? Одна статья для понимания реализации в коде Python общих функций потерь генеративных моделей + анализ принципов расчета.
boy illustration
Используйте (внутренний) почтовый ящик для образовательных учреждений, чтобы использовать Microsoft Family Bucket (1T дискового пространства на одном диске и версию Office 365 для образовательных учреждений)
boy illustration
Руководство по началу работы с оперативным проектом (7) Практическое сочетание оперативного письма — оперативного письма на основе интеллектуальной системы вопросов и ответов службы поддержки клиентов
boy illustration
[docker] Версия сервера «Чтение 3» — создайте свою собственную программу чтения веб-текста
boy illustration
Обзор Cloud-init и этапы создания в рамках PVE
boy illustration
Корпоративные пользователи используют пакет регистрационных ресурсов для регистрации ICP для веб-сайта и активации оплаты WeChat H5 (с кодом платежного узла версии API V3)
boy illustration
Подробное объяснение таких показателей производительности с высоким уровнем параллелизма, как QPS, TPS, RT и пропускная способность.
boy illustration
Удачи в конкурсе Python Essay Challenge, станьте первым, кто испытает новую функцию сообщества [Запускать блоки кода онлайн] и выиграйте множество изысканных подарков!
boy illustration
[Техническая посадка травы] Кровавая рвота и отделка позволяют вам необычным образом ощипывать гусиные перья! Не распространяйте информацию! ! !
boy illustration
[Официальное ограниченное по времени мероприятие] Сейчас ноябрь, напишите и получите приз
boy illustration
Прочтите это в одной статье: Учебник для няни по созданию сервера Huanshou Parlu на базе CVM-сервера.
boy illustration
Cloud Native | Что такое CRD (настраиваемые определения ресурсов) в K8s?
boy illustration
Как использовать Cloudflare CDN для настройки узла (CF самостоятельно выбирает IP) Гонконг, Китай/Азия узел/сводка и рекомендации внутреннего высокоскоростного IP-сегмента
boy illustration
Дополнительные правила вознаграждения амбассадоров акции в марте 2023 г.
boy illustration
Можно ли открыть частный сервер Phantom Beast Palu одним щелчком мыши? Супер простой урок для начинающих! (Прилагается метод обновления сервера)
boy illustration
[Играйте с Phantom Beast Palu] Обновите игровой сервер Phantom Beast Pallu одним щелчком мыши
boy illustration
Maotouhu делится: последний доступный внутри страны адрес склада исходного образа Docker 2024 года (обновлено 1 декабря)
boy illustration
Кодирование Base64 в MultipartFile
boy illustration
5 точек расширения SpringBoot, супер практично!
boy illustration
Глубокое понимание сопоставления индексов Elasticsearch.
boy illustration
15 рекомендуемых платформ разработки с нулевым кодом корпоративного уровня. Всегда найдется та, которая вам понравится.
boy illustration
Аннотация EasyExcel позволяет экспортировать с сохранением двух десятичных знаков.