代码之家  ›  专栏  ›  技术社区  ›  Tom

int http的请求-响应延迟时间:出站网关

  •  1
  • Tom  · 技术社区  · 6 年前

    我想使用在Spring集成中设置的API请求计时。响应时间应作为消息头添加,以便可以在下游进行审核,并与其他数据一起记录。

    HTTP成功和错误响应都应该计时,例如,我想知道服务器发出500响应需要多长时间。我也已经在使用重试和断路器建议(因为我想要这个功能)。

    我已经写了一个定制建议(来自 reading the docs )并添加到我的:

    public class RequestResponseTimeInterceptor extends AbstractRequestHandlerAdvice {
    
    private static final Logger LOG = Logger.getLogger(RequestResponseTimeInterceptor.class);
    
    
    protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) throws Exception {
        long before = System.currentTimeMillis();
    
        try {
            Object result = callback.execute();
    
            long after = System.currentTimeMillis();
            message = MessageBuilder.fromMessage(message).setHeader("requestResponseTime", after - before).build();
    
            return result;
        }
        catch (MessageHandlingException e) {
            long after = System.currentTimeMillis();
            Message modifiedFailedMessage = MessageBuilder.fromMessage(e.getFailedMessage()).setHeader("requestResponseTime", after - before).build();
    
            throw new MessageHandlingException(modifiedFailedMessage, e.getMessage(), e.getCause());
        }
    }
    
    
    <bean id="calculationRetry" class="org.springframework.integration.handler.advice.RequestHandlerRetryAdvice"/>
    <bean id="calculationCircuitBreaker" class="org.springframework.integration.handler.advice.RequestHandlerCircuitBreakerAdvice"/>
    <bean id="timer" class="com.integration.audit.RequestResponseTimeInterceptor"/>
    
    <int-http:request-handler-advice-chain>
            <ref bean="timer"/>
            <ref bean="calculationRetry"/>
            <ref bean="calculationCircuitBreaker"/>
    </int-http:request-handler-advice-chain>
    

    它通过回调执行之间的计时来工作。我有一个问题,失败的HTTP响应(例如HTTP 500)被包装在MessageHandlingException中(在Spring集成中,根据设计),这会阻止其余的建议完成响应并计时。

    我在代码示例中解决了这个问题,捕获异常,将响应时间添加为消息头,重新创建异常并抛出它(因此它会被我的错误通道拾取)。这似乎效果不错,但感觉这不是最好的解决方案。它还将乘以任何重试(根据我的重试建议)的完整持续时间,而不是上次重试的时间。

    有没有更好的方法来计时HTTP请求/响应,这样可以很好地处理现有的重试建议和失败的HTTP响应代码?

    感谢您的反馈!

    编辑:基于Artem的信息。

    请求处理程序建议链中建议的顺序很重要(毕竟它是一个有序链)。因此,将“计时器”放在链的末尾意味着它只对请求/响应进行计时,而不是多次重试或断路。

    我根据Artem的评论更新了建议,所以现在它实际上返回了一条消息。然后,我可以根据需要在管道下游读取新的“requestResponseTime”头。

    以下是新代码:

    public class RequestResponseTimeInterceptor extends AbstractRequestHandlerAdvice {
    
    private static final Logger LOG = Logger.getLogger(RequestResponseTimeInterceptor.class);
    
    protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> requestMessage) throws Exception {
        long before = System.currentTimeMillis();
    
        try {
            Object result = callback.execute();
    
            long after = System.currentTimeMillis();
    
            Message<?> responseMessage = (Message<?>) result;
    
            return MessageBuilder.withPayload(responseMessage.getPayload())
                                .setHeader(MessageHeaderConstants.REQUEST_RESPONSE_TIME, after - before).build();
        }
        catch (MessageHandlingException e) {
            //Catch HTTP errors (e.g. 500s) so we can also time the response
            long after = System.currentTimeMillis();
            Message modifiedFailedMessage = MessageBuilder.fromMessage(e.getFailedMessage()).setHeader(MessageHeaderConstants.REQUEST_RESPONSE_TIME, after - before).build();
    
            //rethrow new exception for error handling
            throw new MessageHandlingException(modifiedFailedMessage, e.getMessage(), e.getCause());
        }
    }
    
    
    
        <int-http:request-handler-advice-chain>
            <ref bean="calculationCircuitBreaker"/>
            <ref bean="calculationRetry"/>
            <ref bean="timer"/>
        </int-http:request-handler-advice-chain>
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   Artem Bilan    6 年前

    首先,想想你的计时器是否真的应该包括所有的重试。对我来说,计算断路器打开的超时时间似乎没有什么价值。我的意思是,以不同的方式重新排列您的建议将是非常现实的:首先循环,然后重试,然后才计时。这样,您将只计算真正的http请求,而不会转到断路部分。

    关于您的例外问题。用所需的标题重建消息肯定没问题。为此,我们引入了 ErrorMessageStrategy : https://docs.spring.io/spring-integration/docs/latest-ga/reference/html/whats-new.html#_errormessagepublisher_and_errormessagestrategy

    另一方面,请注意Spring Cloud Sleuth项目: https://cloud.spring.io/spring-cloud-sleuth/