簡體   English   中英

Spring集成流程中的錯誤處理實踐

[英]Error handling practices in spring integration flow

我有一個Spring集成流程,涉及異步執行,從網關返回值到控制器,返回值后繼續集成流程。

這是網關:

@MessagingGateway
public interface GW {

    @Gateway(requestChannel = "f.input")
    Task input(Collection<MessengerIncomingRequest> messages);

}

這是流程:

@Bean
IntegrationFlow jFlow() {
        return IntegrationFlows.from(
        MessageChannels.executor("f.input", executor()))
        .split()
        .channel(MessageChannels.executor(executor()))
        .transform(transformer)
        .channel(routerChannel())
        .get();
}

@Bean
ThreadPoolTaskExecutor executor() {
        ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
        ...
        return pool;
}

@Bean
MessageChannel routerChannel() {
        return MessageChannels
        .publishSubscribe("routerChannel", executor())
        .get();
}

@Bean
IntegrationFlow routerChannelFlow() {
        return IntegrationFlows
        .from(routerChannel())
        .publishSubscribeChannel(s -> s
        .subscribe(f -> f.bridge(null))
        .subscribe(process()))
        .get();
}

@Bean
IntegrationFlow process() {
        return f ->
        f.route(p -> p.getKind().name(),
        m -> m.suffix("Channel")
        .channelMapping(TaskKind.CREATE.name(), "create")
        ....
}

@Bean
IntegrationFlow createFlow() {
        return IntegrationFlows.from(
        MessageChannels.direct("createChannel"))
        .handle(routerService)
        .get();
}

如何為整個流程定義錯誤處理程序? 什么是最佳做法? 我知道我可以為網關方法調用設置一個try / catch塊,但是它只會捕獲jFlow流中出現的異常,這些異常發生在channel(routerChannel())

如何處理其余流程的錯誤? 還是整個流程?

UPDATE

我為publishSubscribeChannel添加了錯誤處理程序

@Bean
IntegrationFlow routerChannelFlow() {
    return IntegrationFlows
            .from(routerChannel())
            .publishSubscribeChannel(s -> s
                    .subscribe(f -> f.bridge(null))
                    .subscribe(process())
                    .errorHandler(errorHandler))
            .get();
}

但它似乎沒有幫助,因為如果出現異常,我會收到以下錯誤:

cMessagingTemplate$TemporaryReplyChannel : Reply message received but the receiving thread has already received a reply:ErrorMessage [payload=org.springframework.messaging.MessageHandlingException:

並且我的錯誤處理程序不會被調用。

UPDATE

根據Gary的回答,我嘗試了這段代碼:

@Bean
IntegrationFlow jFLow() {
    return IntegrationFlows.from(
            MessageChannels.executor("f.input", executor()))
            .split()
            .channel(MessageChannels.executor(executor()))
            .transform(transformer)
            .channel(routerChannel())
            .get();
}

@Bean
IntegrationFlow exceptionOrErrorFlow() {
    return IntegrationFlows.from(
            MessageChannels.direct("exceptionChannel"))
            .handle(errorHandler, "handleError")
            .get();
}

    @Bean
MessageChannel exceptionChannel() {
    return MessageChannels.direct("exceptionChannel")
            .get();
}

@Bean
IntegrationFlow process() {
        return f ->
        f.enrichHeaders((spec) ->
                    spec.header("errorChannel", "exceptionChannel", true))
        f.route(p -> p.getKind().name(),
        m -> m.suffix("Channel")
        .channelMapping(TaskKind.CREATE.name(), "create")
        ....
}

@MessagingGateway(errorChannel = "exceptionChannel")

在另一次編輯之后,我將exceptionChannel添加到網關,並將富集標題移動到我的流的第二段(異步)。 如果在流的同步部分拋出異常,則控制器被阻塞。

首先,讓我解釋網關的工作原理 - 它應該有助於理解下面的解決方案。

請求消息獲得唯一的臨時回復通道,該通道被添加為replyChannel標頭。 即使網關具有顯式的replyChannel ,它也只是橋接到請求的replyChannel - 這就是網關如何將回復與請求相關聯。

現在,網關還將請求的errorChannel標頭設置為相同的回復通道。 這樣,即使流是異步的,也可以將異常路由回網關,並將其拋出到調用者或路由到網關的錯誤通道(如果指定)。 此路由由MessagePublishingErrorHandler執行,該MessagePublishingErrorHandler連接到ErrorHandlingTaskExecutor ,它包裝您的執行程序。

因為您將結果返回到網關然后繼續; 網關交互是“花費”的,沒有任何東西會收到發送到replyChannel標頭的消息(包括異常)。 因此,您看到的日志消息。

因此,一種解決方案是在發送到獨立流的消息上修復errorChannel頭。 使用.enrichHeaders替換(確保將覆蓋設置為true)網關設置的errorChannel標頭。 這應該在流程中盡快完成,因此任何異常都將路由到該通道(然后您可以在那里訂閱您的錯誤處理程序)。

另一種解決方案是連接您自己的錯誤處理執行程序,在其MessagePublishingErrorHandler上顯式設置defaultErrorChannel並刪除errorChannel標頭。

異步錯誤路由首先查找標頭; 如果存在,則錯誤消息在那里路由; 如果沒有標題,MPEH沒有默認的錯誤通道; 消息將被路由到默認的errorChannel ,其中(通常)訂閱了LoggingChannelAdapter 默認的errorChannel是一個發布/訂閱者通道,因此您可以為其訂閱其他端點。

編輯

您正在更改pub / sub之前的頻道。

獲得至少一個網關響應非常重要; 您應該將錯誤通道單獨留在pub / sub的一條腿上,並在第二條腿上更新它。 這樣,第一條腿上的異常將被拋給調用者(如果你想在那里采取一些動作,你可以向網關添加一個errorChannel ,例如路由到你的異常處理程序)。 您必須只更新第二個分支上的標題,以便它的異常直接發送到您的錯誤處理程序。

如果您將網關上的errorChannel設置為exceptionChannel那么兩條腿上的異常將會出現在那里。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM