Docker 專案
在本節中,我們釋出了一個包含專案的 springcloud/spring-cloud-contract Docker 映象,該專案生成測試並在 EXPLICIT 模式下針對執行中的應用程式執行這些測試。
EXPLICIT 模式意味著從契約生成的測試傳送的是真實請求而非模擬請求。 |
我們還發布了一個 spring-cloud/spring-cloud-contract-stub-runner Docker 映象,它啟動 Stub Runner 的獨立版本。
Maven、JAR 和二進位制儲存的簡要介紹
由於非 JVM 專案可以使用 Docker 映象,因此最好解釋 Spring Cloud Contract 打包預設設定背後的基本術語。
以下定義的部分內容取自 Maven 詞彙表
-
專案: Maven 以專案為單位進行思考。專案是您構建的所有內容。這些專案遵循定義良好的“專案物件模型”。專案可以依賴其他專案——在這種情況下,後者稱為“依賴項”。一個專案可以由多個子專案組成。然而,這些子專案仍然被同等對待為專案。 -
工件: 工件是專案生成或使用的東西。Maven 為專案生成的工件示例包括 JAR 檔案以及原始碼和二進位制發行版。每個工件都由一個組 ID 和一個在該組中唯一的工件 ID 唯一標識。 -
JAR: JAR 代表 Java ARchive。其格式基於 ZIP 檔案格式。Spring Cloud Contract 將契約和生成的存根打包在 JAR 檔案中。 -
GroupId: Group ID 是專案的全域性唯一識別符號。雖然這通常只是專案名稱(例如,commons-collections),但使用完全限定的包名有助於將其與其他同名專案區分開來(例如,org.apache.maven)。通常,當釋出到工件管理器時,GroupId會用斜槓分隔並構成 URL 的一部分。例如,對於 group IDcom.example和 artifact IDapplication,結果將是/com/example/application/。 -
Classifier: Maven 依賴表示法如下:groupId:artifactId:version:classifier。分類器是傳遞給依賴項的附加字尾,例如,stubs或sources。同一個依賴項(例如,com.example:application)可以生成多個僅在分類器上不同的工件。 -
工件管理器: 當您生成二進位制檔案、原始碼或包時,您希望它們可供其他人下載、引用或重用。在 JVM 世界中,這些工件通常是 JAR。對於 Ruby,這些工件是 gem。對於 Docker,這些工件是 Docker 映象。您可以將這些工件儲存在管理器中。此類管理器的示例包括 Artifactory 和 Nexus。
在生產者端生成測試
映象在 /contracts 資料夾下搜尋契約。執行測試的輸出可在 /spring-cloud-contract/build 資料夾中找到(用於除錯目的)。
您可以掛載您的契約並傳遞環境變數。然後映象將
-
生成契約測試
-
針對提供的 URL 執行測試
-
生成 WireMock 存根
-
將存根釋出到工件管理器(可選——預設啟用)
環境變數
Docker 映象需要一些環境變數來指向您執行中的應用程式、工件管理器例項等。以下列表描述了環境變數
名稱 |
描述 |
預設值 |
ADDITIONAL_FLAGS |
(僅限 Docker 映象)要傳遞給 Gradle 構建的附加標誌 |
|
DEBUG |
(僅限 Docker 映象)適用於 Docker 映象 - 為 Gradle 構建開啟除錯模式 |
假 |
EXTERNAL_CONTRACTS_ARTIFACT_ID |
包含契約的專案的工件 ID |
|
EXTERNAL_CONTRACTS_CLASSIFIER |
包含契約的專案的分類器 |
|
EXTERNAL_CONTRACTS_GROUP_ID |
包含契約的專案的組 ID |
com.example |
EXTERNAL_CONTRACTS_PATH |
給定專案內部契約的路徑,位於包含契約的專案中。預設為斜槓分隔的 |
|
EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_PASSWORD |
(可選)如果 |
|
EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URL |
您的工件管理器的 URL。它預設為 |
|
EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_USERNAME |
(可選)如果 |
|
EXTERNAL_CONTRACTS_VERSION |
包含契約的專案的版本。預設為選擇最新版本 |
+ |
EXTERNAL_CONTRACTS_WORK_OFFLINE |
如果設定為 |
假 |
FAIL_ON_NO_CONTRACTS |
如果不存在契約,構建是否應該失敗? |
假 |
MESSAGING_TYPE |
訊息型別。可以是 [rabbit] 或 [kafka]。 |
|
PRODUCER_STUBS_CLASSIFIER |
用於生成生產者存根的存檔分類器 |
stubs |
PROJECT_GROUP |
您的專案的組 ID |
com.example |
PROJECT_NAME |
您的專案的工件 ID |
example |
PROJECT_VERSION |
您的專案的版本 |
0.0.1-SNAPSHOT |
PUBLISH_ARTIFACTS |
如果設定為 |
true |
PUBLISH_ARTIFACTS_OFFLINE |
如果設定為 |
假 |
PUBLISH_STUBS_TO_SCM |
如果設定為 |
假 |
REPO_ALLOW_INSECURE_PROTOCOL |
(可選)如果為 <true>,則允許透過不安全的 HTTP 將工件釋出到工件管理器 |
假 |
REPO_WITH_BINARIES_PASSWORD |
(可選)當工件管理器受保護時的密碼 |
password |
REPO_WITH_BINARIES_URL |
您的工件管理器的 URL(預設為本地執行時 Artifactory 的預設 URL) |
|
REPO_WITH_BINARIES_USERNAME |
(可選)當工件管理器受保護時的使用者名稱 |
admin |
STANDALONE_PROTOCOL |
對於獨立版本,應新增哪個附加協議 |
以下環境變數在執行測試時使用
名稱 |
描述 |
預設值 |
APPLICATION_BASE_URL |
應用程式執行的 URL。 |
|
APPLICATION_PASSWORD |
訪問應用程式的可選密碼。 |
|
APPLICATION_USERNAME |
訪問應用程式的可選使用者名稱。 |
|
MESSAGING_TRIGGER_CONNECT_TIMEOUT |
連線到應用程式以觸發訊息的超時。 |
5000 |
MESSAGING_TRIGGER_READ_TIMEOUT |
從應用程式讀取響應以觸發訊息的超時。 |
5000 |
MESSAGING_TYPE |
訊息型別。可以是 [rabbit] 或 [kafka]。 |
|
MESSAGING_TYPE |
在處理基於訊息的契約時定義訊息型別。 |
|
SPRING_KAFKA_BOOTSTRAP_SERVERS |
對於 Kafka - 代理地址。 |
|
SPRING_RABBITMQ_ADDRESSES |
對於 RabbitMQ - 代理地址。 |
自定義 Gradle 構建
您可以透過在執行容器時將自定義構建檔案掛載為卷,來提供在容器中執行的自定義 gradle.build
$ docker run -v <absolute-path-of-your-custom-file>:/spring-cloud-contract/build.gradle springcloud/spring-cloud-contract:<version>
HTTP 使用示例
在本節中,我們將探討一個簡單的 MVC 應用程式。要開始,請克隆以下 git 倉庫並進入生成的目錄,執行以下命令
$ git clone https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs
$ cd bookstore
契約位於 /contracts 資料夾中。
由於我們要執行測試,我們可以執行以下命令
$ npm test
然而,出於學習目的,我們將其分成幾部分,如下所示
# Stop docker infra (nodejs, artifactory)
$ ./stop_infra.sh
# Start docker infra (nodejs, artifactory)
$ ./setup_infra.sh
# Kill & Run app
$ pkill -f "node app"
$ nohup node app &
# Prepare environment variables
$ SC_CONTRACT_DOCKER_VERSION="..."
$ APP_IP="192.168.0.100"
$ APP_PORT="3000"
$ ARTIFACTORY_PORT="8081"
$ APPLICATION_BASE_URL="http://${APP_IP}:${APP_PORT}"
$ ARTIFACTORY_URL="http://${APP_IP}:${ARTIFACTORY_PORT}/artifactory/libs-release-local"
$ CURRENT_DIR="$( pwd )"
$ CURRENT_FOLDER_NAME=${PWD##*/}
$ PROJECT_VERSION="0.0.1.RELEASE"
# Run contract tests
$ docker run --rm -e "APPLICATION_BASE_URL=${APPLICATION_BASE_URL}" -e "PUBLISH_ARTIFACTS=true" -e "PROJECT_NAME=${CURRENT_FOLDER_NAME}" -e "REPO_WITH_BINARIES_URL=${ARTIFACTORY_URL}" -e "PROJECT_VERSION=${PROJECT_VERSION}" -v "${CURRENT_DIR}/contracts/:/contracts:ro" -v "${CURRENT_DIR}/node_modules/spring-cloud-contract/output:/spring-cloud-contract-output/" springcloud/spring-cloud-contract:"${SC_CONTRACT_DOCKER_VERSION}"
# Kill app
$ pkill -f "node app"
透過 bash 指令碼,發生以下情況
-
基礎設施(MongoDb 和 Artifactory)已設定。在實際場景中,您將使用模擬資料庫執行 NodeJS 應用程式。在此示例中,我們希望展示如何在很短的時間內從 Spring Cloud Contract 中受益。
-
由於這些限制,契約也代表了有狀態的情況。
-
第一個請求是
POST,它導致資料插入到資料庫中。 -
第二個請求是
GET,它返回一個數據列表,其中包含 1 個先前插入的元素。
-
-
NodeJS 應用程式已啟動(埠
3000)。 -
契約測試透過 Docker 生成,並針對執行中的應用程式執行測試。
-
契約取自
/contracts資料夾。 -
測試的輸出可在
node_modules/spring-cloud-contract/output下找到。
-
-
存根已上傳到 Artifactory。您可以在 localhost:8081/artifactory/libs-release-local/com/example/bookstore/0.0.1.RELEASE/ 中找到它們。存根位於 localhost:8081/artifactory/libs-release-local/com/example/bookstore/0.0.1.RELEASE/bookstore-0.0.1.RELEASE-stubs.jar。
透過訊息傳遞使用示例
如果您想透過 Docker 映象使用 Spring Cloud Contract 和訊息傳遞(例如在多語言應用程式的情況下),那麼您必須滿足以下先決條件
-
中介軟體(例如 RabbitMQ 或 Kafka)必須在生成測試之前執行
-
您的契約需要呼叫一個方法
triggerMessage(…),其String引數等於契約的label。 -
您的應用程式需要有一個 HTTP 端點,透過該端點我們可以觸發訊息
-
該端點不應在生產環境中可用(可以透過環境變數啟用)
-
訊息傳遞契約示例
契約需要呼叫 triggerMessage(…) 方法。該方法已在 docker 映象中所有測試的基類中提供,並將向生產者端的 HTTP 端點發送請求。您可以在下面找到此類契約的示例。
- Groovy
-
import org.springframework.cloud.contract.spec.Contract Contract.make { description 'Send a pong message in response to a ping message' label 'ping_pong' input { // You have to provide the `triggerMessage` method with the `label` // as a String parameter of the method triggeredBy('triggerMessage("ping_pong")') } outputMessage { sentTo('output') body([ message: 'pong' ]) } metadata( [amqp: [ outputMessage: [ connectToBroker: [ declareQueueWithName: "queue" ], messageProperties: [ receivedRoutingKey: '#' ] ] ] ]) } - YAML
-
description: 'Send a pong message in response to a ping message' label: 'ping_pong' input: # You have to provide the `triggerMessage` method with the `label` # as a String parameter of the method triggeredBy: 'triggerMessage("ping_pong")' outputMessage: sentTo: 'output' body: message: 'pong' metadata: amqp: outputMessage: connectToBroker: declareQueueWithName: "queue" messageProperties: receivedRoutingKey: '#'
觸發訊息的 HTTP 端點
為什麼需要開發這樣的端點?Spring Cloud Contract 必須以各種語言(就像在 Java 中那樣)生成程式碼,才能觸發將訊息傳送到代理的生產程式碼。如果此類程式碼未生成,那麼我們仍然需要能夠觸發訊息,實現此目的的方法是提供一個 HTTP 端點,使用者將以他們選擇的語言準備該端點。
該端點必須具有以下配置
-
URL:
/springcloudcontract/{label},其中label可以是任何文字 -
方法:
POST -
基於
label將生成一條訊息,該訊息將根據契約定義傳送到給定目的地
下面是此類端點的示例。如果您有興趣提供您語言的示例,請隨時在 Github 上的 Spring Cloud Contract 倉庫 中提交問題。
#!/usr/bin/env python
from flask import Flask
from flask import jsonify
import pika
import os
app = Flask(__name__)
# Production code that sends a message to RabbitMQ
def send_message(cmd):
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
channel.basic_publish(
exchange='output',
routing_key='#',
body=cmd,
properties=pika.BasicProperties(
delivery_mode=2, # make message persistent
))
connection.close()
return " [x] Sent via Rabbit: %s" % cmd
# This should be ran in tests (shouldn't be publicly available)
if 'CONTRACT_TEST' in os.environ:
@app.route('/springcloudcontract/<label>', methods=['POST'])
def springcloudcontract(label):
if label == "ping_pong":
return send_message('{"message":"pong"}')
else:
raise ValueError('No such label expected.')
在生產者端執行訊息測試
現在,讓我們從契約生成測試以測試生產者端。我們將執行 bash 程式碼以啟動帶有附加契約的 Docker 映象,但我們還將新增變數以使訊息傳遞程式碼工作。在這種情況下,我們假設契約儲存在 Git 倉庫中。
#!/bin/bash
set -x
CURRENT_DIR="$( pwd )"
export SC_CONTRACT_DOCKER_VERSION="${SC_CONTRACT_DOCKER_VERSION:-4.0.1-SNAPSHOT}"
export APP_IP="$( ./whats_my_ip.sh )"
export APP_PORT="${APP_PORT:-8000}"
export APPLICATION_BASE_URL="http://${APP_IP}:${APP_PORT}"
export PROJECT_GROUP="${PROJECT_GROUP:-group}"
export PROJECT_NAME="${PROJECT_NAME:-application}"
export PROJECT_VERSION="${PROJECT_VERSION:-0.0.1-SNAPSHOT}"
export PRODUCER_STUBS_CLASSIFIER="${PRODUCER_STUBS_CLASSIFIER:-stubs}"
export FAIL_ON_NO_CONTRACTS="${FAIL_ON_NO_CONTRACTS:-false}"
# In our Python app we want to enable the HTTP endpoint
export CONTRACT_TEST="true"
# In the Verifier docker container we want to add support for RabbitMQ
export MESSAGING_TYPE="rabbit"
# Let's start the infrastructure (e.g. via Docker Compose)
yes | docker-compose kill || echo "Nothing running"
docker-compose up -d
echo "SC Contract Version [${SC_CONTRACT_DOCKER_VERSION}]"
echo "Application URL [${APPLICATION_BASE_URL}]"
echo "Project Version [${PROJECT_VERSION}]"
# Let's run python app
gunicorn -w 4 --bind 0.0.0.0 main:app &
APP_PID=$!
# Generate and run tests
docker run --rm \
--name verifier \
# For the image to find the RabbitMQ running in another container
-e "SPRING_RABBITMQ_ADDRESSES=${APP_IP}:5672" \
# We need to tell the container what messaging middleware we will use
-e "MESSAGING_TYPE=${MESSAGING_TYPE}" \
-e "PUBLISH_STUBS_TO_SCM=false" \
-e "PUBLISH_ARTIFACTS=false" \
-e "APPLICATION_BASE_URL=${APPLICATION_BASE_URL}" \
-e "PROJECT_NAME=${PROJECT_NAME}" \
-e "PROJECT_GROUP=${PROJECT_GROUP}" \
-e "PROJECT_VERSION=${PROJECT_VERSION}" \
-e "EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URL=git://https://github.com/marcingrzejszczak/cdct_python_contracts.git" \
-e "EXTERNAL_CONTRACTS_ARTIFACT_ID=${PROJECT_NAME}" \
-e "EXTERNAL_CONTRACTS_GROUP_ID=${PROJECT_GROUP}" \
-e "EXTERNAL_CONTRACTS_VERSION=${PROJECT_VERSION}" \
-v "${CURRENT_DIR}/build/spring-cloud-contract/output:/spring-cloud-contract-output/" \
springcloud/spring-cloud-contract:"${SC_CONTRACT_DOCKER_VERSION}"
kill $APP_PID
yes | docker-compose kill
將發生以下情況
-
將從 Git 中獲取的契約生成測試
-
在契約中,我們提供了一個名為
declareQueueWithName的元資料條目,它將在傳送觸發訊息的請求之前在 RabbitMQ 中建立具有給定名稱的佇列 -
透過
triggerMessage("ping_pong")方法呼叫,將向 Python 應用程式的/springcloudcontract/ping_pong端點發出 POST 請求 -
Python 應用程式將透過 RabbitMQ 生成併發送一個
'{"message":"pong"}'JSON 到名為output的交換機 -
生成的測試將輪詢傳送到
output交換機的訊息 -
一旦收到訊息,將斷言其內容
測試通過後,我們知道訊息已從 Python 應用程式正確傳送到 RabbitMQ。
在消費者端執行存根
本節描述如何在消費者端使用 Docker 獲取和執行存根。
我們釋出了一個 spring-cloud/spring-cloud-contract-stub-runner Docker 映象,它啟動 Stub Runner 的獨立版本。
安全
由於 Spring Cloud Contract Stub Runner Docker 映象使用 Stub Runner 的獨立版本,因此需要考慮相同的安全問題。您可以在文件的本節中閱讀更多相關內容。
環境變數
您可以執行 docker 映象並以環境變數的形式傳遞 JUnit 和 Spring 的通用屬性。約定是所有字母都應為大寫。點 (.) 應替換為下劃線 (_) 字元。例如,spring.cloud.contract.stubrunner.repositoryRoot 屬性應表示為 SPRING_COUD_CONTRACT_STUBRUNNER_REPOSITORY_ROOT 環境變數。
除了這些變數,您還可以設定以下變數
-
MESSAGING_TYPE- 您正在使用的訊息系統型別(目前支援rabbit、kafka) -
ADDITIONAL_OPTS- 您希望傳遞給應用程式的任何附加屬性
使用示例
我們想使用在此 [docker-server-side] 步驟中建立的存根。假設我們想在埠 9876 上執行存根。您可以透過克隆倉庫並切換到以下命令中指示的目錄來檢視 NodeJS 程式碼
$ git clone https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs
$ cd bookstore
現在我們可以執行帶有存根的 Stub Runner Boot 應用程式,執行以下命令
# Provide the Spring Cloud Contract Docker version
$ SC_CONTRACT_DOCKER_VERSION="..."
# The IP at which the app is running and Docker container can reach it
$ APP_IP="192.168.0.100"
# Spring Cloud Contract Stub Runner properties
$ SPRING_CLOUD_CONTRACT_STUBRUNNER_PORT="8083"
# Stub coordinates 'groupId:artifactId:version:classifier:port'
$ SPRING_CLOUD_CONTRACT_STUBRUNNER_IDS="com.example:bookstore:0.0.1.RELEASE:stubs:9876"
$ SPRING_CLOUD_CONTRACT_STUBRUNNER_REPOSITORY_ROOT="http://${APP_IP}:8081/artifactory/libs-release-local"
# Run the docker with Stub Runner Boot
$ docker run --rm \
-e "SPRING_CLOUD_CONTRACT_STUBRUNNER_IDS=${STUBRUNNER_IDS}" \
-e "SPRING_CLOUD_CONTRACT_STUBRUNNER_REPOSITORY_ROOT=${STUBRUNNER_REPOSITORY_ROOT}" \
-e "SPRING_CLOUD_CONTRACT_STUBRUNNER_STUBS_MODE=REMOTE" \
-p "${STUBRUNNER_PORT}:${STUBRUNNER_PORT}" \
-p "9876:9876" \
springcloud/spring-cloud-contract-stub-runner:"${SC_CONTRACT_DOCKER_VERSION}"
當上述命令執行時,
-
一個獨立的 Stub Runner 應用程式啟動了。
-
它下載座標為
com.example:bookstore:0.0.1.RELEASE:stubs的存根到埠9876。 -
它從執行在
192.168.0.100:8081/artifactory/libs-release-local的 Artifactory 下載。 -
一段時間後,Stub Runner 在埠
8083上執行。 -
存根在埠
9876上執行。
在伺服器端,我們構建了一個有狀態的存根。我們可以使用 curl 來斷言存根已正確設定。為此,請執行以下命令
# let's run the first request (no response is returned)
$ curl -H "Content-Type:application/json" -X POST --data '{ "title" : "Title", "genre" : "Genre", "description" : "Description", "author" : "Author", "publisher" : "Publisher", "pages" : 100, "image_url" : "https://d213dhlpdb53mu.cloudfront.net/assets/pivotal-square-logo-41418bd391196c3022f3cd9f3959b3f6d7764c47873d858583384e759c7db435.svg", "buy_url" : "https://pivotal.io" }' https://:9876/api/books
# Now time for the second request
$ curl -X GET https://:9876/api/books
# You will receive contents of the JSON
如果您想使用在本地主機上構建的存根,您應該設定 -e STUBRUNNER_STUBS_MODE=LOCAL 環境變數並掛載本地 m2 的卷 (-v "${HOME}/.m2/:/home/scc/.m2:rw")。 |
訊息傳遞使用示例
為了使訊息傳遞工作,只需傳遞 MESSAGING_TYPE 環境變數,其值為 kafka 或 rabbit。這將導致使用連線到代理所需的依賴項設定 Stub Runner Boot Docker 映象。
為了設定連線屬性,您可以檢視 Spring Cloud Stream 屬性頁面以設定正確的環境變數。
-
-
您可以搜尋
spring.rabbitmq.xxx或spring.kafka.xxx屬性
-
您會設定的最常見的屬性是執行中介軟體的位置。如果設定該屬性的名稱是 spring.rabbitmq.addresses 或 spring.kafka.bootstrap-servers,那麼您應該分別將環境變數命名為 SPRING_RABBITMQ_ADDRESSES 和 SPRING_KAFKA_BOOTSTRAP_SERVERS。
針對現有中介軟體執行契約測試
有正當理由針對現有中介軟體執行您的契約測試。一些測試框架可能會給您假陽性結果——您的構建中的測試通過了,而生產環境中的通訊失敗了。
在 Spring Cloud Contract docker 映象中,我們提供了連線到現有中介軟體的選項。如前幾小節所述,我們開箱即用地支援 Kafka 和 RabbitMQ。然而,透過 Apache Camel 元件,我們也可以支援其他中介軟體。讓我們看一下以下使用示例。
Spring Cloud Contract Docker 和執行中的中介軟體
為了連線到任意中介軟體,我們將利用契約部分中的 standalone 元資料條目。
description: 'Send a pong message in response to a ping message'
label: 'standalone_ping_pong' (1)
input:
triggeredBy: 'triggerMessage("ping_pong")' (2)
outputMessage:
sentTo: 'rabbitmq:output' (3)
body: (4)
message: 'pong'
metadata:
standalone: (5)
setup: (6)
options: rabbitmq:output?queue=output&routingKey=(7)
outputMessage: (8)
additionalOptions: routingKey=#&queue=output (9)
| 1 | 透過 Stub Runner 觸發訊息的標籤 |
| 2 | 與之前的訊息傳遞示例一樣,我們需要觸發執行中應用程式的 HTTP 端點,使其根據提供的協議傳送訊息 |
| 3 | protocol:destination,由 Apache Camel 請求 |
| 4 | 輸出訊息體 |
| 5 | 獨立元資料條目 |
| 6 | 設定部分將包含在實際呼叫執行中應用程式的 HTTP 端點之前如何準備執行契約測試的資訊 |
| 7 | 將在設定階段呼叫的 Apache Camel URI。在這種情況下,我們將嘗試輪詢 output 交換機中的訊息,並且由於存在 queue=output 和 routingKey=,因此將設定一個名為 output 的佇列並將其繫結到具有路由鍵 的 output 交換機 |
| 8 | 附加選項(更技術性)將附加到第 (3) 點的 protocol:destination - 將以以下格式組合:rabbitmq:output?routingKey=#&queue=output。 |
為了使契約測試透過,我們像在多語言環境中的訊息傳遞情況下一樣,需要一個執行中的應用程式和一個執行中的中介軟體。這次我們將為 Spring Cloud Contract Docker 映象設定不同的環境變數。
#!/bin/bash
set -x
# Setup
# Run the middleware
docker-compose up -d rabbitmq (1)
# Run the python application
gunicorn -w 4 --bind 0.0.0.0 main:app & (2)
APP_PID=$!
docker run --rm \
--name verifier \
-e "STANDALONE_PROTOCOL=rabbitmq" \ (3)
-e "CAMEL_COMPONENT_RABBITMQ_ADDRESSES=172.18.0.1:5672" \ (4)
-e "PUBLISH_STUBS_TO_SCM=false" \
-e "PUBLISH_ARTIFACTS=false" \
-e "APPLICATION_BASE_URL=172.18.0.1" \
-e "PROJECT_NAME=application" \
-e "PROJECT_GROUP=group" \
-e "EXTERNAL_CONTRACTS_ARTIFACT_ID=application" \
-e "EXTERNAL_CONTRACTS_GROUP_ID=group" \
-e "EXTERNAL_CONTRACTS_VERSION=0.0.1-SNAPSHOT" \
-v "${CURRENT_DIR}/build/spring-cloud-contract/output:/spring-cloud-contract-output/" \
springcloud/spring-cloud-contract:"${SC_CONTRACT_DOCKER_VERSION}"
# Teardown
kill $APP_PID
yes | docker-compose kill
| 1 | 我們首先需要讓中介軟體執行 |
| 2 | 應用程式需要啟動並執行 |
| 3 | 透過 STANDALONE_PROTOCOL 環境變數,我們將獲取一個 Apache Camel 元件。我們將獲取的工件是 org.apache.camel.springboot:camel-${STANDALONE_PROTOCOL}-starter。換句話說,STANDALONE_PROTOCOL 匹配 Camel 的元件。 |
| 4 | 我們透過 Camel 的 Spring Boot Starter 機制設定地址(我們可以設定憑據)。Apache Camel 的 RabbitMQ Spring Boot 自動配置示例 |
Stub Runner Docker 和執行中的中介軟體
為了針對執行中的中介軟體觸發存根訊息,我們可以以下列方式執行 Stub Runner Docker 映象。
使用示例
$ docker run \
-e "CAMEL_COMPONENT_RABBITMQ_ADDRESSES=172.18.0.1:5672" \ (1)
-e "SPRING_CLOUD_CONTRACT_STUBRUNNER_IDS=group:application:0.0.1-SNAPSHOT" \ (2)
-e "SPRING_CLOUD_CONTRACT_STUBRUNNER_REPOSITORY_ROOT=git://https://github.com/marcingrzejszczak/cdct_python_contracts.git" \ (3)
-e ADDITIONAL_OPTS="--thin.properties.dependencies.rabbitmq=org.apache.camel.springboot:camel-rabbitmq-starter:3.4.0" \ (4)
-e "SPRING_CLOUD_CONTRACT_STUBRUNNER_STUBS_MODE=REMOTE" \ (5)
-v "${HOME}/.m2/:/home/scc/.m2:rw" \ (6)
-p 8750:8750 \ (7)
springcloud/spring-cloud-contract-stub-runner:3.0.4-SNAPSHOT (8)
| 1 | 我們透過 Apache Camel 的 Spring Boot 自動配置注入 RabbitMQ 的地址 |
| 2 | 我們告訴 Stub Runner 下載哪些存根 |
| 3 | 我們為存根提供了外部位置(Git 倉庫) |
| 4 | 透過 ADDITIONAL_OPTS=--thin.properties.dependencies.XXX=GROUP:ARTIFACT:VERSION 屬性,我們告訴 Stub Runner 在執行時獲取哪些額外的依賴項。在這種情況下,我們想獲取 camel-rabbitmq-starter,所以 XXX 是一個隨機字串,我們想獲取版本 3.4.0 的 org.apache.camel.springboot:camel-rabbitmq-starter 工件。 |
| 5 | 由於我們使用 Git,需要設定遠端選項以獲取存根 |
| 6 | 為了加快 Stub Runner 的啟動速度,我們將本地 Maven 倉庫 .m2 作為卷掛載。如果您的倉庫未填充,您可以考慮透過 :rw 設定寫入許可權,而不是隻讀 :ro。 |
| 7 | 我們公開 Stub Runner 執行的埠 8750。 |
| 8 | Stub Runner Docker 映象的座標。 |
一段時間後,您將在控制檯中注意到以下文字,這意味著 Stub Runner 已準備好接受請求。
o.a.c.impl.engine.AbstractCamelContext : Apache Camel 3.4.3 (camel-1) started in 0.007 seconds
o.s.c.c.s.server.StubRunnerBoot : Started StubRunnerBoot in 14.483 seconds (JVM running for 18.666)
o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
o.s.web.servlet.DispatcherServlet : Completed initialization in 2 ms
要獲取觸發器列表,您可以向 localhost:8750/triggers 端點發送 HTTP GET 請求。要觸發存根訊息,您可以向 localhost:8750/triggers/standalone_ping_pong 傳送 HTTP POST 請求。在控制檯中您將看到
o.s.c.c.v.m.camel.CamelStubMessages : Will send a message to URI [rabbitmq:output?routingKey=#&queue=output]
如果您檢查 RabbitMQ 管理控制檯,您會看到 output 佇列中有 1 條訊息。