Skip to content

Commit

Permalink
[ISSUE alibaba#3094]abstract create nacos restTemplate factory (aliba…
Browse files Browse the repository at this point in the history
…ba#3095)

* abstract create nacos restTemplate factory, allowing users to customize the commonly used http client config

* add class file license.

* change class file name

* Adjust some code
  • Loading branch information
Maijh97 authored Jun 17, 2020
1 parent 3f401c9 commit e528ea8
Show file tree
Hide file tree
Showing 11 changed files with 450 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.nacos.client.naming.net;

import com.alibaba.nacos.common.http.*;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;

/**
* http Manager
*
* @author mai.jh
* @date 2020/6/14
*/
public class NamingHttpClientManager {

private static final int READ_TIME_OUT_MILLIS = Integer
.getInteger("com.alibaba.nacos.client.naming.rtimeout", 50000);
private static final int CON_TIME_OUT_MILLIS = Integer
.getInteger("com.alibaba.nacos.client.naming.ctimeout", 3000);
private static final boolean ENABLE_HTTPS = Boolean
.getBoolean("com.alibaba.nacos.client.naming.tls.enable");
private static final int MAX_REDIRECTS = 5;

private static final HttpClientFactory HTTP_CLIENT_FACTORY = new NamingHttpClientFactory();

public static String getPrefix() {
if (ENABLE_HTTPS) {
return "https://";
}
return "http://";
}

public static NacosRestTemplate getNacosRestTemplate() {
return HttpClientBeanHolder.getNacosRestTemplate(HTTP_CLIENT_FACTORY);
}

private static class NamingHttpClientFactory extends AbstractHttpClientFactory {

@Override
protected HttpClientConfig buildHttpClientConfig() {
return HttpClientConfig.builder()
.setConTimeOutMillis(CON_TIME_OUT_MILLIS)
.setReadTimeOutMillis(READ_TIME_OUT_MILLIS)
.setMaxRedirects(MAX_REDIRECTS).build();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,8 @@ public interface HttpHeaderConsts {
String ACCEPT_CHARSET = "Accept-Charset";
String ACCEPT_ENCODING = "Accept-Encoding";
String CONTENT_ENCODING = "Content-Encoding";
String CONNECTION = "Connection";
String REQUEST_ID = "RequestId";
String REQUEST_MODULE = "REQUEST_MODULE";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.nacos.common.http;

import com.alibaba.nacos.common.http.client.DefaultAsyncHttpClientRequest;
import com.alibaba.nacos.common.http.client.DefaultHttpClientRequest;
import com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.nio.client.HttpAsyncClients;

/**
* AbstractHttpClientFactory
* Let the creator only specify the http client config
*
* @author mai.jh
* @date 2020/6/15
*/
public abstract class AbstractHttpClientFactory implements HttpClientFactory {

@Override
public final NacosRestTemplate createNacosRestTemplate() {
RequestConfig requestConfig = getRequestConfig();
return new NacosRestTemplate(
new DefaultHttpClientRequest(
HttpClients.custom()
.setDefaultRequestConfig(requestConfig).build()));
}

@Override
public final NacosAsyncRestTemplate createNacosAsyncRestTemplate() {
RequestConfig requestConfig = getRequestConfig();
return new NacosAsyncRestTemplate(
new DefaultAsyncHttpClientRequest(
HttpAsyncClients.custom()
.setDefaultRequestConfig(requestConfig).build()));
}

private RequestConfig getRequestConfig() {
HttpClientConfig httpClientConfig = buildHttpClientConfig();
return RequestConfig.custom()
.setConnectTimeout(httpClientConfig.getConTimeOutMillis())
.setSocketTimeout(httpClientConfig.getReadTimeOutMillis())
.setMaxRedirects(httpClientConfig.getMaxRedirects())
.build();
}

/**
* build http client config
* @return HttpClientConfig
*/
protected abstract HttpClientConfig buildHttpClientConfig();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.nacos.common.http;

/**
* default http client factory
*
* @author mai.jh
* @date 2020/6/15
*/
public class DefaultHttpClientFactory extends AbstractHttpClientFactory {

private static final int TIMEOUT = Integer.getInteger("nacos.http.timeout", 5000);

@Override
protected HttpClientConfig buildHttpClientConfig() {
return HttpClientConfig.builder()
.setConTimeOutMillis(TIMEOUT)
.setReadTimeOutMillis(TIMEOUT >> 1)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.nacos.common.http;

import com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.utils.ExceptionUtil;
import com.alibaba.nacos.common.utils.ThreadUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

/**
* Create a rest template
* to ensure that each custom client config and rest template are in one-to-one correspondence
*
* @author mai.jh
* @date 2020/6/16
*/
@SuppressWarnings("all")
public final class HttpClientBeanHolder {

private static final Logger logger = LoggerFactory.getLogger(HttpClientManager.class);

private static final int TIMEOUT = Integer.getInteger("nacos.http.timeout", 5000);

private static HttpClientConfig HTTP_CLIENT_CONFIG = HttpClientConfig.builder()
.setConTimeOutMillis(TIMEOUT).setReadTimeOutMillis(TIMEOUT >> 1).build();

private static final Map<String, NacosRestTemplate> singletonRest = new HashMap<String, NacosRestTemplate>(10);
private static final Map<String, NacosAsyncRestTemplate> singletonAsyncRest = new HashMap<String, NacosAsyncRestTemplate>(10);

private static final AtomicBoolean alreadyShutdown = new AtomicBoolean(false);

static {
ThreadUtils.addShutdownHook(new Runnable() {
@Override
public void run() {
shutdown();
}
});
}

public static NacosRestTemplate getNacosRestTemplate() {
return getNacosRestTemplate(new DefaultHttpClientFactory());
}

public static NacosRestTemplate getNacosRestTemplate(HttpClientFactory httpClientFactory) {
if (httpClientFactory == null) {
throw new NullPointerException("httpClientFactory is null");
}
String factoryName = httpClientFactory.getClass().getName();
NacosRestTemplate nacosRestTemplate = singletonRest.get(factoryName);
if (nacosRestTemplate == null) {
synchronized (singletonRest) {
nacosRestTemplate = singletonRest.get(factoryName);
if (nacosRestTemplate != null) {
return nacosRestTemplate;
}
nacosRestTemplate = httpClientFactory.createNacosRestTemplate();
singletonRest.put(factoryName, nacosRestTemplate);
}
}
return nacosRestTemplate;
}

public static NacosAsyncRestTemplate getNacosAsyncRestTemplate() {
return getNacosAsyncRestTemplate(new DefaultHttpClientFactory());
}

public static NacosAsyncRestTemplate getNacosAsyncRestTemplate(HttpClientFactory httpClientFactory) {
if (httpClientFactory == null) {
throw new NullPointerException("httpClientFactory is null");
}
String factoryName = httpClientFactory.getClass().getName();
NacosAsyncRestTemplate nacosAsyncRestTemplate = singletonAsyncRest.get(factoryName);
if (nacosAsyncRestTemplate == null) {
synchronized (singletonAsyncRest) {
nacosAsyncRestTemplate = singletonAsyncRest.get(factoryName);
if (nacosAsyncRestTemplate != null) {
return nacosAsyncRestTemplate;
}
nacosAsyncRestTemplate = httpClientFactory.createNacosAsyncRestTemplate();
singletonAsyncRest.put(factoryName, nacosAsyncRestTemplate);
}
}
return nacosAsyncRestTemplate;
}

public static void shutdown() {
if (!alreadyShutdown.compareAndSet(false, true)) {
return;
}
logger.warn("[HttpClientBeanFactory] Start destroying NacosRestTemplate");
try {
nacostRestTemplateShutdown();
nacosAsyncRestTemplateShutdown();
}
catch (Exception ex) {
logger.error("[HttpClientBeanFactory] An exception occurred when the HTTP client was closed : {}",
ExceptionUtil.getStackTrace(ex));
}
logger.warn("[HttpClientBeanFactory] Destruction of the end");
}

private static void nacostRestTemplateShutdown() throws Exception{
if (!singletonRest.isEmpty()) {
Collection<NacosRestTemplate> nacosRestTemplates = singletonRest.values();
for (NacosRestTemplate nacosRestTemplate : nacosRestTemplates) {
nacosRestTemplate.close();
}
singletonRest.clear();
}
}

private static void nacosAsyncRestTemplateShutdown() throws Exception{
if (!singletonAsyncRest.isEmpty()) {
Collection<NacosAsyncRestTemplate> nacosAsyncRestTemplates = singletonAsyncRest.values();
for (NacosAsyncRestTemplate nacosAsyncRestTemplate : nacosAsyncRestTemplates) {
nacosAsyncRestTemplate.close();
}
singletonAsyncRest.clear();
}
}
}
Loading

0 comments on commit e528ea8

Please sign in to comment.