Тестирование производительности по протоколу AMQP с Gatling

Вячеслав Смирнов, Райффайзенбанк

Тестирование
производительности
по протоколу AMQP
с Gatling

Вячеслав Смирнов

Эксперт по тестированию,
Райффайзенбанк

Ускоряю сервисы
Raiffeisen
Business
Platform


Развиваю @qa_load

Raiffeisen Business Platform

глазами инженера по производительности

Доклад на основе

опыта 2018-2019 гг. тестирования

Очень много потоков
нужно, чтобы подать нагрузку
по протоколам JMS или AMQP
из Gatling
Десятки тысяч!

Содержание

Код прилагается

Очереди

Ответ придёт нескороили не придёт

Школа Highload. Урок № 4. Масштабирование во времени

(Хакер № 163, 2012 год, стр. 108-112)

Очереди

Отложенные вычисления

Очереди

Асинхронная обработка (отложенная)

Собрать данные сейчас, а обработать потом:

Очередь как паттерн

Очередь может быть в БД, но лучше в MQ

Очереди и множество запросов

Шина: ответы на запросы в другой системе

Очереди и проверка на дубликаты

На 10 запросов может быть 1 ответ

Очереди и надёжность узлов

Шина данных защищает от потерь

Очереди, RabbitMQ, AMQP

Ответы могут:

И ответы не должны теряться

Инструмент для нагрузки должен быть гибким

Чем подавать нагрузку на RabbitMQ в 2019 году?
Может быть Apache.JMeter 5.1+?
Может быть Gatling 3.0+?

Apache.JMeter для RabbitMQ в 2019

github.com/jlavallee/JMeter-Rabbit-AMQP (105 ★)
Last commit 2016-05-17 три года назад
JMeter 2.11 2014, работает в 5.1
Amqp 3.5.1 2015, обновляется до 4.11
Issues 21 2015, критично heardbeat
Pull Requests 9 2017, удобно maven
Fork 109 много, но активных 11

Apache.JMeter для RabbitMQ в 2019

github.com/polarnik/JMeter-Rabbit-AMQP-info (TOP 11 Forks)

Gatling для RabbitMQ в начале 2019

github.com/maiha/gatling-amqp (14 ★)
Last commit 2016-09-02 три года назад
Gatling 2.2.0-M3 2015, не работает в 3.0+
Amqp 4.9.0 2015, обновляется до 4.11
Issues 2 2018, критично gatling-2.2.2
Pull Requests 2 2018
Fork 25 три активных, для gatling-2

Gatling для RabbitMQ в конце 2019

github.com/TinkoffCreditSystems/gatling-amqp-plugin (14 ★)
Last commit 2019-10-06 недавно
Gatling 3.2.0 2019, работает в 3.0+
Amqp 5.7.1 2019, новый
Issues 2 2019, нет Consume
Pull Requests 1 2019, развивается
Fork 5 один активный

Подача нагрузки на RabbitMQ
Для Apache.JMeter нужно немного правок
Для Gatling 3+ нужно было больше правок

Варианты подачи нагрузки на RabbitMQ:

Отправить AMQP-запрос без Gatling

			def send(): Unit = {
			  val factory = new ConnectionFactory()  // open
			  factory.setUsername("guest")           // open
			  val conn = factory.newConnection()     // open
			  val channel = conn.createChannel()     // open
			  val bytes = message.getBytes()
			  channel.basicPublish("exchange","routing.key",null,bytes)
			  channel.close()                        // close
			  conn.close()                           // close
			}			
		

Отправить AMQP-запрос без Gatling

			.group("Transaction Name") {
			  exec {
			    session => 
			      val factory = new ConnectionFactory() // open
			      ...                                   

			      channel.basicPublish("exchange","routing.key",null,bytes)

			      channel.close()                       // close
			      conn.close()                          // close
			    session                          
			  }                      
			}			
		

Отправить AMQP-запрос без Gatling

			.group("Transaction Name") {
			  exec {
			    session => 
			      val factory = new ConnectionFactory() // open
			      ...                                   

			      channel.basicPublish("exchange","routing.key",null,bytes)

			      channel.close()                       // close
			      conn.close()                          // close
			    session.set("variable", variableValue)  // share                        
			  }                      
			}			
		

Задачи плагина для RabbitMQ:
  • DSL-синтаксис
  • пул соединений
  • создание/удаление очередей
  • отправка и получение единичных сообщений
  • корреляция и проверки
  • ...

Логируем гибко в Gatling

			// 1. 12:00:00
			asyncLog("1").start("Generate PDF Report")
			// 2. 12:00:05
			asyncLog("1").log()
			             .label("Generate PDF Report (prepare report complete)")
			// 3. 12:03:00		
			asyncLog("1").stop()		
		

Логируем удобно в Gatling

			.exec(asynclog("Generate PDF Report (prepare report complete)")
      		  .startTimestamp("2019-11-25 00:19:00",
      		                  "yyyy-MM-dd HH:mm:ss")
      		  .endTimestamp("2019-11-25 00:29:00", "yyyy-MM-dd HH:mm:ss")
      		  .status(io.gatling.commons.stats.OK)
      		  .responseCode("200")
    		)		
		

Задачи плагина для логирования:
  • статистика внутри одного сценария
  • статистика для разных сценариев

Выбор основы AMQP-плагина

для Gatling 3.0+

JDBC-plugin (3.2.1) работает, есть инструкция по разработке
JMS-плагин (latest) базовый, работа с очередями
AMQP-плагин (2.1) старый, не сработал
JMeter-плагины наглядность, работают
AMQP-плагин (3.2) новый, работает

Архитектура взаимодействия

Две очереди и CorrelationID

Архитектура взаимодействия

Две очереди и CorrelationID => Ожидания

Архитектура взаимодействия

Две очереди и CorrelationID => Ожидания и OutOfMemory

Архитектура взаимодействия

Сокращение параллельности и времени ожидания

Архитектура взаимодействия

Разделить отправку и получение

Вариант реализации
  1. Использование before для очистки очередей
  2. Разные scenario на отправку и получение
  3. Извлечение CorrelationID из тела ответа
  4. Синхронизация работы через ConcurentHashMap
  5. Плагин для логирования транзакций
  6. Отдельный scenario на отмену запросов
  7. Использование after для очистки очередей

Внутренний механизм корреляции сообщений

Есть разные варианты реализации

Внутренний механизм корреляции сообщений

callback-функция, как в JMS-плагине

Внутренний механизм корреляции сообщений

Корреляция через session, check, wait и ConcurentHashMap

Внутренний механизм корреляции сообщений

Механизм корреляции прямо в AMQP-плагине

Группировка запросов в Gatling
  1. возможности
  2. особенности
  3. ограничения
  4. решения

Пример проекта
https://github.com/polarnik/... (TODO)

Вячеслав Смирнов

github.com/polarnik

Telegram: @qa_load

Спасибо!