基於Spring Integration和Apache Camel的SEDA

banq發表於2022-11-28

SEDA,或階段化事件驅動架構,是Matt Welsh在他的博士論文中提出的一種架構風格。論文。它的主要優點是可伸縮性、支援高併發流量和可維護性。

由於可伸縮性是SEDA的核心目標,因此通常最好設計專注於特定操作的小階段,特別是當我們有I/O密集型任務時。而且,擁有小的階段有助於我們更好地調整每個階段的規模。

基於Spring Integration和Apache Camel的SEDA

我們的示例問題將是簡單明瞭的:計算每個單詞在給定字串中不區分大小寫出現的次數。
讓我們把一個單詞定義為一系列沒有空格的字元,我們將忽略標點符號等其他複雜因素。我們的輸出將是一個對映,其中包含作為鍵的單詞和作為值的計數。


為了解決字數統計問題,我們可以透過以下幾個階段來實現解決方案:

  • 接受文字
  • 分割詞語
  • 轉換小寫
  • 單詞計數
  • 返回


現在我們已經有了階段設計,讓我們在下一節中使用兩種不同的企業整合技術來實現它。在此表中,我們可以預覽SEDA將如何在我們的實現中顯示:

使用Spring整合的解決方案
對於我們的第一個實現,我們將使用Spring Integration。Spring Integration構建在Spring模型之上,以支援流行的企業整合模式。
Spring Integration有三個主要元件:

  1. 訊息是包含報頭和正文的資料結構。
  2. 通道將訊息從一個終結點傳送到另一個終結點。 Spring Integration中有兩種通道:
    • 點對點:只有一個終結點可以使用此通道中的訊息。
    • 釋出-訂閱:多個終結點可以使用此通道中的訊息。
  3. 終結點將訊息路由到執行某些業務邏輯的應用程式元件。 SpringIntegration中有各種各樣的端點,比如轉換器、路由器、服務啟用器和過濾器。

    1、準備階段

    <dependencies>
        <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-integration</artifactId>
        </dependency>
        <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        </dependency>
        <dependency>
        <groupId>org.springframework.integration</groupId>
        <artifactId>spring-integration-test</artifactId>
        <scope>test</scope>
        </dependency>
    </dependencies>
    


    訊息傳遞閘道器是一個代理,它隱藏了向整合流傳送訊息的複雜性。讓我們為Spring整合流程設定一個:

    @MessagingGateway
    public interface IncomingGateway {
        @Gateway(requestChannel = "receiveTextChannel", replyChannel = "returnResponseChannel")
        public Map<String, Long> countWords(String input);
    }
    


    在SEDA下,通道需要透過關聯的執行緒池進行擴充套件,因此讓我們從建立執行緒池開始:

    @Bean("receiveTextChannelThreadPool")
    TaskExecutor receiveTextChannelThreadPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(1);
        executor.setMaxPoolSize(5);
        executor.setThreadNamePrefix("receive-text-channel-thread-pool");
        executor.initialize();
        return executor;
    }
    


    接下來,我們將使用執行緒池建立通道:

    @Bean(name = "receiveTextChannel")
    MessageChannel getReceiveTextChannel() {
        return MessageChannels.executor("receive-text", receiveTextChannelThreadPool)
          .get();
    }
    


    MessageChannels是一個Spring Integration類,它幫助我們建立各種型別的通道。這裡,我們使用executor()方法建立一個 ExecutorChannel,它是一個由執行緒池管理的通道。

    2、SEDA接受檔案階段

    我們的渠道建立後,我們就可以開始實施我們的階段了。讓我們建立初始階段:

    @Bean
    IntegrationFlow receiveText() {
        return IntegrationFlows.from(receiveTextChannel)
          .channel(splitWordsChannel)
          .get();
    }
    


    IntegrationFlows是一個流暢的Spring整合API,用於建立 IntegrationFlow物件,表示我們的流的各個階段。


    3、SEDA拆分單詞階段
    我們的下一階段只有一項責任:將我們的輸入字串拆分成一個 字串陣列,其中包含句子中的各個單詞:

    @Bean
    IntegrationFlow splitWords() {
        return IntegrationFlows.from(splitWordsChannel)
          .transform(splitWordsFunction)
          .channel(toLowerCaseChannel)
          .get();
    }
    


    4、SEDA轉為小寫階段

    @Bean
    IntegrationFlow toLowerCase() {
        return IntegrationFlows.from(toLowerCaseChannel)
          .split()
          .transform(toLowerCase)
          .aggregate(aggregatorSpec -> aggregatorSpec.releaseStrategy(listSizeReached)
            .outputProcessor(buildMessageWithListPayload))
          .channel(countWordsChannel)
          .get();
    }
    

    我們在這裡使用的第一個新的 IntegrationFlows 方法是 split()。split()方法使用splitter模式,將我們的輸入訊息的每個元素作為單獨的訊息傳送到toLowerCase。

    我們看到的下一個新方法是aggregator(),它實現了聚合器模式。聚合器模式有兩個基本引數。
    • 釋出策略,它決定何時將訊息合併成一個單一的訊息
    • 處理器,它決定了如何將訊息合併成一個單一的訊息。

    我們的釋出策略函式使用listSizeReached,它告訴聚合器在輸入陣列的所有元素都被收集後開始聚合。

    5、計詞階段
    我們的最後階段將我們的單詞計數打包成一個Map,其中鍵是原始輸入的單詞,而值是每個單詞的出現次數。

    @Bean
    IntegrationFlow countWords() {
        return IntegrationFlows.from(countWordsChannel)
          .transform(convertArrayListToCountMap)
          .channel(returnResponseChannel)
          .get();
    }
    


    使用Apache Camel的解決方案
    Apache Camel是一個流行而強大的開源整合框架。它基於四個主要概念。

    • Camel上下文。Camel執行時將不同的部分粘在一起。
    • 路由。路由決定了一個訊息應該如何被處理,以及它接下來應該去哪裡。
    • 處理程式。這些是各種企業整合模式的即用型實現。
    • 元件。元件是透過JMS、HTTP、檔案IO等整合外部系統的擴充套件點。


    詳細點選標題

    這些示例的原始碼可在 GitHub 上獲得。
  4. 相關文章