聊聊AsyncHttpClient的exception

2023-12-10 22:28:18 浏览数 (2)

本文主要研究一下AsyncHttpClient的exception

ChannelClosedException

org/asynchttpclient/exception/ChannelClosedException.java

代码语言:javascript复制
public final class ChannelClosedException extends IOException {

  public static final ChannelClosedException INSTANCE = unknownStackTrace(new ChannelClosedException(), ChannelClosedException.class, "INSTANCE");

  private ChannelClosedException() {
    super("Channel closed");
  }
}

ChannelClosedException用于表示Channel closed的异常

handleUnexpectedClosedChannel

org/asynchttpclient/netty/request/NettyRequestSender.java

代码语言:javascript复制
  public void handleUnexpectedClosedChannel(Channel channel, NettyResponseFuture<?> future) {
    if (Channels.isActiveTokenSet(channel)) {
      if (future.isDone()) {
        channelManager.closeChannel(channel);
      } else if (future.incrementRetryAndCheck() && retry(future)) {
        future.pendingException = null;
      } else {
        abort(channel, future,
                future.pendingException != null ? future.pendingException : RemotelyClosedException.INSTANCE);
      }
    }
  }

NettyRequestSender定义了handleUnexpectedClosedChannel方法,它会关闭或abort当前的channel

PoolAlreadyClosedException

org/asynchttpclient/exception/PoolAlreadyClosedException.java

代码语言:javascript复制
public class PoolAlreadyClosedException extends IOException {

  public static final PoolAlreadyClosedException INSTANCE = unknownStackTrace(new PoolAlreadyClosedException(), PoolAlreadyClosedException.class, "INSTANCE");

  private PoolAlreadyClosedException() {
    super("Pool is already closed");
  }
}

PoolAlreadyClosedException用于表示连接池已经关闭的异常

sendRequestWithNewChannel

org/asynchttpclient/netty/request/NettyRequestSender.java

代码语言:javascript复制
  private <T> ListenableFuture<T> sendRequestWithNewChannel(Request request,
                                                            ProxyServer proxy,
                                                            NettyResponseFuture<T> future,
                                                            AsyncHandler<T> asyncHandler) {

    // some headers are only set when performing the first request
    HttpHeaders headers = future.getNettyRequest().getHttpRequest().headers();
    Realm realm = future.getRealm();
    Realm proxyRealm = future.getProxyRealm();
    requestFactory.addAuthorizationHeader(headers, perConnectionAuthorizationHeader(request, proxy, realm));
    requestFactory.setProxyAuthorizationHeader(headers, perConnectionProxyAuthorizationHeader(request, proxyRealm));

    future.setInAuth(realm != null && realm.isUsePreemptiveAuth() && realm.getScheme() != AuthScheme.NTLM);
    future.setInProxyAuth(
            proxyRealm != null && proxyRealm.isUsePreemptiveAuth() && proxyRealm.getScheme() != AuthScheme.NTLM);

    try {
      if (!channelManager.isOpen()) {
        throw PoolAlreadyClosedException.INSTANCE;
      }

      // Do not throw an exception when we need an extra connection for a
      // redirect.
      future.acquirePartitionLockLazily();
    } catch (Throwable t) {
      abort(null, future, getCause(t));
      // exit and don't try to resolve address
      return future;
    }

    //......
}    

sendRequestWithNewChannel在channelManager非open的时候会抛出PoolAlreadyClosedException

RemotelyClosedException

org/asynchttpclient/exception/RemotelyClosedException.java

代码语言:javascript复制
public final class RemotelyClosedException extends IOException {

  public static final RemotelyClosedException INSTANCE = unknownStackTrace(new RemotelyClosedException(), RemotelyClosedException.class, "INSTANCE");

  RemotelyClosedException() {
    super("Remotely closed");
  }
}

RemotelyClosedException用于表示Remotely closed的异常

handleUnexpectedClosedChannel

org/asynchttpclient/netty/request/NettyRequestSender.java

代码语言:javascript复制
  public void handleUnexpectedClosedChannel(Channel channel, NettyResponseFuture<?> future) {
    if (Channels.isActiveTokenSet(channel)) {
      if (future.isDone()) {
        channelManager.closeChannel(channel);
      } else if (future.incrementRetryAndCheck() && retry(future)) {
        future.pendingException = null;
      } else {
        abort(channel, future,
                future.pendingException != null ? future.pendingException : RemotelyClosedException.INSTANCE);
      }
    }
  }

NettyRequestSender的handleUnexpectedClosedChannel的时候,对于future未完成也没有重试的时候会执行abort,并抛出RemotelyClosedException

TooManyConnectionsException

org/asynchttpclient/exception/TooManyConnectionsException.java

代码语言:javascript复制
public class TooManyConnectionsException extends IOException {

  public TooManyConnectionsException(int max) {
    super("Too many connections: "   max);
  }
}

TooManyConnectionsException用于表示全局连接超过限制的异常

TooManyConnectionsPerHostException

org/asynchttpclient/exception/TooManyConnectionsPerHostException.java

代码语言:javascript复制
public class TooManyConnectionsPerHostException extends IOException {

  public TooManyConnectionsPerHostException(int max) {
    super("Too many connections: "   max);
  }
}

TooManyConnectionsPerHostException用于表示连接超出单host限制的异常

acquireChannelLock

org/asynchttpclient/netty/channel/ConnectionSemaphore.java

代码语言:javascript复制
  public void acquireChannelLock(Object partitionKey) throws IOException {
    if (!tryAcquireGlobal())
      throw tooManyConnections;
    if (!tryAcquirePerHost(partitionKey)) {
      freeChannels.release();

      throw tooManyConnectionsPerHost;
    }
  }

acquireChannelLock方法在全局连接超出限制时抛出tooManyConnections,在单host连接超出限制时抛出tooManyConnectionsPerHost

小结

AsyncHttpClient一共定义了五个异常,它们都继承了IOException,分别是ChannelClosedException、PoolAlreadyClosedException、RemotelyClosedException、TooManyConnectionsException、TooManyConnectionsPerHostException。

0 人点赞