37
Распределённое нагрузочное тестирование на Java Алексей Рагозин Артём Панасюк jug.msk.ru 2016

Распределённое нагрузочное тестирование на Java

Embed Size (px)

Citation preview

Page 1: Распределённое нагрузочное тестирование на Java

Распределённое нагрузочное тестирование на Java

Алексей Рагозин

Артём Панасюк

jug.msk.ru 2016

Page 2: Распределённое нагрузочное тестирование на Java

В докладе

• Введение

• Концепция PTDD Performance Test Driven Development

• Распределённый нагрузочный тест – что это?

• Стек инструментов

• Пример теста

Page 3: Распределённое нагрузочное тестирование на Java

Тестирование – инструмент познания мира

Page 4: Распределённое нагрузочное тестирование на Java

Performance Test Driven Development

Функциональное тестирование

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

Cost of bug

Test volume

Release

Release

Test volumeCost of bug

Page 5: Распределённое нагрузочное тестирование на Java

Performance Test Driven Development

• Пишем неоптимизированный код • Пишем нагрузочные тесты / бенчмарк • Исправляем проблемы производительности • Организуем изолированные тесты в профили

нагрузки по мере добавления функционала • Непрерывное тестирование производительности

Page 6: Распределённое нагрузочное тестирование на Java

Как тестировать до “начала”?

Нет скрипов, инфраструктуры, приложения

Надо тестировать базовые сценарии

Тестировать на реальном масштабе

Тестировать сценарии отказов

Дизайн меняется на ходу, тесты вместе с ним

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

Page 7: Распределённое нагрузочное тестирование на Java

Как тестировать до “начала”?

На чём вы пишите юнит-тесты? • JUnit - Java

Почему бы не писать нагрузочные также? • Мы знаем Java • На Java есть библиотеки для всего • Никаких переформанс инженеров

тесты пишут разработчики

Page 8: Распределённое нагрузочное тестирование на Java

Вопрос культуры

“Классический” подход • bash + ssh + анализ логов + Excel / R • Мало пригоден для повторного использования • Короткий период полураспада тестов • Использование незнакомого инструментария

“Монокультурный” подход • Платформа приложения = платформа автоматизации − Приходится изобретать велосипеды, но + Решается проблема культурного диссонанса

Page 9: Распределённое нагрузочное тестирование на Java

Нагрузочный тест

Развёртывание В распределённой среде

Подготовка данных / разогрев

Сценарий тестирования Например, дневной профиль нагрузки с отказом узла в кластера

Сбор метрик Тестовые события Метрики ОС Данные профилирования

Подготовка отчёта

Page 10: Распределённое нагрузочное тестирование на Java

Стек инструментов

Nanocloud - https://github.com/gridkit/nanocloud/

Развертывание / управление распределённой средой

GridBeans – “массивно параллельная” Java

Оркестрация развертывая и подготовки

Выполнение сценария

Nimble

Компоненты: cбор данных, мониторинг и прочее

Отчёты

Сырой CSV на выходе, решение не найдено

Page 11: Распределённое нагрузочное тестирование на Java

Nanocloud

Page 12: Распределённое нагрузочное тестирование на Java

Nanocloud

Удалённое выполнения Java кода

Просто как …

@Test

public void hello_remote_world() {

Cloud cloud = CloudFactory.createSimpleSshCloud();

cloud.node("myserver.acme.com").exec(new Callable<Void>(){

@Override

public Void call() throws Exception {

String localhost = InetAddress.getLocalHost().toString();

System.out.println("Hi! I'm running on " + localhost);

return null;

}

});

}

Page 13: Распределённое нагрузочное тестирование на Java

All you need is …

NanoCloud requirements

SSHd

Java (1.6 and above) present

Works though NAT and firewalls

Works on Amazon EC2

Works everywhere where SSH works

Page 14: Распределённое нагрузочное тестирование на Java

Master – slave communications

Master process Slave hostSSH

(Single TCP)

Slave

Slave

RMI

(TCP)

std err

std out

std in

diag

Slave

controller

Slave

controller

multiplexed slave streams Agent

Page 15: Распределённое нагрузочное тестирование на Java

Death clock is ticking

Master JVM kills slave processes, unless

SSH session was interrupted

someone kill -9 master JVM

master JVM has crashed (e.g. under debuger)

Death clock is ticking on slave though

if master is not responding

slave process will terminate itself

Page 16: Распределённое нагрузочное тестирование на Java

Cloud scale JVM

Same API – different topoligies

in-process (debug), local, remote (distributed)

Transparent remoting

SSH to manage remote server

Automatic classpath replication (with caching)

Zero infrastructure

Any OS for master host

SSHd + JVM for slave hosts (Unix / Cygwin)

200+ slave topology in routinely used

Page 17: Распределённое нагрузочное тестирование на Java

Распределённый сценарий

Page 18: Распределённое нагрузочное тестирование на Java

Распределённый сценарий

• Простые шаги (реализованные на Java)

• Выполняемые в распределённой системе согласно сценарию

• Возможность синхронизации шагов

• Обмен данными между шагами

• Нет циклов и условного выполнения

• Fail fast – ошибка любого шага завершает сценарий

Page 19: Распределённое нагрузочное тестирование на Java

Mockito

@Test public void test() { MyList mock = Mockito.mock(MyList.class, Mockito.RETURNS_DEEP_STUBS); Mockito.when(mock.get(0).getValue()).thenReturn("v1"); Mockito.when(mock.get(1).getValue()).thenReturn("v2"); Assert.assertEquals(null, mock.get(2).getValue()); Assert.assertEquals("v2", mock.get(1).getValue()); Assert.assertEquals("v1", mock.get(0).getValue()); InOrder io = Mockito.inOrder(mock); io.verify(mock).get(2); io.verify(mock).get(1); io.verify(mock).get(0); io.verifyNoMoreInteractions(); }

Page 20: Распределённое нагрузочное тестирование на Java

Mockito way

1. Декларация намерений

Моки и вызовы методов

“Виртуальное” время

“Абстрактная” распределённость

2. Физическое выполнение

Привязка к топологии

Зависимости между шагами

Параллельное / распределённое выполнение

Page 21: Распределённое нагрузочное тестирование на Java

Простой пример #1

public void example() { MonadBuilder bld = MonadFactory.build(); MyReader reader = bld.locator(Cloud.class).at("reader") .deploy(MyReader.class, ...); reader.configure("read config"); bld.join("start"); reader.execute(); bld.join("done"); bld.rewind(); MyWriter writer = bld.locator(Cloud.class) .at("writer").deploy(MyWriter.class, ...); writer.configure("write config"); bld.join("start"); writer.execute(); bld.join("done"); }

Page 22: Распределённое нагрузочное тестирование на Java

Простой пример #1

deploy

reader

reader

.configure()

start

reader

.execute()

done

deploy

writer

writer

.configure()

writer

.execute()

Page 23: Распределённое нагрузочное тестирование на Java

Простой пример #1

Драйвер Интерфейс декларирующий шаги Шаги – методы Шаг может вернуть “интерфейс” Шаги могут принимать параметры Сериализуемые объекты Результаты выполнения шагов

Реализация драйвера размещается в распределённой среде используя локатор

Page 24: Распределённое нагрузочное тестирование на Java

Простой пример #1

public void example() { MonadBuilder bld = MonadFactory.build(); MyReader reader = bld.locator(Cloud.class).at("reader") .deploy(MyReader.class, ...); reader.configure("read config"); bld.join("start"); reader.execute(); bld.join("done"); bld.rewind(); MyWriter writer = bld.locator(Cloud.class).at("writer") .deploy(MyWriter.class, ...); writer.configure("write config"); bld.join("start"); writer.execute(); bld.join("done"); }

Локатор Драйвер прокси

Checkpoint Checkpoint

Перемотка времени

Page 25: Распределённое нагрузочное тестирование на Java

Простой пример #1

deploy

reader

reader

.configure()

start

reader

.execute()

done

deploy

writer

writer

.configure()

writer

.execute()

deploy

reader

reader

.configure()

reader

.execute()

deploy

writer

writer

.configure()

writer

.execute()

Page 26: Распределённое нагрузочное тестирование на Java

Простой пример #2

MyReader reader = bld.locator(Cloud.class).at("reader") .deploy(MyReader.class, ...); reader.configure("read config"); bld.sync(); Runnable readTask = reader.createTask(); bld.join("start"); ExecutionDriver exec = bld.bean(ExecutionDriver.class); Activity readJob = exec.execute(readTask); bld.join("stop"); readJob.stop(); bld.join(readJob); bld.join("done"); bld.rewind("start"); bld.wallclock().delay(30, TimeUnit.SECONDS); bld.join("stop");

Page 27: Распределённое нагрузочное тестирование на Java

Простой пример #2

deploy

reader

reader

.configure()

start

wallclock

.delay()

done

reader

.createTask()

exec

.execute()

stop

readTask

readJob

.stop()

readJob

readJob

.join()

Page 28: Распределённое нагрузочное тестирование на Java

Простой пример #2

MyReader reader = bld.locator(Cloud.class).at("reader") .deploy(MyReader.class, ...); reader.configure("read config"); bld.sync(); Runnable readTask = reader.createTask(); bld.join("start"); ExecutionDriver exec = bld.bean(ExecutionDriver.class); Activity readJob = exec.execute(readTask); bld.join("stop"); readJob.stop(); bld.join(readJob); bld.join("done"); bld.rewind("start"); bld.wallclock().delay(30, TimeUnit.SECONDS); bld.join("stop");

Вспомогательный сервис

Интерфейс фоновых задач

Получение сервиса

Page 29: Распределённое нагрузочное тестирование на Java

Простой пример #2

Ошибка выполнение шага отлавливается и завершает сценарий.

Когда создаётся фоновая задача, используется Activity.join() шага, который не завершится пока задача не будет остановлена.

Wallclock – драйвер предоставляемый из коробки.

ExecutionDriver – пример вспомогательного драйвера.

Page 30: Распределённое нагрузочное тестирование на Java

Распределённый сценарий

Всех аспекты теста – Развёртывание / Сбор данных / Мониторинг / и т.д.

шаги / драйверы единого сценария

Page 31: Распределённое нагрузочное тестирование на Java

Распределённый сценарий

Fallacies of distributed computing https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing

• The network is reliable – fail test fast.

• Latency is zero – small number of round trip.

• Bandwidth is infinite – low bandwidth control flow.

• The network is secure – irrelevant for testing.

• Topology doesn't change – fail test fast and rerun.

• There is one administrator – zero deployment.

• Transport cost is zero – there is no free lunch

• The network is homogeneous – location conscious scenario.

Page 32: Распределённое нагрузочное тестирование на Java

Вспомогательные компоненты

Page 33: Распределённое нагрузочное тестирование на Java

Метеринг

Сбор метрик в распределённой среде

Данные тестовых событий Данные мониторинга

Метрики аккумулируются на локальном диске и передаются на управляющий узел по завершении сценария

Все результаты экспортируются в CSV файл большой CSV файл

Page 34: Распределённое нагрузочное тестирование на Java

Мониторинг

Метрики OS - https://github.com/hyperic/sigar Network interface stats Process stats (поиск нужных процессов)

JVM GC Threads Custom MBeans

Build your own

Page 35: Распределённое нагрузочное тестирование на Java

Профилирование

BTrace 2 - https://github.com/jbachorik/btrace2

Инструментирующий профайлер

Точки перехвата на Java

Развёртывание как часть сценария

Интеграция с метерингом

Page 36: Распределённое нагрузочное тестирование на Java

Ссылки

NanoCloud • https://github.com/gridkit/nanocloud/

• https://code.google.com/p/gridkit/wiki/NanoCloudTutorial

• Maven Central: org.gridkit.lab:nanocloud:0.8.10

• http://blog.ragozin.info/2013/01/remote-code-execution-in-java-made.html

GridBeans • https://github.com/aragozin/gridbeans

Nimble • https://github.com/gridkit/nimble

Пример бенчмарка • https://github.com/gridkit/zk-benchmark-example

Page 37: Распределённое нагрузочное тестирование на Java

Thank you

Alexey Ragozin [email protected]

http://blog.ragozin.info - my articles http://www.meetup.com/bigmoscow - community events in Moscow