You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Apache Camel配置异步Web服务:仅当System B可用时触发路由

Nice work setting up the async decoupling with ActiveMQ so far! The problem you're facing—where the integrationToB route still tries to call System B even when it's offline—is a common one, and there are a few solid ways to fix this with Apache Camel. Let's break down the best approaches:

Circuit breakers monitor the success/failure rate of calls to System B, and "trip" (stop making calls) when B is unavailable. Once B recovers, the circuit automatically closes to resume processing.

First, add the Resilience4j Camel component dependency to your project. Then modify your integrationToB route to wrap the HTTP call with circuit breaker logic:

<camel:route id="integrationToB"> 
  <camel:from uri="activemq:requestqueue" /> 
  <camel:transacted /> 
  <camel:bean ref="afterQueueProcessor" /> 

  <!-- Configure circuit breaker to handle System B unavailability -->
  <camel:resilience4jCircuitBreaker id="systemBCircuitBreaker"
      failureRateThreshold="50"
      waitDurationInOpenState="10000"
      permittedNumberOfCallsInHalfOpenState="3"
      slidingWindowSize="10">
    <camel:setHeader headerName="CamelHttpMethod"> 
      <camel:constant>POST</camel:constant> 
    </camel:setHeader> 
    <camel:setHeader headerName="Content-Type"> 
      <camel:constant>application/x-www-form-urlencoded</camel:constant> 
    </camel:setHeader> 
    <camel:to uri="http://localhost:8080/systemB/newOrder?test=testData" /> 
  </camel:resilience4jCircuitBreaker>

  <!-- Requeue messages when circuit is open instead of sending to DLQ -->
  <camel:onException>
    <camel:exception>io.github.resilience4j.circuitbreaker.CallNotPermittedException</camel:exception>
    <camel:delay>
      <camel:simple>15000</camel:simple> <!-- 15-second delay before retry -->
    </camel:delay>
    <camel:inOnly uri="activemq:requestqueue" />
    <camel:handled>
      <camel:constant>true</camel:constant>
    </camel:handled>
  </camel:onException>
</camel:route>

When the circuit opens (System B is down), messages are requeued with a delay instead of being sent to the dead letter queue. Once B recovers, the circuit closes and processing resumes.

2. Add a Pre-Call Health Check

Add a lightweight check to verify System B's availability before making the actual POST request. Use a health endpoint (like /health) on System B for this:

<camel:route id="integrationToB"> 
  <camel:from uri="activemq:requestqueue" /> 
  <camel:transacted /> 
  <camel:bean ref="afterQueueProcessor" /> 

  <!-- Check if System B is reachable first -->
  <camel:choice>
    <camel:when>
      <camel:simple>${header.CamelHttpResponseCode} == 200</camel:simple>
      <camel:to uri="http://localhost:8080/systemB/health?httpMethod=HEAD" />
      <!-- Proceed with order request if B is healthy -->
      <camel:setHeader headerName="CamelHttpMethod"> 
        <camel:constant>POST</camel:constant> 
      </camel:setHeader> 
      <camel:setHeader headerName="Content-Type"> 
        <camel:constant>application/x-www-form-urlencoded</camel:constant> 
      </camel:setHeader> 
      <camel:to uri="http://localhost:8080/systemB/newOrder?test=testData" /> 
    </camel:when>
    <camel:otherwise>
      <!-- Requeue message with delay if B is unavailable -->
      <camel:delay>
        <camel:simple>20000</camel:simple> <!-- 20-second delay -->
      </camel:delay>
      <camel:inOnly uri="activemq:requestqueue" />
    </camel:otherwise>
  </camel:choice>
</camel:route>

Ensure System B has a simple /health endpoint that returns a 200 OK status when it's ready to handle requests.

3. Dynamic Route Control with Camel Health Checks

Use Camel's camel-health component to monitor System B's status and dynamically start/stop the integrationToB route.

First, create a custom health check bean:

@Component
public class SystemBHealthCheck extends AbstractHealthCheck {

    @Override
    protected void doCall(HealthCheckResultBuilder builder, Map<String, Object> options) {
        try (CloseableHttpClient client = HttpClients.createDefault()) {
            HttpHead request = new HttpHead("http://localhost:8080/systemB/health");
            HttpResponse response = client.execute(request);
            if (response.getStatusLine().getStatusCode() == 200) {
                builder.up();
            } else {
                builder.down().detail("statusCode", response.getStatusLine().getStatusCode());
            }
        } catch (IOException e) {
            builder.down().detail("error", e.getMessage());
        }
    }
}

Then add a monitoring route to control the integrationToB route:

<camel:route id="healthMonitorRoute">
  <camel:from uri="health-check:systemBHealthCheck?frequency=30000" /> <!-- Check every 30 seconds -->
  <camel:choice>
    <camel:when>
      <camel:simple>${body.state} == 'UP'</camel:simple>
      <camel:to uri="controlbus:route?routeId=integrationToB&action=start" />
    </camel:when>
    <camel:otherwise>
      <camel:to uri="controlbus:route?routeId=integrationToB&action=stop" />
    </camel:otherwise>
  </camel:choice>
</camel:route>

This stops the integrationToB route when System B is down (so it won't consume queue messages) and restarts it once B is back online.

Bonus: Tune ActiveMQ Redelivery Policies

Complement the above solutions by configuring ActiveMQ to avoid fast DLQ routing:

<bean id="activemq" class="org.apache.camel.component.activemq.ActiveMQComponent">
  <property name="connectionFactory">
    <bean class="org.apache.activemq.ActiveMQConnectionFactory">
      <property name="brokerURL" value="tcp://localhost:61616" />
      <property name="redeliveryPolicy">
        <bean class="org.apache.activemq.RedeliveryPolicy">
          <property name="maximumRedeliveries" value="5" />
          <property name="initialRedeliveryDelay" value="5000" />
          <property name="redeliveryDelay" value="10000" />
          <property name="useExponentialBackOff" value="true" />
        </bean>
      </property>
    </bean>
  </property>
</bean>

This adds increasing delays between retries before messages reach the DLQ.

内容的提问来源于stack exchange,提问作者Gajendra Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:48:55