搶先一步
VMware 提供培訓和認證,以加速您的進展。
了解更多這是 Spring Cloud Stream 2.0.0.RELEASE 準備階段中一系列預先發佈部落格的第一篇。
Spring Cloud Stream 2.0 包含針對基於通道的繫結器的內容類型協商進行了徹底的修改,以解決效能、彈性,以及最重要的是一致性。 以下部落格文章將觸及關於已完成的工作、預期以及它可能如何協助您的一些關鍵要點。
資料轉換是任何訊息驅動微服務架構的核心功能之一。 在 Spring Cloud Stream 中,此類資料表示為 Spring Message
。
在訊息流程(串流)的各個點,訊息可能必須在到達其目的地之前轉換為所需的形狀/大小。 這是由於兩個原因而需要的
1. 將傳入訊息的內容從線路格式轉換,以符合應用程式提供的處理常式的簽章。 2. 將傳出訊息的內容轉換為下一個處理常式的簽章(如果存在一些內部流程)或轉換回線路格式。
線路格式通常是 byte[]
,並且由繫結器實作管理。
在 Spring Cloud Stream Message 中,轉換是使用 org.springframework.messaging.converter.MessageConverter
抽象化完成的。
以下步驟順序顯示了典型的訊息流程以及 Message
經歷的轉換,使用 Spring Cloud Stream 的 Processor
合約描述,本質上涵蓋了輸入和輸出內容轉換背後的要求。
1. 從繫結器接收線路格式的 Spring Message
2. 確保在 Spring Message
中設定了輸入 contentType
標頭 3. 將 Spring Message
從線路格式轉換為應用程式提供的 MessageHandler
的簽章 4. 呼叫應用程式提供的 MessageHandler
5. 將 MessageHandler
的傳回值轉換回 Spring Message
6. 確保在 Spring Message
中設定了輸出 contentType
標頭 7. 將 Spring Message
轉換回線路格式 8. 以線路格式將 Spring Message
送回繫結器
雖然以上內容提供了典型訊息流程中主要狀態變更的完整摘要,但魔鬼總是在細節中,所以讓我們更仔細地查看每個步驟。
Processor.INPUT'
)。contentType
標頭注入到傳入訊息中,當且僅當傳入訊息尚未設定 contentType
標頭時。 這是必需的,以確保在需要時,下游訊息轉換可以將 contentType
納入考量(稍後會詳細介紹)。 注入的 contentType
來自每個目的地繫結設定的內容類型,application/json
是預設內容類型。例如,'spring.cloud.stream.bindings.myInput.content-type=text/plain' 將 'myInput'(傳入)目的地繫結的內容類型設定為 'text/plain'。 這表示每個傳入訊息都會注入 'contentType=text/plain' 標頭,除非該訊息已經包含 'contentType' 標頭。 換句話說,標頭提供的 contentType
取代每個繫結設定的那個。 3. 現在,借助於 HandlerMethodArgumentResolvers
和預先配置或使用者提供的 MessageConverters
,傳入訊息會被轉換為應用程式提供的 MessageHandler
的簽章(例如,public Text process(Foo foo){..}
)。 此類處理常式方法通常使用 @StreamListener
、@ServiceActivator
、@Transformer
等註解。 這是某些轉換器可能需要 contentType
的地方,步驟 2 中的動作可確保此類訊息始終透過其 contentType
標頭可用。 當然,如果此類方法採用 Message
作為其輸入引數,則不會執行轉換。 4. 呼叫處理常式方法,成功後,便開始從處理常式方法的傳回值建立傳出訊息的過程(假設是非 void 處理常式方法)。 5. 僅當傳回值還不是 Message
時,處理常式方法傳回的值才會轉換回 Spring Message
。 這表示會建立一個新的 Spring Message
,其有效負載是處理常式的傳回值。 傳入訊息的標頭會被複製到新的傳出訊息中,並移除由'SpringIntegrationProperties.messageHandlerNotPropagatedHeaders' 識別的任何標頭。 預設情況下,那裡只有一個標頭設定 - contentType
。 這表示會建立一個沒有設定 contentType
標頭的新傳出訊息。 這是為了確保 contentType
可以隨著實際資料的應用程式層級轉換而演變。 注意:僅當處理常式方法傳回非 Message 時,才會移除 contentType
。 訊息會被傳送到繫結器的輸出通道。 6. 與繫結器的輸入通道類似,繫結器的輸出通道(例如,Processor.OUTPUT
)也預先配置了一個通道攔截器。 在這裡,我們會選擇性地將 contentType
標頭注入到傳出訊息中,以準備將傳出訊息的內容轉換回線路格式。 讓我們看看僅有的兩種可能情況: a. 傳出 Message 設定了 contentType
標頭。 由於標頭設定的 contentType
優先於任何其他 contentType
,因此不會執行 contentType
注入,並且標頭設定的 contentType
值將在轉換回線路格式期間使用。 b. 傳出 Message 沒有設定 contentType
標頭。 繫結 contentType
(預設或提供的)將作為標頭注入到傳出訊息中,並在轉換回線路格式期間使用。 7. 訊息是使用其中一個可用的 MessageConverters
轉換為線路格式。 8. 轉換後的訊息會被送回繫結器,並保留注入或現有的 contentType
標頭。 換句話說,傳出訊息將始終存在 contentType
標頭。
以上涵蓋了預設的開箱即用行為。 但這可能還不夠,所以我們是否可以自訂?如果可以,我們要如何自訂?。 2.0 中所做的內容類型協商改進的目標不僅是回答這些類型的問題,而且要確保答案是一致的 - 輸入和輸出通道攔截器用來轉換為/從線路格式的 'MessageConverters' 與 'HandlerMethodArgumentResolvers' 用來轉換為/從強類型的 'MessageConverters' 相同。
若要新增自訂 MessageConverter,只需建立 org.springframework.messaging.converter.MessageConverter
的實作,並將其配置為 @Bean
,並將該 Bean 標註為 @StreamMessageConverter
,它將作為第一個轉換器新增到現有 MessageConverters 的堆疊中,本質上優先於現有的 MessageConverters。
希望到目前為止,很明顯任何和所有內容類型轉換都是由 MessageConverters
完成的。 雖然 MessageConverters
在其實作中有所不同,但大多數都利用 contentType
標頭以及目標類型 (targetClass
),這使他們能夠執行類型內轉換以及與線路格式之間的轉換。 目前有一組預先配置的 MessageConverters
來支援大多數用例,因此對於大多數典型的資料類型(即,json、文字等),最終使用者實際上不需要做任何事情。 然而,值得了解現在事情如何運作以及如何自訂 - 自訂現有和/或引入新的 MessageConverter
實作。
我們目前正在更新文件,其中將包含更多關於此主題以及與 2.0 版本相關的其他主題的詳細資訊和範例。這些預發布部落格的主要目的是提高認知度、方便大家「嘗試」並徵求回饋意見。 也就是說;Spring Cloud Stream 2.0.0.RC1 可在此處取得
我們鼓勵您使用以下管道之一提供意見回饋
祝您使用愉快!