AsyncHttpClient KeepAliveStrategy源码流程解读

 更新时间:2023年12月12日 08:35:19   作者:codecraft  
这篇文章主要为大家介绍了AsyncHttpClient KeepAliveStrategy源码流程解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

本文主要研究一下AsyncHttpClient的KeepAliveStrategy

KeepAliveStrategy

org/asynchttpclient/channel/KeepAliveStrategy.java

public interface KeepAliveStrategy {

  /**
   * Determines whether the connection should be kept alive after this HTTP message exchange.
   *
   * @param ahcRequest    the Request, as built by AHC
   * @param nettyRequest  the HTTP request sent to Netty
   * @param nettyResponse the HTTP response received from Netty
   * @return true if the connection should be kept alive, false if it should be closed.
   */
  boolean keepAlive(Request ahcRequest, HttpRequest nettyRequest, HttpResponse nettyResponse);
}
KeepAliveStrategy接口定义了keepAlive方法用于决定是否对该connection进行keep alive

DefaultKeepAliveStrategy

org/asynchttpclient/channel/DefaultKeepAliveStrategy.java

/**
 * Connection strategy implementing standard HTTP 1.0/1.1 behavior.
 */
public class DefaultKeepAliveStrategy implements KeepAliveStrategy {

  /**
   * Implemented in accordance with RFC 7230 section 6.1 https://tools.ietf.org/html/rfc7230#section-6.1
   */
  @Override
  public boolean keepAlive(Request ahcRequest, HttpRequest request, HttpResponse response) {
    return HttpUtil.isKeepAlive(response)
            && HttpUtil.isKeepAlive(request)
            // support non standard Proxy-Connection
            && !response.headers().contains("Proxy-Connection", CLOSE, true);
  }
}
DefaultKeepAliveStrategy实现了KeepAliveStrategy接口,其keepAlive方法判根据HTTP 1.0/1.1协议的规定进行判断,需要request、response都是keep alive,且response header不包含Proxy-Connection: close才返回true

HttpUtil

io/netty/handler/codec/http/HttpUtil.java

/**
     * Returns {@code true} if and only if the connection can remain open and
     * thus 'kept alive'.  This methods respects the value of the.
     *
     * {@code "Connection"} header first and then the return value of
     * {@link HttpVersion#isKeepAliveDefault()}.
     */
    public static boolean isKeepAlive(HttpMessage message) {
        return !message.headers().containsValue(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE, true) &&
               (message.protocolVersion().isKeepAliveDefault() ||
                message.headers().containsValue(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE, true));
    }
isKeepAlive方法在HttpMessage没有connection: close的header,且http协议默认keep alive或者header包含了connection: keep-alive才返回true

handleHttpResponse

org/asynchttpclient/netty/handler/HttpHandler.java

private void handleHttpResponse(final HttpResponse response, final Channel channel, final NettyResponseFuture<?> future, AsyncHandler<?> handler) throws Exception {
    HttpRequest httpRequest = future.getNettyRequest().getHttpRequest();
    logger.debug("\n\nRequest {}\n\nResponse {}\n", httpRequest, response);
    future.setKeepAlive(config.getKeepAliveStrategy().keepAlive(future.getTargetRequest(), httpRequest, response));
    NettyResponseStatus status = new NettyResponseStatus(future.getUri(), response, channel);
    HttpHeaders responseHeaders = response.headers();
    if (!interceptors.exitAfterIntercept(channel, future, handler, response, status, responseHeaders)) {
      boolean abort = abortAfterHandlingStatus(handler, status) || //
              abortAfterHandlingHeaders(handler, responseHeaders) || //
              abortAfterHandlingReactiveStreams(channel, future, handler);
      if (abort) {
        finishUpdate(future, channel, true);
      }
    }
  }
HttpHandler的handleHttpResponse方法会通过KeepAliveStrategy的keepAlive来判断是否需要keep alive,然后写入到NettyResponseFuture中

exitAfterHandlingConnect

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

public boolean exitAfterHandlingConnect(Channel channel,
                                          NettyResponseFuture<?> future,
                                          Request request,
                                          ProxyServer proxyServer) {
    if (future.isKeepAlive())
      future.attachChannel(channel, true);
    Uri requestUri = request.getUri();
    LOGGER.debug("Connecting to proxy {} for scheme {}", proxyServer, requestUri.getScheme());
    channelManager.updatePipelineForHttpTunneling(channel.pipeline(), requestUri);
    future.setReuseChannel(true);
    future.setConnectAllowed(false);
    requestSender.drainChannelAndExecuteNextRequest(channel, future, new RequestBuilder(future.getTargetRequest()).build());
    return true;
  }
exitAfterHandlingConnect方法在NettyResponseFuture的keep alive为true时执行future.attachChannel(channel, true)

attachChannel

org/asynchttpclient/netty/NettyResponseFuture.java

public void attachChannel(Channel channel, boolean reuseChannel) {
    // future could have been cancelled first
    if (isDone()) {
      Channels.silentlyCloseChannel(channel);
    }
    this.channel = channel;
    this.reuseChannel = reuseChannel;
  }
  public boolean isReuseChannel() {
    return reuseChannel;
  }
attachChannel这里维护了reuseChannel属性

getOpenChannel

org/asynchttpclient/netty/request/NettyRequestSender.java

private Channel getOpenChannel(NettyResponseFuture<?> future, Request request, ProxyServer proxyServer,
                                 AsyncHandler<?> asyncHandler) {
    if (future != null && future.isReuseChannel() && Channels.isChannelActive(future.channel())) {
      return future.channel();
    } else {
      return pollPooledChannel(request, proxyServer, asyncHandler);
    }
  }
  private Channel pollPooledChannel(Request request, ProxyServer proxy, AsyncHandler<?> asyncHandler) {
    try {
      asyncHandler.onConnectionPoolAttempt();
    } catch (Exception e) {
      LOGGER.error("onConnectionPoolAttempt crashed", e);
    }
    Uri uri = request.getUri();
    String virtualHost = request.getVirtualHost();
    final Channel channel = channelManager.poll(uri, virtualHost, proxy, request.getChannelPoolPartitioning());
    if (channel != null) {
      LOGGER.debug("Using pooled Channel '{}' for '{}' to '{}'", channel, request.getMethod(), uri);
    }
    return channel;
  }
getOpenChannel先判断NettyResponseFuture是否是reuse的,以及是否active,若是则直接返回future.channel(),否则通过pollPooledChannel从连接池中获取

小结

AsyncHttpClient的KeepAliveStrategy定义了keepAlive方法用于决定是否对该connection进行keep alive;HttpHandler的handleHttpResponse方法会通过KeepAliveStrategy的keepAlive来判断是否需要keep alive,然后写入到NettyResponseFuture中;getOpenChannel先判断NettyResponseFuture是否是reuse的,以及是否active,若是则直接返回future.channel(),否则通过pollPooledChannel从连接池中获取。

以上就是AsyncHttpClient KeepAliveStrategy源码流程解读的详细内容,更多关于AsyncHttpClient KeepAliveStrategy的资料请关注脚本之家其它相关文章!

相关文章

  • SpringBoot 回滚操作的几种实现方式

    SpringBoot 回滚操作的几种实现方式

    回滚操作是一种常见的操作,用于撤销之前执行的操作,本文主要介绍了SpringBoot回滚操作的几种实现方式,包含基于异常类型的回滚、基于自定义逻辑的回滚和基于数据库状态的回滚,感兴趣的可以了解一下
    2024-03-03
  • Java如何生成4位、6位随机数短信验证码(高效实现)

    Java如何生成4位、6位随机数短信验证码(高效实现)

    这篇文章主要介绍了Java如何生成4位、6位随机数短信验证码(高效实现),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • java实现简单注册选择所在城市

    java实现简单注册选择所在城市

    这篇文章主要为大家详细介绍了java实现简单注册选择所在城市的相关代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-04-04
  • Springboot中项目的属性配置的详细介绍

    Springboot中项目的属性配置的详细介绍

    很多时候需要用到一些配置的信息,这些信息可能在测试环境和生产环境下会有不同的配置,本文主要介绍了Springboot中项目的属性配置的详细介绍,感兴趣的可以了解一下
    2022-01-01
  • Java中的NoSuchMethodException异常原因以及解决方案详解

    Java中的NoSuchMethodException异常原因以及解决方案详解

    这篇文章主要介绍了Java中的NoSuchMethodException异常原因以及解决方案详解,NoSuchMethodException是Java反射机制中的异常,在尝试通过反射获取方法时,找不到指定的方法,通常发生在调用 Class 对象的方法时,当方法名或方法参数不匹配时抛出该异常,需要的朋友可以参考下
    2024-02-02
  • MyBatis SELECT基本查询实现方法详解

    MyBatis SELECT基本查询实现方法详解

    这篇文章主要介绍了MyBatis SELECT基本查询实现方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • Spring中的BeanFactory工厂详细解析

    Spring中的BeanFactory工厂详细解析

    这篇文章主要介绍了Spring中的BeanFactory工厂详细解析,Spring的本质是一个bean工厂(beanFactory)或者说bean容器,它按照我们的要求,生产我们需要的各种各样的bean,提供给我们使用,需要的朋友可以参考下
    2023-12-12
  • Java用 Rhino/Nashorn 代替第三方 JSON 转换库

    Java用 Rhino/Nashorn 代替第三方 JSON 转换库

    本篇文章主要介绍了Java用 Rhino/Nashorn 代替第三方 JSON 转换库,非常具有实用价值,需要的朋友可以参考下
    2017-05-05
  • 浅谈Java中Properties类的详细使用

    浅谈Java中Properties类的详细使用

    properties类继承自hashtable,通常和io流结合使用。它最突出的特点是将key/value作为配置属性写入到配置文件中以实现配置持久化,或从配置文件中读取这些属性。它的这些配置文件的规范后缀名为".properties"。表示了一个持久的属性集
    2021-06-06
  • Sa-Token不同模式实现单地登录 多地登录 同端互斥登录

    Sa-Token不同模式实现单地登录 多地登录 同端互斥登录

    这篇文章主要为大家介绍了Sa-Token不同模式实现单地登录 多地登录 同端互斥登录,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07

最新评论