日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring集成–强大的拆分器聚合器

發布時間:2023/12/3 javascript 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring集成–强大的拆分器聚合器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

堅固是什么意思?

在本文的上下文中,健壯性是指在不立即返回到調用者的情況下管理流中的異常條件的能力。 在某些處理方案中, n個 m個回答足以做出結論。 通常具有這些趨勢的示例處理場景是:

  • 財務,保險和預訂系統的報價。
  • 扇出出版系統。
  • 為什么需要魯棒的分離器聚合器設計?

    首先,可能需要對典型的Splitter Aggregator模式進行介紹。 拆分器是一種EIP模式,它描述了一種機制,用于將復合消息分解為多個部分,以便可以分別處理它們。 路由器是一種EIP模式,用于將消息路由到各個通道中-將它們瞄準特定的消息傳遞端點。 聚合器是一種EIP模式,用于整理和存儲屬于某個組的一組消息,并在該組完成后釋放它們。

    這三個EIP構造共同構成了一種強大的機制,可將處理劃分為不同的工作單元。 Spring Integration(SI)使用與EIP相同的模式術語,因此該方法的讀者將非常熟悉Spring Integration Framework的構造。 SI框架允許對所有這三個結構進行重大定制,此外,就像在任何其他多線程配置中一樣,只需使用異步通道即可使這些工作單元并行執行。

    與SI Splitter Aggregator設計一起使用時,一個有趣的挑戰是構建適當健壯的流,這些流可以在許多調用場景中可預測地運行。 一個簡單的拆分器聚合器設計可以在許多情況下使用,并且無需大量定制SI構造即可運行。 但是,某些服務要求需要更強大的處理策略,因此需要更復雜的配置。 以下各節描述并顯示了Simple Splitter Aggregator設計的實際外觀,設計必須能夠處理的處理類型,然后為更健壯的處理提出建議的解決方案。

    簡單的拆分器聚合器設計

    以下Splitter Aggregator設計展示了一個簡單的流程,該流程將文檔請求消息接收到消息傳遞網關中,將消息分為兩個處理路由,然后聚合響應。 請注意,該圖是從OmniGraffle中的EIP構造構建的,而不是從STS內部的“集成圖”視圖。 為了簡潔起見,圖中沒有顯示通道。

    SI的詳細構造:

    消息傳遞網關 –有三個消息傳遞網關。 有多種配置可用于網關規范,但可以顯著地返回業務對象,異常和空值(超時后)。 最左邊的網關是我們為其定義流程的服務網關。 路由器和聚合器之間的其他兩個網關是外部系統,它們將提供對我們流程產生的業務問題的響應。

    拆分器 –存在一個拆分器,它負責使用文檔消息并生成消息集合以進行后續處理。 通常,自定義拆分器的Java簽名指定單個對象參數和用于返回的集合。

    收件人列表路由器 –存在一個路由器,可以使用任何適當的路由器,選擇與您的要求非常匹配的路由器–您可以輕松地按表達式或有效負載類型進行路由。 路由器的主要目的是路由分離器提供的消息集合。 這是一個非常典型的拆分器聚合器配置。

    聚集器 –單個構造,負責將消息集中在一起收集,以便可以對網關響應進行進一步處理。 盡管可以使用屬性和Bean定義來配置Aggregator,以提供替代的分組和發布策略,但大多數情況下,默認的聚合策略就足夠了。

    拆分器聚合器操作的有趣方面

  • 網關 –入站網關(最左邊的一個)上可能有也可能沒有定義錯誤處理bean引用。 如果這樣做,那么該bean將有機會處理該網關右側的流中引發的異常。 否則,任何異常將直接拋出網關。
  • 網關 –可以在每個網關上設置一個可選的默認答復超時 ,設置此值有很大的含義,請確保它們被很好地理解。 超時將導致網關返回空值 。 如果上游網關也沒有設置默認應答超時 ,則這是可能導致線程駐留的完全相同的條件。
  • 分配器輸入通道 –這可以是簡單的直接通道,也可以是定義了調度程序的直接通道。 如果通道指定了調度程序,則此點的下游流將是異步的多線程的。 這也改變了上游網關的語義,因為它通常意味著原本不重要的default-reply-timeout變為活動狀態。
  • 拆分器 –拆分器必須返回單個對象。 拆分器返回的單個對象是一個集合java.util.List。 SI框架將采用該列表的每個成員,并將其饋入Splitter的輸出通道 –與本示例一樣,通常直接進入路由器。 “拆分器列表”返回的合同與在Java中的用法相同-它可能包含零個,一個或多個元素。 如果拆分器返回一個空列表,則路由器不太可能要做任何工作,因此流調用將完成。 但是,如果列表包含一項,則SI框架將從列表中提取該項目并將其推入路由器,如果成功路由,則流程將繼續。
  • 路由器 –在此示例中,路由器將僅將消息路由到兩個網關之一。
  • 網關 –在拆分器和聚合器之間使用的兩個網關很有趣。 在此示例中,我使用通用網關EIP模式表示消息子系統,但未明確定義-我們可以使用HTTP出站網關,另一個SI流或任何其他外部系統。 當然,對于這些子系統中的每一個,許多響應都是可能的。 取決于協議和外部系統,消息請求可能無法發送,響應未能到達,調用了長時間運行的進程,網絡錯誤或超時或常規處理異常。
  • 聚合器 –單個聚合器將等待大量響應,具體取決于拆分器創建的內容。 在拆分器返回列表為空的情況下,將不會調用聚合器。 如果拆分器返回列表只有一個條目,則聚合器將等待一個網關響應來完成該組。 如果“拆分器”列表具有n個條目,則聚合器將等待n個條目來完成該組。 可以在一組豐富的配置方面中注入自定義關聯策略,發布策略和消息存儲。
  • 簡單拆分器聚合器操作的有趣方面

    確定這種類型的簡單網關是否足以滿足要求的主要決定因素是了解發生故障時發生的情況。 如果您的SI流中發生任何異常導致流調用被放棄并且符合您的要求,則無需進一步閱讀。 但是,如果您需要在其中一個網關發生故障后繼續進行處理,那么本文的其余部分可能會引起您的更多興趣。

    拆分器和聚合器之間生成的任何來源的異常都將導致聚合器丟棄空的或部分的組。 異常將傳播回最近的上游網關,以供自定義bean處理或由網關重新拋出。 請注意,聚合器上的自定義釋放策略很難使用,尤其是與超時一起使用,但在這種情況下無濟于事,因為異常將在調用聚合器之前傳播回最左邊的網關。

    也可以在最內部的網關上配置異常處理程序,可能會捕獲到異常消息,但是如何將消息從定制異常處理程序路由到聚合器以完成組,將聚合器通道定義注入到定制異常處理程序中呢? 這是一種較差的方法,可能涉及解包異常消息有效負載,將原始消息標頭復制到新的SI消息中,然后添加原始有效負載–只有四或五行代碼,但是很臟。

    生成異常后,不能將異常消息( 未經修改 )路由到聚合器中以完成組。 原始消息(包含有關組和組位置的相關ID和序列ID的消息)被掩埋在SI消息異常有效負載之內。

    如果在異常生成之后需要繼續處理,則必須清楚,為了繼續處理,必須進行以下操作:

    • 聚合組需要完成,
    • 返回到壁櫥上游網關之前,必須捕獲和處理所有異常,
    • 允許在聚合器中完成組的相關性和序列標識符被掩埋在異常消息有效負載之內,并且將需要對綁定到聚合器的消息進行提取和設置

    更健壯的解決方案–消息傳遞網關適配器模式

    處理網關的異常和空返回值自然會導致一種設計,該設計在消息傳遞網關周圍實現包裝器。 這樣就提供了一個很難建立的控制級別。

    這種適配器技術允許在將消息傳遞網關注入到Service Activator并從中直接調用時,捕獲并處理消息傳遞網關的所有返回。 消息傳遞網關不再直接響應聚合器,而是響應在Service Activator名稱空間定義中配置的自定義Java代碼Spring bean。 不出所料,不會發生異常的處理將繼續正常進行。 那些經歷異常情況或消息網關發出意外響應或缺少響應的流需要以某種方式處理消息,例如可以完成綁定到聚合的消息組。 如果Service Activator允許將異常傳播到其支持bean之外,則該組將無法完成。 同樣的情況不僅適用于異常,而且不包含前提條件組相關ID和序列標頭的任何返回對象-這就是應用適配的地方。

    捕獲和處理來自消息傳遞網關的異常消息或空響應,如以下示例代碼所示:

    import com.l8mdv.sample.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.integration.Message; import org.springframework.integration.MessageHeaders; import org.springframework.integration.support.MessageBuilder; import org.springframework.util.Assert;public class AvsServiceImpl implements AvsService {private static final Logger logger= LoggerFactory.getLogger(AvsServiceImpl.class);public static final String MISSING_MANDATORY_ARG= "Mandatory argument is missing.";private AvsGateway avsGateway;public AvsServiceImpl(final AvsGateway avsGateway) {this.avsGateway = avsGateway;}public Message<AvsResponse> service(Message<AvsRequest> message) {Assert.notNull(message, MISSING_MANDATORY_ARG);Assert.notNull(message.getPayload(), MISSING_MANDATORY_ARG);MessageHeaders requestMessageHeaders = message.getHeaders();Message<AvsResponse> responseMessage = null;try {logger.debug("Entering AVS Gateway");responseMessage = avsGateway.send(message);if (responseMessage == null)responseMessage = buildNewResponse(requestMessageHeaders,AvsResponseType.NULL_RESULT);logger.debug("Exited AVS Gateway");return responseMessage;} catch (Exception e) {return buildNewResponse(responseMessage, requestMessageHeaders,AvsResponseType.EXCEPTION_RESULT, e);}}private Message<AvsResponse> buildNewResponse(MessageHeaders requestMessageHeaders,AvsResponseType avsResponseType) {Assert.notNull(requestMessageHeaders, MISSING_MANDATORY_ARG);Assert.notNull(avsResponseType, MISSING_MANDATORY_ARG);AvsResponse avsResponse = new AvsResponse();avsResponse.setError(avsResponseType);return MessageBuilder.withPayload(avsResponse).copyHeadersIfAbsent(requestMessageHeaders).build();}private Message<AvsResponse> buildNewResponse(Message<AvsResponse> responseMessage,MessageHeaders requestMessageHeaders,AvsResponseType avsResponseType,Exception e) {Assert.notNull(responseMessage, MISSING_MANDATORY_ARG);Assert.notNull(responseMessage.getPayload(), MISSING_MANDATORY_ARG);Assert.notNull(requestMessageHeaders, MISSING_MANDATORY_ARG);Assert.notNull(avsResponseType, MISSING_MANDATORY_ARG);Assert.notNull(e, MISSING_MANDATORY_ARG);AvsResponse avsResponse = new AvsResponse();avsResponse.setError(avsResponseType,responseMessage.getPayload(), e);return MessageBuilder.withPayload(avsResponse).copyHeadersIfAbsent(requestMessageHeaders).build();} }

    注意異常處理塊的catch子句的最后一行。 這行代碼將相關性和序列標頭復制到響應消息中,如果要允許聚合組完成,則這是強制性的,并且在出現異常后總是必需的,如此處所示。

    使用這種技術的后果

    毫無疑問,在SI配置中引入消息傳遞網關適配器會使配置更加復雜,難以閱讀和遵循。 此處的關鍵因素是在配置文件中不再線性進行。 這是因為Service Activator必須轉發引用一個網關或一個在適配Service Activator之前定義的網關–在兩種情況下,結果都是相同的。

    資源資源

    注意:-推動創建此元模式的軟件的設計基于一項要求,即單個中央風險評估服務將訪問許多外部風險評估服務。 為了使服務的客戶滿意,盡管這些外部服務中的任何一項發生了故障,調用都必須并行進行并繼續進行。 這項要求導致了該項目的消息傳遞網關適配器模式的設計。

  • Spring集成參考手冊
  • 在建立大型美國金融機構的風險評估流程的背景下,直接與Mark Fisher(SpringSource)討論了解決此問題的方法。 盡管配置和代碼受NDA和版權保護,但可以在本文中表達設計意圖和類似代碼。
  • 參考: Spring Integration – TechiQuest博客上來自我們JCG合作伙伴 Matt Vickery的強大的Splitter Aggregator 。

    翻譯自: https://www.javacodegeeks.com/2013/06/spring-integration-robust-splitter-aggregator.html

    總結

    以上是生活随笔為你收集整理的Spring集成–强大的拆分器聚合器的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。