Ничто не мешает вам сделать это с помощью конвейера Jenkins DSL .
У нас один и тот же конвейер работает параллельно, чтобы смоделировать комбинированные нагрузки для приложения, которое предоставляет веб-службы, предоставляет базу данных нескольким внешним приложениям, получает данные через несколько рабочих очередей и имеет интерфейс GUI. Бизнес предъявляет нам нефункциональные требования (NFR), которым должно удовлетворять наше приложение, что гарантирует его отзывчивость даже в напряженное время.
Различные экземпляры конвейера запускаются с разными параметрами. Первый экземпляр может быть WS_Load
, второй GUI_Load
и третий Daily_Update_Load
, моделирующий большую очередь данных, которая требует обработки в течение определенного периода времени. Можно добавить больше, в зависимости от того, какую комбинацию нагрузок мы хотим протестировать.
В других ответах говорилось о флажках для параллельных сборок, но я хотел упомянуть еще одну проблему: конфликт ресурсов.
Если ваш конвейер использует временные файлы или хранит файлы между стадиями конвейера, экземпляры могут в конечном итоге вытащить коврик из-под ног друг друга. Например, вы можете в конечном итоге удалить файл в одном параллельном экземпляре, пытаясь прочитать тот же файл в другом. Мы используем следующий код, чтобы гарантировать, что таймеры и временные имена файлов уникальны для каждого параллельного экземпляра:
def concurrentStash(stashName, String includes) {
/* make a stash unique to this pipeline and build
that can be unstashed using concurrentUnstash() */
echo "Safe stashing $includes in ${concurrentSafeName(stashName)}..."
stash name: concurrentSafeName(stashName), includes: includes
}
def concurrentSafeName(name) {
/* make a name or name component unique to this pipeline and build
* guards against contention caused by two or more builds from the same
* Jenkinsfile trying to:
* - read/write/delete the same file
* - stash/unstash under the same name
*/
"${name}-${BUILD_NUMBER}-${JOB_NAME}"
}
def concurrentUnstash(stashName) {
echo "Safe unstashing ${concurrentSafeName(stashName)}..."
unstash name: concurrentSafeName(stashName)
}
Затем мы можем использовать concurrentStash stashName
и concurrentUnstash stashName
, и у параллельных экземпляров не будет конфликта.
Если, скажем, оба конвейера должны хранить статистику, мы можем сделать что-то подобное для имен файлов:
def statsDir = concurrentSafeName('stats')
, а затем каждый экземпляр будет использовать уникальное имя файла для хранения своего вывода.