AsyncHttpClient IOExceptionFilter异常过滤器

 更新时间:2023年12月13日 09:34:57   作者:codecraft  
这篇文章主要为大家介绍了AsyncHttpClient IOExceptionFilter异常过滤器代码流程解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

本文主要研究一下AsyncHttpClient的IOExceptionFilter

IOExceptionFilter

org/asynchttpclient/filter/IOExceptionFilter.java

/**
 * This filter is invoked when an {@link java.io.IOException} occurs during an http transaction.
 */
public interface IOExceptionFilter {
  /**
   * An {@link org.asynchttpclient.AsyncHttpClient} will invoke {@link IOExceptionFilter#filter} and will
   * use the returned {@link FilterContext} to replay the {@link org.asynchttpclient.Request} or abort the processing.
   *
   * @param ctx a {@link FilterContext}
   * @param <T> the handler result type
   * @return {@link FilterContext}. The {@link FilterContext} instance may not the same as the original one.
   * @throws FilterException to interrupt the filter processing.
   */
  <T> FilterContext<T> filter(FilterContext<T> ctx) throws FilterException;
}
IOExceptionFilter接口定义了filter方法,在捕获到IOException的时候执行

ResumableIOExceptionFilter

org/asynchttpclient/handler/resumable/ResumableIOExceptionFilter.java

/**
 * Simple {@link org.asynchttpclient.filter.IOExceptionFilter} that replay the current {@link org.asynchttpclient.Request} using a {@link ResumableAsyncHandler}
 */
public class ResumableIOExceptionFilter implements IOExceptionFilter {
  public <T> FilterContext<T> filter(FilterContext<T> ctx) {
    if (ctx.getIOException() != null && ctx.getAsyncHandler() instanceof ResumableAsyncHandler) {

      Request request = ResumableAsyncHandler.class.cast(ctx.getAsyncHandler()).adjustRequestRange(ctx.getRequest());

      return new FilterContext.FilterContextBuilder<>(ctx).request(request).replayRequest(true).build();
    }
    return ctx;
  }
}
ResumableIOExceptionFilter实现了IOExceptionFilter接口,它在asyncHandler是ResumableAsyncHandler类型的时候执行adjustRequestRange方法获取新的request,然后再通过new FilterContext.FilterContextBuilder<>(ctx).request(request).replayRequest(true).build()返回

ResumableAsyncHandler

org/asynchttpclient/handler/resumable/ResumableAsyncHandler.java

/**
   * Invoke this API if you want to set the Range header on your {@link Request} based on the last valid bytes
   * position.
   *
   * @param request {@link Request}
   * @return a {@link Request} with the Range header properly set.
   */
  public Request adjustRequestRange(Request request) {
    Long ri = resumableIndex.get(request.getUrl());
    if (ri != null) {
      byteTransferred.set(ri);
    }
    // The Resumable
    if (resumableListener != null && resumableListener.length() > 0 && byteTransferred.get() != resumableListener.length()) {
      byteTransferred.set(resumableListener.length());
    }
    RequestBuilder builder = new RequestBuilder(request);
    if (request.getHeaders().get(RANGE) == null && byteTransferred.get() != 0) {
      builder.setHeader(RANGE, "bytes=" + byteTransferred.get() + "-");
    }
    return builder.build();
  }
adjustRequestRange方法在byteTransferred不等于resumableListener.length()的时候会重置byteTransferred,对于有range的header则重置其bytes参数值

ResponseFiltersInterceptor

org/asynchttpclient/netty/handler/intercept/ResponseFiltersInterceptor.java

public boolean exitAfterProcessingFilters(Channel channel,
                                            NettyResponseFuture<?> future,
                                            AsyncHandler<?> handler,
                                            HttpResponseStatus status,
                                            HttpHeaders responseHeaders) {
    FilterContext fc = new FilterContext.FilterContextBuilder().asyncHandler(handler).request(future.getCurrentRequest()).responseStatus(status)
            .responseHeaders(responseHeaders).build();
    for (ResponseFilter asyncFilter : config.getResponseFilters()) {
      try {
        fc = asyncFilter.filter(fc);
        // FIXME Is it worth protecting against this?
        assertNotNull("fc", "filterContext");
      } catch (FilterException efe) {
        requestSender.abort(channel, future, efe);
      }
    }
    // The handler may have been wrapped.
    future.setAsyncHandler(fc.getAsyncHandler());
    // The request has changed
    if (fc.replayRequest()) {
      requestSender.replayRequest(future, fc, channel);
      return true;
    }
    return false;
  }
ResponseFiltersInterceptor的exitAfterProcessingFilters方法,对于fc.replayRequest()为true则执行requestSender.replayRequest(future, fc, channel)

replayRequest

org/asynchttpclient/netty/request/NettyRequestSender.java

public void replayRequest(final NettyResponseFuture<?> future, FilterContext fc, Channel channel) {

    Request newRequest = fc.getRequest();
    future.setAsyncHandler(fc.getAsyncHandler());
    future.setChannelState(ChannelState.NEW);
    future.touch();

    LOGGER.debug("\n\nReplaying Request {}\n for Future {}\n", newRequest, future);
    try {
      future.getAsyncHandler().onRetry();
    } catch (Exception e) {
      LOGGER.error("onRetry crashed", e);
      abort(channel, future, e);
      return;
    }

    channelManager.drainChannelAndOffer(channel, future);
    sendNextRequest(newRequest, future);
  }
NettyRequestSender的replayRequest方法会触发future.getAsyncHandler().onRetry()回调,然后执行channelManager.drainChannelAndOffer(channel, future)及sendNextRequest

applyIoExceptionFiltersAndReplayRequest

org/asynchttpclient/netty/request/NettyRequestSender.java

public boolean applyIoExceptionFiltersAndReplayRequest(NettyResponseFuture<?> future, IOException e,
                                                         Channel channel) {
    boolean replayed = false;
    @SuppressWarnings({"unchecked", "rawtypes"})
    FilterContext<?> fc = new FilterContext.FilterContextBuilder().asyncHandler(future.getAsyncHandler())
            .request(future.getCurrentRequest()).ioException(e).build();
    for (IOExceptionFilter asyncFilter : config.getIoExceptionFilters()) {
      try {
        fc = asyncFilter.filter(fc);
        assertNotNull(fc, "filterContext");
      } catch (FilterException efe) {
        abort(channel, future, efe);
      }
    }
    if (fc.replayRequest() && future.incrementRetryAndCheck() && future.isReplayPossible()) {
      future.setKeepAlive(false);
      replayRequest(future, fc, channel);
      replayed = true;
    }
    return replayed;
  }
NettyRequestSender的applyIoExceptionFiltersAndReplayRequest方法会遍历config.getIoExceptionFilters(),然后挨个执行fc = asyncFilter.filter(fc)

小结

AsyncHttpClient的IOExceptionFilter接口定义了filter方法,在捕获到IOException的时候执行;

ResumableIOExceptionFilter实现了IOExceptionFilter接口,它在asyncHandler是ResumableAsyncHandler类型的时候执行adjustRequestRange方法获取新的request,然后再通过new FilterContext.FilterContextBuilder<>(ctx).request(request).replayRequest(true).build()返回;

NettyRequestSender的replayRequest方法会触发future.getAsyncHandler().onRetry()回调,然后执行channelManager.drainChannelAndOffer(channel, future)及sendNextRequest。

以上就是AsyncHttpClient IOExceptionFilter异常过滤器的详细内容,更多关于AsyncHttpClient IOExceptionFilter的资料请关注脚本之家其它相关文章!

相关文章

  • Spring Security整合KeyCloak保护Rest API实现详解

    Spring Security整合KeyCloak保护Rest API实现详解

    这篇文章主要为大家介绍了Spring Security整合KeyCloak保护Rest API实现实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • Java 多线程并发 ReentrantReadWriteLock详情

    Java 多线程并发 ReentrantReadWriteLock详情

    这篇文章主要介绍了Java多线程并发ReentrantReadWriteLock详情,ReentrantReadWriteLock可重入读写锁。实际使用场景中,我们需要处理的操作本质上是读与写,更多相关资料,感兴趣的小伙伴可以参考一下下面文章内容
    2022-06-06
  • 使用jmx exporter采集kafka指标示例详解

    使用jmx exporter采集kafka指标示例详解

    这篇文章主要为大家介绍了使用jmx exporter采集kafka指标示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • Java框架Struts2实现图片上传功能

    Java框架Struts2实现图片上传功能

    这篇文章主要为大家详细介绍了Java框架Struts2实现图片上传功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • Java设计模式常用原则解析

    Java设计模式常用原则解析

    这篇文章主要介绍了Java设计模式常用原则解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • Java获取时间差(天数差,小时差,分钟差)代码示例

    Java获取时间差(天数差,小时差,分钟差)代码示例

    这篇文章主要介绍了Java获取时间差(天数差,小时差,分钟差)代码示例,使用SimpleDateFormat来实现的相关代码,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • Java 实现多线程的几种方式汇总

    Java 实现多线程的几种方式汇总

    JAVA多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。
    2016-03-03
  • java 较大数据量取差集,list.removeAll性能优化详解

    java 较大数据量取差集,list.removeAll性能优化详解

    这篇文章主要介绍了java 较大数据量取差集,list.removeAll性能优化详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • springBoot整合rabbitmq测试常用模型小结

    springBoot整合rabbitmq测试常用模型小结

    这篇文章主要介绍了springBoot整合rabbitmq并测试五种常用模型,本文主要针对前五种常用模型,在spirngboot框架的基础上整合rabbitmq并进行测试使用,需要的朋友可以参考下
    2022-01-01
  • JAVA 枚举相关知识汇总

    JAVA 枚举相关知识汇总

    这篇文章主要介绍了JAVA 枚举相关知识,文中讲解的非常详细,代码帮助大家更好的参考和学习,感兴趣的朋友可以了解下
    2020-06-06

最新评论