Hermes訊息代理簡介
1. 引言
在本教程中,我們將了解Allegro Tech 公司的Hermes 訊息代理程式。我們將了解它的功能、設定方法以及如何使用它來發送和接收訊息。
2. 什麼是愛馬仕?
Hermes 是一個基於 Apache Kafka 的訊息代理程式。它採用簡潔的 HTTP 中心架構,允許客戶端透過標準的 HTTP 請求發布訊息和接收訊息。這種設計使得任何客戶端都能以最小的依賴項使用它,而無需了解底層訊息傳遞基礎設施。這意味著我們可以使用 Hermes 連接各種應用程序,無論它們使用何種技術。
儘管 Hermes 為我們提供了簡化的訊息發布和接收接口,但它在底層 Kafka 系統之上僅增加了極少的開銷。它還具有高可靠性,並且能夠隨著需求的成長輕鬆擴展。即使底層基礎設施發生故障,它也會盡力確保發送到系統的所有訊息都能正確處理並傳遞給所有客戶端。
3. 奔跑的愛馬仕
Hermes由多個組件構成,所有組件都需要協同工作:
- Hermes 管理 – 用於設定 Hermes 群組、主題和訂閱的管理介面
- Hermes 前端 – 接收來自客戶端的新訊息並將其傳送給已訂閱客戶端的介面。
- Hermes Consumers – 向已訂閱的客戶發送訊息
此外,我們還需要一些基礎設施。至少需要 Kafka 和 Zookeeper。
快速入門最簡單的方法就是使用 Docker。 Allegro Tech 為所有 Hermes 元件以及我們的依賴項發布了 Docker 容器。因此,我們可以使用 Docker Compose 檔案將所有內容一起啟動:
services:
zk:
image: "confluentinc/cp-zookeeper:7.9.4"
ports:
- "2181:2181"
user: root
environment:
ZOOKEEPER_CLIENT_PORT: 2181
kafka:
image: "confluentinc/cp-kafka:7.9.4"
ports:
- '9092:9092'
depends_on:
- zk
user: root
environment:
KAFKA_ZOOKEEPER_CONNECT: zk:2181
KAFKA_ADVERTISED_LISTENERS: DOCKER_INTERNAL_LISTENER://kafka:29092,DOCKER_EXTERNAL_LISTENER://localhost:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: DOCKER_INTERNAL_LISTENER:PLAINTEXT,DOCKER_EXTERNAL_LISTENER:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: DOCKER_INTERNAL_LISTENER
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
frontend:
image: allegro/hermes-frontend:hermes-2.11.7
ports:
- "8080:8080"
depends_on:
- zk
- kafka
consumers:
image: allegro/hermes-consumers:hermes-2.11.7
ports:
- "8070:8070"
depends_on:
- zk
- kafka
management:
image: allegro/hermes-management:hermes-2.11.7
ports:
- "8090:8090"
depends_on:
- zk
- kafka
這將啟動 Hermes 2.11.7(撰寫本文時的最新版本),以及 Zookeeper 和 Kafka。請注意,此簡化版本未配置任何磁碟區,因此容器關閉後不會持久化任何資料。因此,它僅適用於快速測試。
一旦所有程式啟動完畢,我們就可以透過http://localhost:8090/ui存取管理介面:
我們也可以透過向 http://localhost:8080 發出適當的 API 呼叫來發布訊息,稍後我們將看到這一點。
4. 小組和主題
Hermes 將我們所有的郵件按主題進行管理,並將主題組合成群組。我們可以在管理控制台中管理所有這些內容。
當我們打開管理介面並存取控制台時,它會顯示所有群組的清單:
在這裡,我們可以選擇一個現有群組或建立一個新群組。建立新群組只需要輸入群組名稱即可:
打開群組後,我們就可以看到所有主題的清單:
在這裡,我們可以選擇一個現有主題,也可以建立一個新主題:
在創建主題時,我們需要填寫以下資訊:
- 名稱——主題的名稱。
- 描述-主題的有用描述。
- 所有者來源和所有者 – 對主題所有者的描述。
- Kafka ACK 等級 – 需要確認收到新訊息的 Kafka 節點數量。
- 內容類型 – 我們將要傳送的訊息類型,JSON 或 AVRO。
與 Java 類別類似,我們的主題也有一個完全限定名稱,它由群組名稱和主題名稱組成,中間用句點分隔——在本例中,它就是com.baeldung.hermes.testing 。這在我們向主題發布訊息時非常重要。
創建好主題後,我們就可以立即發布訊息。但是,此時沒有人會收到這些訊息。
5. 訂閱
當某個主題收到訊息時,Hermes 會使用訂閱來決定如何傳遞這些訊息。我們可以在主題的「訂閱」窗格中查看該主題的所有訂閱:
我們可以根據需要為一個主題建立任意數量的訂閱。每個訂閱在訊息送達時都會將其發送到不同的端點。
我們也可以從這裡使用「建立訂閱」按鈕建立新的訂閱:
在建立訂閱時,我們需要填寫以下資訊:
- 名稱 – 訂閱的名稱。
- 端點 – 所有訊息都會傳送到的 URL。
- 描述 – 對該訂閱的詳細說明。
- 所有者來源和所有者 – 對訂閱所有者的描述。
- 發送方式-是單獨發送訊息,還是大量發送訊息。
- 內容類型 – 訊息的內容類型,JSON 或 AVRO。
- 速率限制——每秒發送的最大訊息數。
- 正在發送的訊息數量 – 在任何給定時間正在發送的訊息的最大數量。
訂閱創建完成後,發送到該主題的所有訊息都會傳遞到我們的端點。此外,系統也會傳遞在配置的保留期內發送到該主題的所有訊息。這使我們能夠創建新的訂閱,從而立即獲取最新的消息。
6. 發布訊息
現在我們已經設定好了主題和訂閱,接下來需要能夠向其中發布訊息。 Hermes 提供了一個簡單的 HTTP API 用於發布訊息,還有一個 Java 用戶端,使用起來更加方便。
6.1. HTTP
要向我們的主題發布訊息,我們需要向 Hermes 前端服務發送 HTTP POST 請求。該請求的 URL 為/topics/後面跟著主題的完整限定名稱,例如/topics/com.baeldung.hermes.testing 。請求正文就是我們要傳送到主題的訊息:
POST /topics/com.baeldung.hermes.testing HTTP/1.1
Host: localhost:8080
Content-Length: 29
Content-Type: application/json
{"id": 12345, "page": "main"}
如果請求成功,Hermes 將傳回 HTTP 202 Accepted 回應:
HTTP/1.1 202 Accepted
Hermes-Message-Id: dd483b95-0a91-4331-b366-7c7ddff8eaf2
Content-Length: 0
Date: Thu, 20 Nov 2025 07:29:54 GMT
此回應確認 Hermes 已接收訊息,並將盡快發布給訂閱者。 Hermes也會透過Hermes-Message-Id HTTP 標頭傳回一個唯一的訊息 ID。該 ID 會為我們發送的每個訊息生成,以便我們追蹤訊息在系統中的流轉情況。
如果失敗,我們會收到相應的錯誤訊息。例如,如果我們嘗試發佈到不存在的主題,則會收到 HTTP 404 Not Found 錯誤。
6.2. Java客戶端
我們還有一個 Java 客戶端,可以更輕鬆地發布訊息。
要使用它,我們首先需要將客戶端依賴項新增到我們的專案中。如果我們使用的是 Maven,我們可以將此依賴項新增到pom.xml檔案中:
<dependency>
<groupId>pl.allegro.tech.hermes</groupId>
<artifactId>hermes-client</artifactId>
<version>2.11.10</version>
</dependency>
完成上述步驟後,我們現在可以建立一個HermesClient實例:
HermesClient hermesClient = HermesClientBuilder.hermesClient(hermesSender)
.withURI(URI.create("http://localhost:8080"))
.build();
我們還需要一個HermesSender實例來發出 HTTP 請求。我們有 幾個實例可供選擇,例如,如果我們想要使用 Spring WebClient ,可以選擇WebClientHermesSender ;如果我們想要使用 Spring RestClient , RestClientHermesSender 。
HermesSender hermesSender = new WebClientHermesSender(WebClient.create());
HermesSender hermesSender = new RestClientHermesSender(RestClient.create());
創建好HermesClient之後,我們就可以使用publishJSON()方法發送訊息了:
CompletableFuture<HermesResponse> result =
hermesClient.publishJSON("com.baeldung.hermes.testing", "{\"hello\": 1}");
這需要提供主題的完整限定名稱和我們要發佈的內容。
如果我們對結果感興趣,這將提供一個CompletableFuture ,它包裝了發布訊息的結果。我們可以使用它來檢查呼叫是否成功,如果需要,也可以取得訊息 ID:
HermesResponse response = result.join();
if (response.isSuccess()) {
String messageId = response.getMessageId();
// Handle success
} else {
// Handle failure
}
此時,我們可以向 Hermes 發送訊息,然後 Hermes 會將訊息轉發給所有訂閱者。
7. 接收訊息
除了發送訊息,我們還需要能夠接收訊息。這就要求我們執行一個已知 URL 的 HTTP 伺服器。這個伺服器可以位於任何位置,只要 Hermes Consumer 服務能夠存取它即可:
@RestController
@RequestMapping("/hermes")
public class HermesController {
@PostMapping("/testing")
public void receive(@RequestBody String body) {
System.out.println("Received message: " + body);
}
}
接下來,我們需要像之前看到的那樣,將此 URL 註冊為您的主題的訂閱者。 Hermes會向我們的 URL 發送 HTTP POST 請求,並將訊息有效負載作為請求體。之後,我們可以對該有效負載進行任何操作。
如果我們的伺服器回傳 HTTP 2xx 或 HTTP 4xx 狀態碼,Hermes 會認為訊息已送達。 4xx 狀態碼通常表示錯誤,但這些錯誤是客戶端的錯誤,而非伺服器端的錯誤。因此,Hermes 會認為訊息永遠無法成功送達,並且不會再嘗試。
如果我們的伺服器傳回 HTTP 5xx 狀態碼,Hermes 會將其視為失敗並採取相應的措施。這可能包括在適當情況下重試發送訊息,從而盡可能確保訊息送達。
8. 總結
本文中,我們對 Hermes 訊息代理人進行了簡要介紹。這個系統還有很多其他功能。下次您的應用程式需要訊息代理程式時,不妨試試 Hermes。
與往常一樣,本文中的所有範例都可以在 GitHub 上找到。