Тестирование В Яндекс. Как Сделать Отказоустойчивую Сетку Из Тысяч Браузеров

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

Селен .

Яндекс проводит миллионы автотестов в день, используя Selenium для работы с браузерами, поэтому нам нужны тысячи разных браузеров, доступных одновременно и 24/7. И вот здесь начинается веселье.



Тестирование в Яндекс.
</p><p>
 Как сделать отказоустойчивую сетку из тысяч браузеров

Selenium при большом количестве браузеров имеет множество проблем с масштабированием и отказоустойчивостью.

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

Наш проект сетка-маршрутизатор позволяет организовать отказоустойчивую Selenium-сетку из любого количества браузеров.

Код имеет открытый исходный код и доступен на Гитхаб .

Ниже под катом я расскажу, на какие недостатки Selenium мы обратили внимание, как пришли к нашему решению, и объясню, как его настроить.



Проблема

Selenium сильно изменился с момента своего появления, и нынешняя архитектура, называемая Selenium Grid, работает именно так.



Тестирование в Яндекс.
</p><p>
 Как сделать отказоустойчивую сетку из тысяч браузеров

Кластер состоит из двух приложений: центр (концентратор) и узлы (узел).

Хаб — это API, который принимает запросы пользователей и отправляет их нодам.

Узел — это исполнитель запросов, который запускает браузеры и выполняет в них тестовые шаги.

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

А что на практике?

  • Есть слабое место.

    Хаб — единственная точка доступа к браузерам.

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

    Понятно, что сервис также перестает работать, если в дата-центре, где расположен хаб, происходит сбой в сети или электропитании.

  • Selenium Grid плохо масштабируется.

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

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

  • Никаких квот. Вы не можете создавать пользователей и указывать, какие версии браузера тот или иной пользователь может использовать.



Решение

Чтобы не мучиться, если упадет один хаб, можно поднять несколько.

Но обычные библиотеки для работы с Selenium рассчитаны на работу только с одним хабом, поэтому вам придется научить их работать с распределенной системой.



Балансировка на клиенте

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



Тестирование в Яндекс.
</p><p>
 Как сделать отказоустойчивую сетку из тысяч браузеров

Вот как это работает:

  1. Информация о хостах с хабами и доступных на них версиях браузеров сохраняется в файле конфигурации.

  2. Пользователь включает библиотеку в свои тесты и запрашивает браузер.

  3. Из списка случайным образом выбирается хост и предпринимается попытка получить браузер.

  4. Если попытка успешна, то браузер передается пользователю и начинаются тесты.

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

    Такой подход позволяет равномерно распределить нагрузку.

  6. Пользователь получает сообщение об ошибке только в том случае, если браузер не доступен ни на одном из хабов.

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

WebDriver driver = new RemoteWebDriver(SELENIUM_SERVER_URL, capabilities);

Здесь УдаленныйВебДрайвер — стандартный класс для работы с Selenium в Java. Для работы в нашей инфраструктуре нам придется обернуть ее в собственный код с выбором хаба:

WebDriver driver = SeleniumHubFinder.find(capabilities);

В тестовом коде больше нет URL-адреса Selenium; он содержится в конфигурации библиотеки.

Это также означает, что тестовый код теперь привязан к SeleniumHubFinder и без этого не запустится.

Кроме того, если у вас есть тесты не только на Java, но и на других языках, вам придется писать клиентский балансировщик нагрузки для них всех, а это может быть дорого.

Гораздо проще разместить код балансировки на сервере и указать его адрес в тестовом коде.



Балансировка на сервере

При проектировании сервера мы заложили следующие естественные требования:
  1. Сервер должен реализовать Selenium API (протокол JsonWire ), чтобы тесты с ним работали как с обычным Selenium хабом.

  2. Вы можете разместить сколько угодно серверных головок в любых дата-центрах и балансировать их с помощью аппаратного или программного балансировщика (SLB).

  3. Головки серверов полностью независимы друг от друга и не хранят общее состояние.

  4. Сервер из коробки обеспечивает квоты, то есть независимую работу нескольких пользователей.



Тестирование в Яндекс.
</p><p>
 Как сделать отказоустойчивую сетку из тысяч браузеров

Архитектурно полученное решение выглядит следующим образом:
  • Балансировщик нагрузки (SLB) распределяет запросы от пользователей на одну из N головок, при этом сервер прослушивает стандартный порт (4444).

  • Каждая из голов хранит информацию обо всех доступных Selenium-хабах в виде конфигурации.

  • Когда запрос приходит в браузер, сервер использует алгоритм балансировки, описанный в предыдущем разделе, и принимает браузер.

  • Каждый работающий браузер в стандарте Selenium получает свой уникальный идентификатор, называемый Идентификатор сессии .

    Это значение отправляется клиентом в хаб для любого запроса.

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

    Результирующая сессия с расширенным идентификатором передается клиенту.

  • Для последующих запросов сервер извлекает из идентификатора сеанса адрес хоста с хабом и проксирует запросы на этот хост. Поскольку вся необходимая серверу информация находится в самом запросе, нет необходимости синхронизировать состояние головок — каждая из них может работать независимо.



Гридроутер

Мы назвали сервер сетка-маршрутизатор и решил поделиться своим кодом со всеми.

Сервер написан на Java с использованием Весенняя структура .

Исходники проекта можно посмотреть по адресу связь .

Мы также подготовили Пакеты Debian , установка сервера.

В настоящее время gridrouter установлен как рабочий сервер, используемый различными командами Яндекса.

Общее количество доступных браузеров в этой сетке — более трёх тысяч.

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



Как настроить гридроутер

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

Мы не ставили перед собой задачу сделать сверхбезопасную аутентификацию с помощью хэш-функций и соли, поэтому используем обычную базовая HTTP-аутентификация , а логины и пароли мы храним в открытом виде в текстовом файле /etc/grid-router/users.properties тип:

user:password, user user2:password2, user

В каждой строке указаны имя пользователя и пароль, разделенные двоеточием, а также роль, которая на данный момент та же — пользователь .

Что касается квот, то здесь тоже все очень просто.

Каждая квота представляет собой отдельный XML-файл.

/etc/grid-router/quota/ .

xml , Где - Имя пользователя.

Внутри файл выглядит так:

<qa:browsers xmlns:qa="urn:config.gridrouter.qatools.ru"> <browser name="firefox" defaultVersion="33.0"> <version number="33.0"> <region name="us-west"> <host name="my-firefox33-host-1.example.com" port="4444" count="5"/> </region> <region name="us-east"> <host name="my-firefox33-host-2.example.com" port="4444" count="5"/> </region> </version> <version number="38.0"> <region name="us-west"> <host name="my-firefox38-host-1.example.com" port="4444" count="4"/> <host name="my-firefox38-host-2.example.com" port="4444" count="4"/> </region> <region name="us-east"> <host name="my-firefox38-host-3.example.com" port="4444" count="4"/> </region> </version> </browser> <browser name="chrome" defaultVersion="42.0"> <version number="42.0"> <region name="us-west"> <host name="my-chrome42-host-1.example.com" port="4444" count="1"/> </region> <region name="us-east"> <host name="my-chrome42-host-2.example.com" port="4444" count="4"/> <host name="my-chrome42-host-3.example.com" port="4444" count="3"/> </region> </version> </browser> </qa:browsers>

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

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

Название региона может быть произвольным.

Информация о регионах нужна в тех случаях, когда один из дата-центров становится недоступен.

В этом случаеgrirouter после одной неудачной попытки получить браузер в определенном регионе пытается получить браузер из другого региона.

Этот алгоритм значительно увеличивает вероятность быстрого получения браузера.



Как запускать тесты

Хотя мы в основном пишем на Java, мы протестировали наш сервер Selenium с помощью тестов на других языках программирования.

Обычно в тестах URL хаба указывается примерно так:

http://example.com:4444/wd/hub

Поскольку мы используем базовую HTTP-аутентификацию, при работе сgrirouter вам следует использовать следующие ссылки:

http://username:[email protected]:4444/wd/hub

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



Рекомендации по настройке хабов и нод

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



Тестирование в Яндекс.
</p><p>
 Как сделать отказоустойчивую сетку из тысяч браузеров

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

локальный хост: 4444 .

Особенно удобно это делать, если все развернуто на виртуальных машинах.

Например, мы обнаружили, что для виртуальной машины с двумя VCPU и 4 ГБ памяти оптимальным является сочетание хаба и пяти узлов.

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

Теги: #с открытым исходным кодом #Разработка веб-сайтов #Тестирование веб-сервисов #java #автоматизация qa #Selenium #seleniumgrid #selenium-webdriver

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.