Skip to content

Commit

Permalink
apply pull alibaba#6441 to avoid IO reactor stopped
Browse files Browse the repository at this point in the history
  • Loading branch information
zrlw committed Dec 13, 2021
1 parent b646b97 commit aa2f3c9
Showing 1 changed file with 86 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,33 @@

package com.alibaba.nacos.common.http;

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.nio.conn.NHttpClientConnectionManager;
import org.apache.http.nio.conn.NoopIOSessionStrategy;
import org.apache.http.nio.conn.SchemeIOSessionStrategy;
import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;
import org.apache.http.nio.reactor.IOReactorException;
import org.apache.http.nio.reactor.IOReactorExceptionHandler;
import org.apache.http.protocol.RequestContent;
import org.apache.http.ssl.SSLContexts;
import org.slf4j.Logger;

import com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.http.client.request.DefaultAsyncHttpClientRequest;
Expand All @@ -25,18 +52,6 @@
import com.alibaba.nacos.common.tls.TlsHelper;
import com.alibaba.nacos.common.tls.TlsSystemConfig;
import com.alibaba.nacos.common.utils.BiConsumer;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.protocol.RequestContent;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.slf4j.Logger;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;

/**
* AbstractHttpClientFactory Let the creator only specify the http client config.
Expand Down Expand Up @@ -77,7 +92,65 @@ public NacosAsyncRestTemplate createNacosAsyncRestTemplate() {
.setDefaultRequestConfig(getRequestConfig())
.setMaxConnTotal(originalRequestConfig.getMaxConnTotal())
.setMaxConnPerRoute(originalRequestConfig.getMaxConnPerRoute())
.setUserAgent(originalRequestConfig.getUserAgent()).build()));
.setUserAgent(originalRequestConfig.getUserAgent())
.setConnectionManager(getConnectionManager(originalRequestConfig))
.build()));
}

/**
* create the {@link NHttpClientConnectionManager}, the code mainly from {@link HttpAsyncClientBuilder#build()}.
* we add the {@link IOReactorExceptionHandler} to handle the {@link IOException} and {@link RuntimeException}
* thrown by the {@link org.apache.http.impl.nio.reactor.BaseIOReactor} when process the event of Network.
* Using this way to avoid the {@link DefaultConnectingIOReactor} killed by unknown error of network.
*
* @param originalRequestConfig request config.
* @return {@link NHttpClientConnectionManager}.
*/
private NHttpClientConnectionManager getConnectionManager(HttpClientConfig originalRequestConfig) {
SSLContext sslcontext = SSLContexts.createDefault();
HostnameVerifier hostnameVerifier = new DefaultHostnameVerifier();
SchemeIOSessionStrategy sslStrategy = new SSLIOSessionStrategy(sslcontext, null, null, hostnameVerifier);

final DefaultConnectingIOReactor ioreactor;
try {
ioreactor = new DefaultConnectingIOReactor(getIoReactorConfig());
} catch (IOReactorException e) {
assignLogger().error("[NHttpClientConnectionManager] Create DefaultConnectingIOReactor failed", e);
throw new IllegalStateException();
}

// if the handle return true, then the exception thrown by IOReactor will be ignore, and will not finish the IOReactor.
ioreactor.setExceptionHandler(new IOReactorExceptionHandler() {

@Override
public boolean handle(IOException ex) {
assignLogger().warn("[NHttpClientConnectionManager] handle IOException, ignore it.", ex);
return true;
}

@Override
public boolean handle(RuntimeException ex) {
assignLogger().warn("[NHttpClientConnectionManager] handle RuntimeException, ignore it.", ex);
return true;
}
});

Registry<SchemeIOSessionStrategy> registry = RegistryBuilder.<SchemeIOSessionStrategy>create()
.register("http", NoopIOSessionStrategy.INSTANCE)
.register("https", sslStrategy)
.build();
final PoolingNHttpClientConnectionManager poolingmgr = new PoolingNHttpClientConnectionManager(ioreactor, registry);

int maxTotal = originalRequestConfig.getMaxConnTotal();
if (maxTotal > 0) {
poolingmgr.setMaxTotal(maxTotal);
}

int maxPerRoute = originalRequestConfig.getMaxConnPerRoute();
if (maxPerRoute > 0) {
poolingmgr.setDefaultMaxPerRoute(maxPerRoute);
}
return poolingmgr;
}

protected IOReactorConfig getIoReactorConfig() {
Expand Down

0 comments on commit aa2f3c9

Please sign in to comment.