Merge pull request #4119 from alibaba/develop

Master upgrade 1.4.0
This commit is contained in:
杨翊 SionYang 2020-11-02 20:37:27 +08:00 committed by GitHub
commit c0ffb1d7e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
428 changed files with 12847 additions and 3622 deletions

23
.github/workflows/maven.yml vendored Normal file
View File

@ -0,0 +1,23 @@
name: Java CI
on: [push]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-18.04]
java: [8, 8.0.192, 11, 11.0.9]
fail-fast: false
max-parallel: 2
name: Test JDK ${{ matrix.java }}, ${{ matrix.os }}
steps:
- uses: actions/checkout@v1
- name: Set up JDK
uses: actions/setup-java@v1
with:
java-version: ${{ matrix.java }}
- name: Test with Maven
run: mvn test -B --file pom.xml

View File

@ -1,5 +1,5 @@
<img src="doc/Nacos_Logo.png" width="50%" height="50%" />
<img src="doc/Nacos_Logo.png" width="50%" syt height="50%" />
# Nacos: Dynamic *Na*ming and *Co*nfiguration *S*ervice
@ -12,25 +12,25 @@
Nacos (official site: [http://nacos.io](http://nacos.io)) is an easy-to-use platform designed for dynamic service discovery and configuration and service management. It helps you to build cloud native applications and microservices platform easily.
Service is a first-class citizen in Nacos. Nacos supports almost all type of servicesfor example[Dubbo/gRPC service](https://nacos.io/en-us/docs/use-nacos-with-dubbo.html)、[Spring Cloud RESTFul service](https://nacos.io/en-us/docs/use-nacos-with-springcloud.html) or [Kubernetes service](https://nacos.io/en-us/docs/use-nacos-with-kubernetes.html).
Service is a first-class citizen in Nacos. Nacos supports almost all type of servicesfor example[Dubbo/gRPC service](https://nacos.io/en-us/docs/use-nacos-with-dubbo.html), [Spring Cloud RESTFul service](https://nacos.io/en-us/docs/use-nacos-with-springcloud.html) or [Kubernetes service](https://nacos.io/en-us/docs/use-nacos-with-kubernetes.html).
Nacos provides four major functions.
* **Service Discovery and Service Health Check**
Nacos makes it simple for services to register themselves and to discover other services via a DNS or HTTP interface. Nacos also provides real-time healthchecks of services to prevent sending requests to unhealthy hosts or service instance.
Nacos makes it simple for services to register themselves and to discover other services via a DNS or HTTP interface. Nacos also provides real-time health checks of services to prevent sending requests to unhealthy hosts or service instances.
* **Dynamic Configuration Management**
Dynamic Configuration Service allows you to manage configurations of all services in a centralized and dynamic manner across all environments. Nacos eliminates the need to redeploy applications and services when configurations are updated, which makes configuration changes more efficient and agile.
Dynamic Configuration Service allows you to manage configurations of all services in a centralized and dynamic manner across all environments. Nacos eliminates the need to redeploy applications and services when configurations are updated, which makes configuration changes more efficient and agile.
* **Dynamic DNS Service**
Nacos supports weighted routing, making it easier for you to implement mid-tier load balancing, flexible routing policies, flow control, and simple DNS resolution services in the production environment within your data center. It helps you to implement DNS-based service discovery easily and prevent applications from coupling to vendor-specific service discovery APIs.
Nacos supports weighted routing, making it easier for you to implement mid-tier load balancing, flexible routing policies, flow control, and simple DNS resolution services in the production environment within your data center. It helps you to implement DNS-based service discovery easily and prevent applications from coupling to vendor-specific service discovery APIs.
* **Service and MetaData Management**
Nacos provides an easy-to-use service dashboard to help you manage your services metadata, configuration, kubernetes DNS, service health and metrics statistics.
Nacos provides an easy-to-use service dashboard to help you manage your services metadata, configuration, kubernetes DNS, service health and metrics statistics.
## Quick Start
@ -38,10 +38,10 @@ It is super easy to get started with your first project.
#### Step 1: Download the binary package
You can download the package from the [latest stable release](https://github.com/alibaba/nacos/releases).
You can download the package from the [latest stable release](https://github.com/alibaba/nacos/releases).
Take release nacos-server-1.0.0.zip for example.
```
Take release `nacos-server-1.0.0.zip` for example:
```sh
unzip nacos-server-1.0.0.zip
cd nacos/bin
```
@ -49,11 +49,11 @@ cd nacos/bin
#### Step 2: Start Server
On the **Linux/Unix/Mac** platform, run the following command to start server with standalone mode:
```
```sh
sh startup.sh -m standalone
```
On the **Windows** platform, run the following command to start server with standalone mode. Alternatively, you can also double-click the startup.cmd to run NacosServer.
On the **Windows** platform, run the following command to start server with standalone mode. Alternatively, you can also double-click the `startup.cmd` to run NacosServer.
```
cmd startup.cmd -m standalone
```
@ -74,7 +74,7 @@ For more details, see [quick-start.](https://nacos.io/en-us/docs/quick-start.htm
You can view the full documentation from the [Nacos website](https://nacos.io/en-us/docs/what-is-nacos.html).
All the latest and long-term notice can also be found here from [Github notice issue](https://github.com/alibaba/nacos/labels/notice)
All the latest and long-term notice can also be found here from [Github notice issue](https://github.com/alibaba/nacos/labels/notice).
## Contributing
@ -84,7 +84,7 @@ Contributors are welcomed to join Nacos project. Please check [CONTRIBUTING](./C
## Other Related Project Repositories
* [nacos-spring-project](https://github.com/nacos-group/nacos-spring-project) provides the integration functionality for Spring.
* [nacos-group](https://github.com/nacos-group) is the reposity that hosts the eco tools for Nacos, such as SDK, synchronization tool, etc.
* [nacos-group](https://github.com/nacos-group) is the repository that hosts the eco tools for Nacos, such as SDK, synchronization tool, etc.
* [spring-cloud-alibaba](https://github.com/spring-cloud-incubator/spring-cloud-alibaba) provides the one-stop solution for application development over Alibaba middleware which includes Nacos.
## Contact

View File

@ -19,7 +19,7 @@
<parent>
<artifactId>nacos-all</artifactId>
<groupId>com.alibaba.nacos</groupId>
<version>1.3.2</version>
<version>1.4.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -16,10 +16,10 @@
package com.alibaba.nacos.address.auth;
import com.alibaba.nacos.core.auth.AccessException;
import com.alibaba.nacos.core.auth.AuthManager;
import com.alibaba.nacos.core.auth.Permission;
import com.alibaba.nacos.core.auth.User;
import com.alibaba.nacos.auth.AuthManager;
import com.alibaba.nacos.auth.exception.AccessException;
import com.alibaba.nacos.auth.model.Permission;
import com.alibaba.nacos.auth.model.User;
/**
* Address server auth manager.

View File

@ -17,7 +17,7 @@
package com.alibaba.nacos.address.configuration;
import com.alibaba.nacos.address.auth.AddressServerAuthManager;
import com.alibaba.nacos.core.auth.AuthManager;
import com.alibaba.nacos.auth.AuthManager;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

View File

@ -19,7 +19,7 @@
<parent>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-all</artifactId>
<version>1.3.2</version>
<version>1.4.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -24,6 +24,7 @@ package com.alibaba.nacos.api.common;
* <li> Global and common code starts with 10001.
* <li> Naming module code starts with 20001.
* <li> Config module code starts with 30001.
* <li> Core module code starts with 40001.
*
* @author nkorange
* @since 1.2.0

View File

@ -167,4 +167,10 @@ public interface NamingMaintainService {
*/
void updateService(Service service, AbstractSelector selector) throws NacosException;
/**
* Shutdown the resource service.
*
* @throws NacosException exception.
*/
void shutDown() throws NacosException;
}

View File

@ -19,6 +19,7 @@ package com.alibaba.nacos.api.naming.pojo;
import com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;
import com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Tcp;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
@ -31,7 +32,9 @@ import java.util.Map;
* @author nkorange
*/
@SuppressWarnings("checkstyle:abbreviationaswordinname")
public class Cluster {
public class Cluster implements Serializable {
private static final long serialVersionUID = -7196138840047197271L;
/**
* Name of belonging service.

View File

@ -22,6 +22,7 @@ import com.alibaba.nacos.api.utils.StringUtils;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
@ -33,7 +34,9 @@ import static com.alibaba.nacos.api.common.Constants.NUMBER_PATTERN;
* @author nkorange
*/
@JsonInclude(Include.NON_NULL)
public class Instance {
public class Instance implements Serializable {
private static final long serialVersionUID = -742906310567291979L;
/**
* unique id of this instance.

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.api.naming.pojo;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
@ -29,7 +30,9 @@ import java.util.Map;
*
* @author nkorange
*/
public class Service {
public class Service implements Serializable {
private static final long serialVersionUID = -3470985546826874460L;
/**
* service name.

View File

@ -25,6 +25,8 @@ import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import java.io.Serializable;
/**
* Abstract health checker.
*
@ -34,7 +36,9 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
@JsonSubTypes({@JsonSubTypes.Type(name = Http.TYPE, value = Http.class),
@JsonSubTypes.Type(name = Mysql.TYPE, value = Mysql.class),
@JsonSubTypes.Type(name = Tcp.TYPE, value = Tcp.class)})
public abstract class AbstractHealthChecker implements Cloneable {
public abstract class AbstractHealthChecker implements Cloneable, Serializable {
private static final long serialVersionUID = 3848305577423336421L;
@JsonIgnore
protected final String type;

View File

@ -28,6 +28,9 @@ import com.alibaba.nacos.api.utils.StringUtils;
public class NamingUtils {
public static String getGroupedName(final String serviceName, final String groupName) {
if (StringUtils.isBlank(serviceName)) {
throw new IllegalArgumentException("Param 'serviceName' is illegal, serviceName is blank");
}
final String resultGroupedName = groupName + Constants.SERVICE_INFO_SPLITER + serviceName;
return resultGroupedName.intern();
}
@ -51,4 +54,25 @@ public class NamingUtils {
}
return serviceNameWithGroup.split(Constants.SERVICE_INFO_SPLITER)[0];
}
/**
* check combineServiceName format. the serviceName can't be blank. some relational logic in {@link
* com.alibaba.nacos.naming.web.DistroFilter#doFilter}, it will handle combineServiceName in some case, you should
* know it.
* <pre>
* serviceName = "@@"; the length = 0; illegal
* serviceName = "group@@"; the length = 1; illegal
* serviceName = "@@serviceName"; the length = 2; legal
* serviceName = "group@@serviceName"; the length = 2; legal
* </pre>
*
* @param combineServiceName such as: groupName@@serviceName
*/
public static void checkServiceNameFormat(String combineServiceName) {
String[] split = combineServiceName.split(Constants.SERVICE_INFO_SPLITER);
if (split.length <= 1) {
throw new IllegalArgumentException(
"Param 'serviceName' is illegal, it should be format as 'groupName@@serviceName'");
}
}
}

View File

@ -20,6 +20,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import java.io.Serializable;
/**
* Abstract selector that only contains a type.
*
@ -27,7 +29,9 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
* @since 0.7.0
*/
@JsonTypeInfo(use = Id.NAME, property = "type", defaultImpl = NoneSelector.class)
public abstract class AbstractSelector {
public abstract class AbstractSelector implements Serializable {
private static final long serialVersionUID = 4530233098102379229L;
/**
* The type of this selector, each child class should announce its own unique type.

87
auth/pom.xml Normal file
View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-all</artifactId>
<version>1.4.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-auth</artifactId>
<packaging>jar</packaging>
<name>nacos-auth ${project.version}</name>
<url>http://nacos.io</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>nacos-common</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>nacos-sys</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -14,12 +14,17 @@
* limitations under the License.
*/
package com.alibaba.nacos.core.auth;
package com.alibaba.nacos.auth;
import com.alibaba.nacos.auth.exception.AccessException;
import com.alibaba.nacos.auth.model.Permission;
import com.alibaba.nacos.auth.model.User;
/**
* Access control entry. Can be extended by 3rd party implementations.
*
* @author nkorange
* @author mai.jh
* @since 1.2.0
*/
public interface AuthManager {

View File

@ -14,8 +14,11 @@
* limitations under the License.
*/
package com.alibaba.nacos.core.auth;
package com.alibaba.nacos.auth.annotation;
import com.alibaba.nacos.auth.common.ActionTypes;
import com.alibaba.nacos.auth.parser.DefaultResourceParser;
import com.alibaba.nacos.auth.parser.ResourceParser;
import org.apache.commons.lang3.StringUtils;
import java.lang.annotation.Retention;
@ -25,6 +28,7 @@ import java.lang.annotation.RetentionPolicy;
* Annotation indicating that the annotated request should be authorized.
*
* @author nkorange
* @author mai.jh
* @since 1.2.0
*/
@Retention(RetentionPolicy.RUNTIME)

View File

@ -14,12 +14,13 @@
* limitations under the License.
*/
package com.alibaba.nacos.core.auth;
package com.alibaba.nacos.auth.common;
/**
* Resource action type definitions.
*
* @author nkorange
* @author mai.jh
* @since 1.2.0
*/
public enum ActionTypes {

View File

@ -14,18 +14,15 @@
* limitations under the License.
*/
package com.alibaba.nacos.core.auth;
package com.alibaba.nacos.auth.common;
import com.alibaba.nacos.common.JustForTest;
import com.alibaba.nacos.core.env.ReloadableConfigs;
import com.alibaba.nacos.sys.utils.ApplicationUtils;
import io.jsonwebtoken.io.Decoders;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import java.util.Objects;
@ -33,24 +30,26 @@ import java.util.Objects;
* Auth related configurations.
*
* @author nkorange
* @author mai.jh
* @since 1.2.0
*/
@Component
@Configuration
public class AuthConfigs {
@JustForTest
private static Boolean cachingEnabled = null;
@Autowired
private ReloadableConfigs reloadableConfigs;
/**
* secret key.
*/
@Value("${nacos.core.auth.default.token.secret.key:}")
private String secretKey;
/**
* secret key byte array.
*/
private byte[] secretKeyBytes;
/**
* Token validity time(seconds).
*/
@ -63,8 +62,11 @@ public class AuthConfigs {
@Value("${nacos.core.auth.system.type:}")
private String nacosAuthSystemType;
public String getSecretKey() {
return secretKey;
public byte[] getSecretKeyBytes() {
if (secretKeyBytes == null) {
secretKeyBytes = Decoders.BASE64.decode(secretKey);
}
return secretKeyBytes;
}
public long getTokenValidityInSeconds() {
@ -87,7 +89,7 @@ public class AuthConfigs {
return BooleanUtils.toBoolean(enabled);
}
return BooleanUtils
.toBoolean(reloadableConfigs.getProperties().getProperty("nacos.core.auth.enabled", "false"));
.toBoolean(ApplicationUtils.getProperty("nacos.core.auth.enabled", "false"));
}
/**
@ -100,28 +102,11 @@ public class AuthConfigs {
return cachingEnabled;
}
return BooleanUtils
.toBoolean(reloadableConfigs.getProperties().getProperty("nacos.core.auth.caching.enabled", "true"));
.toBoolean(ApplicationUtils.getProperty("nacos.core.auth.caching.enabled", "true"));
}
@JustForTest
public static void setCachingEnabled(boolean cachingEnabled) {
AuthConfigs.cachingEnabled = cachingEnabled;
}
@Bean
public FilterRegistrationBean authFilterRegistration() {
FilterRegistrationBean<AuthFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(authFilter());
registration.addUrlPatterns("/*");
registration.setName("authFilter");
registration.setOrder(6);
return registration;
}
@Bean
public AuthFilter authFilter() {
return new AuthFilter();
}
}

View File

@ -14,12 +14,13 @@
* limitations under the License.
*/
package com.alibaba.nacos.core.auth;
package com.alibaba.nacos.auth.common;
/**
* Types of all auth implementations.
*
* @author nkorange
* @author mai.jh
* @since 1.2.0
*/
public enum AuthSystemTypes {

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.alibaba.nacos.core.auth;
package com.alibaba.nacos.auth.exception;
import com.alibaba.nacos.api.exception.NacosException;
@ -22,6 +22,7 @@ import com.alibaba.nacos.api.exception.NacosException;
* Exception to be thrown if authorization is failed.
*
* @author nkorange
* @author mai.jh
* @since 1.2.0
*/
public class AccessException extends NacosException {

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.alibaba.nacos.core.auth;
package com.alibaba.nacos.auth.model;
import java.io.Serializable;
@ -22,6 +22,7 @@ import java.io.Serializable;
* Permission to auth.
*
* @author nkorange
* @author mai.jh
* @since 1.2.0
*/
public class Permission implements Serializable {

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.alibaba.nacos.core.auth;
package com.alibaba.nacos.auth.model;
import java.io.Serializable;
@ -22,6 +22,7 @@ import java.io.Serializable;
* Resource used in authorization.
*
* @author nkorange
* @author mai.jh
* @since 1.2.0
*/
public class Resource implements Serializable {

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.alibaba.nacos.core.auth;
package com.alibaba.nacos.auth.model;
import java.io.Serializable;
@ -22,6 +22,7 @@ import java.io.Serializable;
* User information in authorization.
*
* @author nkorange
* @author mai.jh
* @since 1.2.0
*/
public class User implements Serializable {

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.alibaba.nacos.core.auth;
package com.alibaba.nacos.auth.parser;
import org.apache.commons.lang3.StringUtils;
@ -22,6 +22,7 @@ import org.apache.commons.lang3.StringUtils;
* Default resource parser.
*
* @author nkorange
* @author mai.jh
* @since 1.2.0
*/
public class DefaultResourceParser implements ResourceParser {

View File

@ -14,12 +14,13 @@
* limitations under the License.
*/
package com.alibaba.nacos.core.auth;
package com.alibaba.nacos.auth.parser;
/**
* Resource parser.
*
* @author nkorange
* @author mai.jh
* @since 1.2.0
*/
public interface ResourceParser {

View File

@ -19,7 +19,7 @@
<parent>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-all</artifactId>
<version>1.3.2</version>
<version>1.4.0</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -49,14 +49,13 @@ import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.Callable;
/**
* Server Agent.
@ -94,9 +93,9 @@ public class ServerHttpAgent implements HttpAgent {
if (headers != null) {
newHeaders.addAll(headers);
}
Query query = Query.newInstance().initParams(paramValues);
HttpRestResult<String> result = NACOS_RESTTEMPLATE
.get(getUrl(currentServerAddr, path), httpConfig, newHeaders, paramValues, String.class);
.get(getUrl(currentServerAddr, path), httpConfig, newHeaders, query, String.class);
if (isFail(result)) {
LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}",
serverListMgr.getCurrentServerAddr(), result.getCode());
@ -152,8 +151,7 @@ public class ServerHttpAgent implements HttpAgent {
newHeaders.addAll(headers);
}
HttpRestResult<String> result = NACOS_RESTTEMPLATE
.postForm(getUrl(currentServerAddr, path), httpConfig, newHeaders,
new HashMap<String, String>(0), paramValues, String.class);
.postForm(getUrl(currentServerAddr, path), httpConfig, newHeaders, paramValues, String.class);
if (isFail(result)) {
LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}", currentServerAddr,
@ -207,8 +205,9 @@ public class ServerHttpAgent implements HttpAgent {
if (headers != null) {
newHeaders.addAll(headers);
}
Query query = Query.newInstance().initParams(paramValues);
HttpRestResult<String> result = NACOS_RESTTEMPLATE
.delete(getUrl(currentServerAddr, path), httpConfig, newHeaders, paramValues, String.class);
.delete(getUrl(currentServerAddr, path), httpConfig, newHeaders, query, String.class);
if (isFail(result)) {
LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}",
serverListMgr.getCurrentServerAddr(), result.getCode());

View File

@ -17,7 +17,7 @@
package com.alibaba.nacos.client.config.impl;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.client.identify.Base64;
import com.alibaba.nacos.common.codec.Base64;
import com.alibaba.nacos.client.identify.CredentialService;
import com.alibaba.nacos.common.utils.StringUtils;

View File

@ -17,7 +17,7 @@
package com.alibaba.nacos.client.config.utils;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.utils.IpUtil;
import com.alibaba.nacos.common.utils.IpUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import java.util.List;
@ -190,7 +190,7 @@ public class ParamUtils {
}
String[] ipsArr = betaIps.split(",");
for (String ip : ipsArr) {
if (!IpUtil.isIpv4(ip)) {
if (!IpUtils.isIpv4(ip)) {
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "betaIps invalid");
}
}

View File

@ -19,6 +19,8 @@ package com.alibaba.nacos.client.logging;
import com.alibaba.nacos.common.utils.ConvertUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import java.io.File;
/**
* Abstract nacos logging.
*
@ -31,13 +33,13 @@ public abstract class AbstractNacosLogging {
private static final String NACOS_LOGGING_DEFAULT_CONFIG_ENABLED_PROPERTY = "nacos.logging.default.config.enabled";
private static final String NACOS_LOGGING_PATH_PROPERTY = "nacos.logging.path";
private static final String NACOS_LOGGING_PATH_PROPERTY = "JM.LOG.PATH";
static {
String loggingPath = System.getProperty(NACOS_LOGGING_PATH_PROPERTY);
if (StringUtils.isBlank(loggingPath)) {
String userHome = System.getProperty("user.home");
System.setProperty(NACOS_LOGGING_PATH_PROPERTY, userHome + "/logs/nacos");
System.setProperty(NACOS_LOGGING_PATH_PROPERTY, userHome + File.separator + "logs");
}
}

View File

@ -173,4 +173,8 @@ public class NacosNamingMaintainService implements NamingMaintainService {
serverProxy.updateService(service, selector);
}
@Override
public void shutDown() throws NacosException {
serverProxy.shutdown();
}
}

View File

@ -39,6 +39,7 @@ import com.alibaba.nacos.client.utils.ValidatorUtils;
import com.alibaba.nacos.common.utils.ConvertUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@ -151,9 +152,13 @@ public class NacosNamingService implements NamingService {
}
private void initCacheDir() {
cacheDir = System.getProperty("com.alibaba.nacos.naming.cache.dir");
if (StringUtils.isEmpty(cacheDir)) {
cacheDir = System.getProperty("user.home") + "/nacos/naming/" + namespace;
String jmSnapshotPath = System.getProperty("JM.SNAPSHOT.PATH");
if (!StringUtils.isBlank(jmSnapshotPath)) {
cacheDir = jmSnapshotPath + File.separator + "nacos" + File.separator + "naming"
+ File.separator + namespace;
} else {
cacheDir = System.getProperty("user.home") + File.separator + "nacos" + File.separator + "naming"
+ File.separator + namespace;
}
}

View File

@ -143,11 +143,12 @@ public class ConcurrentDiskUtil {
}
} while (null == lock);
ByteBuffer sendBuffer = ByteBuffer.wrap(content.getBytes(charsetName));
byte[] contentBytes = content.getBytes(charsetName);
ByteBuffer sendBuffer = ByteBuffer.wrap(contentBytes);
while (sendBuffer.hasRemaining()) {
channel.write(sendBuffer);
}
channel.truncate(content.length());
channel.truncate(contentBytes.length);
} catch (FileNotFoundException e) {
throw new IOException("file not exist");
} finally {

View File

@ -25,6 +25,7 @@ import com.alibaba.nacos.client.naming.beat.BeatInfo;
import com.alibaba.nacos.client.naming.beat.BeatReactor;
import com.alibaba.nacos.client.naming.cache.DiskCache;
import com.alibaba.nacos.client.naming.net.NamingProxy;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
import com.alibaba.nacos.common.lifecycle.Closeable;
import com.alibaba.nacos.common.utils.JacksonUtils;
@ -296,6 +297,14 @@ public class HostReactor implements Closeable {
return serviceInfoMap.get(serviceObj.getKey());
}
private void updateServiceNow(String serviceName, String clusters) {
try {
updateService(serviceName, clusters);
} catch (NacosException e) {
NAMING_LOGGER.error("[NA] failed to update serviceName: " + serviceName, e);
}
}
/**
* Schedule update if absent.
*
@ -323,7 +332,7 @@ public class HostReactor implements Closeable {
* @param serviceName service name
* @param clusters clusters
*/
public void updateServiceNow(String serviceName, String clusters) {
public void updateService(String serviceName, String clusters) throws NacosException {
ServiceInfo oldService = getServiceInfo0(serviceName, clusters);
try {
@ -332,8 +341,6 @@ public class HostReactor implements Closeable {
if (StringUtils.isNotEmpty(result)) {
processServiceJson(result);
}
} catch (Exception e) {
NAMING_LOGGER.error("[NA] failed to update serviceName: " + serviceName, e);
} finally {
if (oldService != null) {
synchronized (oldService) {
@ -375,26 +382,42 @@ public class HostReactor implements Closeable {
private final String serviceName;
/**
* the fail situation. 1:can't connect to server 2:serviceInfo's hosts is empty
*/
private int failCount = 0;
public UpdateTask(String serviceName, String clusters) {
this.serviceName = serviceName;
this.clusters = clusters;
}
private void incFailCount() {
int limit = 6;
if (failCount == limit) {
return;
}
failCount++;
}
private void resetFailCount() {
failCount = 0;
}
@Override
public void run() {
long delayTime = -1;
long delayTime = DEFAULT_DELAY;
try {
ServiceInfo serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters));
if (serviceObj == null) {
updateServiceNow(serviceName, clusters);
delayTime = DEFAULT_DELAY;
updateService(serviceName, clusters);
return;
}
if (serviceObj.getLastRefTime() <= lastRefTime) {
updateServiceNow(serviceName, clusters);
updateService(serviceName, clusters);
serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters));
} else {
// if serviceName already updated by push, we should not override it
@ -410,17 +433,18 @@ public class HostReactor implements Closeable {
NAMING_LOGGER.info("update task is stopped, service:" + serviceName + ", clusters:" + clusters);
return;
}
if (CollectionUtils.isEmpty(serviceObj.getHosts())) {
incFailCount();
return;
}
delayTime = serviceObj.getCacheMillis();
resetFailCount();
} catch (Throwable e) {
incFailCount();
NAMING_LOGGER.warn("[NA] failed to update serviceName: " + serviceName, e);
} finally {
if (delayTime > 0) {
executor.schedule(this, delayTime, TimeUnit.MILLISECONDS);
}
executor.schedule(this, Math.min(delayTime << failCount, DEFAULT_DELAY * 60), TimeUnit.MILLISECONDS);
}
}
}
}

View File

@ -107,6 +107,9 @@ public class PushReceiver implements Runnable, Closeable {
udpSocket.send(new DatagramPacket(ack.getBytes(UTF_8), ack.getBytes(UTF_8).length,
packet.getSocketAddress()));
} catch (Exception e) {
if (closed) {
return;
}
NAMING_LOGGER.error("[NA] error while receiving push data", e);
}
}

View File

@ -18,6 +18,7 @@ package com.alibaba.nacos.client.naming.net;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.tls.TlsSystemConfig;
import com.alibaba.nacos.common.utils.HttpMethod;
import com.alibaba.nacos.common.utils.IoUtils;
import com.alibaba.nacos.common.utils.StringUtils;
@ -53,7 +54,7 @@ public class HttpClient {
public 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 boolean ENABLE_HTTPS = Boolean.getBoolean(TlsSystemConfig.TLS_ENABLE);
static {
// limit max redirection

View File

@ -23,6 +23,7 @@ import com.alibaba.nacos.common.http.HttpClientConfig;
import com.alibaba.nacos.common.http.HttpClientFactory;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.lifecycle.Closeable;
import com.alibaba.nacos.common.tls.TlsSystemConfig;
import com.alibaba.nacos.common.utils.ExceptionUtil;
import org.slf4j.Logger;
@ -40,7 +41,7 @@ public class NamingHttpClientManager implements Closeable {
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 boolean ENABLE_HTTPS = Boolean.getBoolean(TlsSystemConfig.TLS_ENABLE);
private static final int MAX_REDIRECTS = 5;
@ -85,7 +86,7 @@ public class NamingHttpClientManager implements Closeable {
return HttpClientConfig.builder().setConTimeOutMillis(CON_TIME_OUT_MILLIS)
.setReadTimeOutMillis(READ_TIME_OUT_MILLIS).setMaxRedirects(MAX_REDIRECTS).build();
}
@Override
protected Logger assignLogger() {
return NAMING_LOGGER;

View File

@ -596,7 +596,7 @@ public class NamingProxy implements Closeable {
try {
HttpRestResult<String> restResult = nacosRestTemplate
.exchangeForm(url, header, params, body, method, String.class);
.exchangeForm(url, header, Query.newInstance().initParams(params), body, method, String.class);
end = System.currentTimeMillis();
MetricsMonitor.getNamingRequestMonitor(method, url, String.valueOf(restResult.getCode()))

View File

@ -16,7 +16,7 @@
package com.alibaba.nacos.client.naming.utils;
import com.alibaba.nacos.client.identify.Base64;
import com.alibaba.nacos.common.codec.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

View File

@ -21,6 +21,7 @@ import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.fasterxml.jackson.databind.JsonNode;
@ -138,7 +139,7 @@ public class SecurityProxy {
}
try {
HttpRestResult<String> restResult = nacosRestTemplate
.postForm(url, Header.EMPTY, params, bodyMap, String.class);
.postForm(url, Header.EMPTY, Query.newInstance().initParams(params), bodyMap, String.class);
if (!restResult.ok()) {
SECURITY_LOGGER.error("login failed: {}", JacksonUtils.toJson(restResult));
return false;

View File

@ -20,9 +20,9 @@ import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.SystemPropertyKeyConst;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.common.utils.VersionUtils;
import org.slf4j.Logger;
import java.io.InputStream;
import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.regex.Pattern;
@ -80,19 +80,7 @@ public class ParamUtil {
}
LOGGER.info("[settings] [http-client] connect timeout:{}", connectTimeout);
try {
InputStream in = ValidatorUtils.class.getClassLoader().getResourceAsStream("application.properties");
Properties props = new Properties();
props.load(in);
String val = null;
val = props.getProperty("version");
if (val != null) {
clientVersion = val;
}
LOGGER.info("NACOS_CLIENT_VERSION: {}", clientVersion);
} catch (Exception e) {
LOGGER.error("[500] read application.properties", e);
}
clientVersion = VersionUtils.version;
try {
perTaskConfigSize = Double.valueOf(System.getProperty("PER_TASK_CONFIG_SIZE", "3000"));

View File

@ -1,16 +0,0 @@
#
# 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.
#
version=${project.version}

View File

@ -17,8 +17,8 @@
<Configuration status="WARN">
<Appenders>
<RollingFile name="CONFIG_LOG_FILE" fileName="${sys:nacos.logging.path}/config.log"
filePattern="${sys:nacos.logging.path}/config.log.%d{yyyy-MM-dd}.%i">
<RollingFile name="CONFIG_LOG_FILE" fileName="${sys:JM.LOG.PATH}/nacos/config.log"
filePattern="${sys:JM.LOG.PATH}/nacos/config.log.%d{yyyy-MM-dd}.%i">
<PatternLayout>
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %p [%-5t:%c{2}] %m%n</Pattern>
</PatternLayout>
@ -31,8 +31,8 @@
<DefaultRolloverStrategy max="${sys:JM.LOG.RETAIN.COUNT:-7}"/>
</RollingFile>
<RollingFile name="NAMING_LOG_FILE" fileName="${sys:nacos.logging.path}/naming.log"
filePattern="${sys:nacos.logging.path}/naming.log.%d{yyyy-MM-dd}.%i">
<RollingFile name="NAMING_LOG_FILE" fileName="${sys:JM.LOG.PATH}/nacos/naming.log"
filePattern="${sys:JM.LOG.PATH}/nacos/naming.log.%d{yyyy-MM-dd}.%i">
<PatternLayout>
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %p [%-5t:%c{2}] %m%n</Pattern>
</PatternLayout>

View File

@ -19,10 +19,10 @@
<contextName>nacos</contextName>
<appender name="CONFIG_LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${nacos.logging.path}/config.log</file>
<file>${JM.LOG.PATH}/nacos/config.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>${nacos.logging.path}/config.log.%i</fileNamePattern>
<fileNamePattern>${JM.LOG.PATH}/nacos/config.log.%i</fileNamePattern>
<maxIndex>${JM.LOG.RETAIN.COUNT:-7}</maxIndex>
</rollingPolicy>
@ -36,10 +36,10 @@
</appender>
<appender name="NAMING_LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${nacos.logging.path}/naming.log</file>
<file>${JM.LOG.PATH}/nacos/naming.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>${nacos.logging.path}/naming.log.%i</fileNamePattern>
<fileNamePattern>${JM.LOG.PATH}/nacos/naming.log.%i</fileNamePattern>
<maxIndex>${JM.LOG.RETAIN.COUNT:-7}</maxIndex>
</rollingPolicy>

View File

@ -20,6 +20,7 @@ import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.AbstractListener;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.common.utils.ThreadUtils;
import org.junit.After;
import org.junit.Assert;
@ -28,7 +29,7 @@ import org.junit.Ignore;
import org.junit.Test;
import java.util.Properties;
import java.util.Scanner;
import java.util.concurrent.atomic.AtomicBoolean;
@Ignore
public class ConfigTest {
@ -36,7 +37,7 @@ public class ConfigTest {
private static ConfigService configService;
@Before
public static void before() throws Exception {
public void before() throws Exception {
Properties properties = new Properties();
properties.setProperty(PropertyKeyConst.SERVER_ADDR, "127.0.0.1:8848");
configService = NacosFactory.createConfigService(properties);
@ -48,7 +49,8 @@ public class ConfigTest {
}
@Test
public static void test() throws Exception {
public void test() throws Exception {
// set config
final String dataId = "lessspring";
final String group = "lessspring";
final String content = "lessspring-" + System.currentTimeMillis();
@ -57,24 +59,46 @@ public class ConfigTest {
ThreadUtils.sleep(10000L);
// set change listener
final AtomicBoolean hasListener = new AtomicBoolean(false);
final AtomicBoolean hasChangedCallback = new AtomicBoolean(false);
final String[] changedTmpContent = {""};
String response = configService.getConfigAndSignListener(dataId, group, 5000, new AbstractListener() {
@Override
public void receiveConfigInfo(String configInfo) {
System.err.println(configInfo);
System.out.println("receiveConfigInfo:" + configInfo);
changedTmpContent[0] = configInfo;
hasChangedCallback.set(true);
}
});
hasListener.set(true);
Assert.assertEquals(content, response);
Scanner scanner = new Scanner(System.in);
System.out.println("input content");
while (scanner.hasNextLine()) {
String s = scanner.next();
if ("exit".equals(s)) {
scanner.close();
return;
// new thread to publish config
final String newRawContent = "nacosnewconfig-" + System.currentTimeMillis();
new Thread(new Runnable() {
@Override
public void run() {
while (hasListener.get()) {
try {
configService.publishConfig(dataId, group, newRawContent);
hasListener.set(false);
break;
} catch (NacosException e) {
e.printStackTrace();
}
}
}
configService.publishConfig(dataId, group, s);
}
}).start();
// spin
do {
if (hasChangedCallback.get()) {
System.out.println(newRawContent + "==> " + changedTmpContent[0]);
Assert.assertEquals(newRawContent, changedTmpContent[0]);
break;
}
} while (!hasChangedCallback.get());
}
}

View File

@ -47,6 +47,7 @@ public class DiskCacheTest {
instance.setIp("1.1.1.1");
instance.setPort(1234);
instance.setServiceName("testName");
instance.addMetadata("chinese", "中文");
serviceInfo.setHosts(Collections.singletonList(instance));
}
@ -87,9 +88,10 @@ public class DiskCacheTest {
}
private void assertInstance(Instance actual, Instance expected) {
assertEquals(actual.getServiceName(), actual.getServiceName());
assertEquals(actual.getClusterName(), actual.getClusterName());
assertEquals(actual.getIp(), actual.getIp());
assertEquals(actual.getPort(), actual.getPort());
assertEquals(actual.getServiceName(), expected.getServiceName());
assertEquals(actual.getClusterName(), expected.getClusterName());
assertEquals(actual.getIp(), expected.getIp());
assertEquals(actual.getPort(), expected.getPort());
assertEquals(actual.getMetadata(), expected.getMetadata());
}
}

View File

@ -21,7 +21,7 @@
<parent>
<artifactId>nacos-all</artifactId>
<groupId>com.alibaba.nacos</groupId>
<version>1.3.2</version>
<version>1.4.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -21,7 +21,7 @@
<parent>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-all</artifactId>
<version>1.3.2</version>
<version>1.4.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.alibaba.nacos.client.identify;
package com.alibaba.nacos.common.codec;
import java.nio.charset.Charset;

View File

@ -0,0 +1,44 @@
/*
* 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.NacosRestTemplate;
import com.alibaba.nacos.common.http.client.request.DefaultHttpClientRequest;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.HttpClients;
/**
* apache http client factory implements.
*
* @author mai.jh
*/
public abstract class AbstractApacheHttpClientFactory extends AbstractHttpClientFactory {
@Override
public final NacosRestTemplate createNacosRestTemplate() {
final HttpClientConfig originalRequestConfig = buildHttpClientConfig();
final RequestConfig requestConfig = getRequestConfig();
return new NacosRestTemplate(assignLogger(), new DefaultHttpClientRequest(
HttpClients.custom().setDefaultRequestConfig(requestConfig)
.setUserAgent(originalRequestConfig.getUserAgent())
.setMaxConnTotal(originalRequestConfig.getMaxConnTotal())
.setMaxConnPerRoute(originalRequestConfig.getMaxConnPerRoute())
.setConnectionTimeToLive(originalRequestConfig.getConnTimeToLive(),
originalRequestConfig.getConnTimeToLiveTimeUnit()).build()));
}
}

View File

@ -20,10 +20,22 @@ 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;
import com.alibaba.nacos.common.http.client.request.JdkHttpClientRequest;
import com.alibaba.nacos.common.tls.SelfHostnameVerifier;
import com.alibaba.nacos.common.tls.TlsFileWatcher;
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.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.
*
@ -32,25 +44,83 @@ import org.slf4j.Logger;
public abstract class AbstractHttpClientFactory implements HttpClientFactory {
@Override
public final NacosRestTemplate createNacosRestTemplate() {
public NacosRestTemplate createNacosRestTemplate() {
HttpClientConfig httpClientConfig = buildHttpClientConfig();
return new NacosRestTemplate(assignLogger(), new JdkHttpClientRequest(httpClientConfig));
final JdkHttpClientRequest clientRequest = new JdkHttpClientRequest(httpClientConfig);
// enable ssl
initTls(new BiConsumer<SSLContext, HostnameVerifier>() {
@Override
public void accept(SSLContext sslContext, HostnameVerifier hostnameVerifier) {
clientRequest.setSSLContext(loadSSLContext());
clientRequest.replaceSSLHostnameVerifier(hostnameVerifier);
}
}, new TlsFileWatcher.FileChangeListener() {
@Override
public void onChanged(String filePath) {
clientRequest.setSSLContext(loadSSLContext());
}
});
return new NacosRestTemplate(assignLogger(), clientRequest);
}
@Override
public final NacosAsyncRestTemplate createNacosAsyncRestTemplate() {
RequestConfig requestConfig = getRequestConfig();
public NacosAsyncRestTemplate createNacosAsyncRestTemplate() {
final HttpClientConfig originalRequestConfig = buildHttpClientConfig();
final RequestConfig requestConfig = getRequestConfig();
return new NacosAsyncRestTemplate(assignLogger(), new DefaultAsyncHttpClientRequest(
HttpAsyncClients.custom().setDefaultRequestConfig(requestConfig).build()));
HttpAsyncClients.custom().setDefaultRequestConfig(requestConfig)
.setMaxConnTotal(originalRequestConfig.getMaxConnTotal())
.setMaxConnPerRoute(originalRequestConfig.getMaxConnPerRoute())
.setUserAgent(originalRequestConfig.getUserAgent()).build()));
}
private RequestConfig getRequestConfig() {
protected RequestConfig getRequestConfig() {
HttpClientConfig httpClientConfig = buildHttpClientConfig();
return RequestConfig.custom().setConnectTimeout(httpClientConfig.getConTimeOutMillis())
.setSocketTimeout(httpClientConfig.getReadTimeOutMillis())
.setConnectionRequestTimeout(httpClientConfig.getConnectionRequestTimeout())
.setMaxRedirects(httpClientConfig.getMaxRedirects()).build();
}
protected void initTls(BiConsumer<SSLContext, HostnameVerifier> initTlsBiFunc,
TlsFileWatcher.FileChangeListener tlsChangeListener) {
if (!TlsSystemConfig.tlsEnable) {
return;
}
final HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
final SelfHostnameVerifier selfHostnameVerifier = new SelfHostnameVerifier(hv);
initTlsBiFunc.accept(loadSSLContext(), selfHostnameVerifier);
if (tlsChangeListener != null) {
try {
TlsFileWatcher.getInstance()
.addFileChangeListener(tlsChangeListener, TlsSystemConfig.tlsClientTrustCertPath,
TlsSystemConfig.tlsClientKeyPath);
} catch (IOException e) {
assignLogger().error("add tls file listener fail", e);
}
}
}
@SuppressWarnings("checkstyle:abbreviationaswordinname")
protected synchronized SSLContext loadSSLContext() {
if (!TlsSystemConfig.tlsEnable) {
return null;
}
try {
return TlsHelper.buildSslContext(true);
} catch (NoSuchAlgorithmException e) {
assignLogger().error("Failed to create SSLContext", e);
} catch (KeyManagementException e) {
assignLogger().error("Failed to create SSLContext", e);
}
return null;
}
/**
* build http client config.
*

View File

@ -16,7 +16,6 @@
package com.alibaba.nacos.common.http;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.http.handler.ResponseHandler;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.Query;
@ -39,7 +38,9 @@ import java.net.URI;
* Base http client.
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
* @deprecated Refer to the new {@link com.alibaba.nacos.common.http.client.request.HttpClientRequest}
*/
@Deprecated
public abstract class BaseHttpClient {
protected <T> RestResult<T> execute(CloseableHttpClient httpClient, final Type type, HttpUriRequest request)
@ -101,7 +102,7 @@ public abstract class BaseHttpClient {
final BaseHttpMethod httpMethod = BaseHttpMethod.sourceOf(method);
final HttpRequestBase httpRequestBase = httpMethod.init(url);
HttpUtils.initRequestHeader(httpRequestBase, header);
HttpUtils.initRequestEntity(httpRequestBase, body, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
HttpUtils.initRequestEntity(httpRequestBase, body, header);
return httpRequestBase;
}

View File

@ -17,9 +17,9 @@
package com.alibaba.nacos.common.http;
import com.alibaba.nacos.common.utils.HttpMethod;
import com.alibaba.nacos.common.utils.StringUtils;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPatch;
@ -28,6 +28,8 @@ import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.HttpTrace;
import java.net.URI;
/**
* Base http method.
*
@ -48,7 +50,7 @@ public enum BaseHttpMethod {
GET_LARGE(HttpMethod.GET_LARGE) {
@Override
protected HttpRequestBase createRequest(String url) {
return new BaseHttpClient.HttpGetWithEntity(url);
return new HttpGetWithEntity(url);
}
},
@ -82,6 +84,16 @@ public enum BaseHttpMethod {
}
},
/**
* delete Large request.
*/
DELETE_LARGE(HttpMethod.DELETE_LARGE) {
@Override
protected HttpRequestBase createRequest(String url) {
return new HttpDeleteWithEntity(url);
}
},
/**
* head request.
*/
@ -151,4 +163,48 @@ public enum BaseHttpMethod {
throw new IllegalArgumentException("Unsupported http method : " + name);
}
/**
* get Large implemented.
* <p>
* Mainly used for GET request parameters are relatively large, can not be placed on the URL, so it needs to be
* placed in the body.
* </p>
*/
public static class HttpGetWithEntity extends HttpEntityEnclosingRequestBase {
public static final String METHOD_NAME = "GET";
public HttpGetWithEntity(String url) {
super();
setURI(URI.create(url));
}
@Override
public String getMethod() {
return METHOD_NAME;
}
}
/**
* delete Large implemented.
* <p>
* Mainly used for DELETE request parameters are relatively large, can not be placed on the URL, so it needs to be
* placed in the body.
* </p>
*/
public static class HttpDeleteWithEntity extends HttpEntityEnclosingRequestBase {
public static final String METHOD_NAME = "DELETE";
public HttpDeleteWithEntity(String url) {
super();
setURI(URI.create(url));
}
@Override
public String getMethod() {
return METHOD_NAME;
}
}
}

View File

@ -16,6 +16,8 @@
package com.alibaba.nacos.common.http;
import java.util.concurrent.TimeUnit;
/**
* http client config build.
*
@ -23,16 +25,62 @@ package com.alibaba.nacos.common.http;
*/
public class HttpClientConfig {
/**
* connect time out.
*/
private final int conTimeOutMillis;
/**
* read time out.
*/
private final int readTimeOutMillis;
/**
* connTimeToLive.
*/
private final long connTimeToLive;
/**
* connTimeToLiveTimeUnit.
*/
private final TimeUnit connTimeToLiveTimeUnit;
/**
* connectionRequestTimeout.
*/
private final int connectionRequestTimeout;
/**
* max redirect.
*/
private final int maxRedirects;
public HttpClientConfig(int conTimeOutMillis, int readTimeOutMillis, int maxRedirects) {
/**
* max connect total.
*/
private final int maxConnTotal;
/**
* Assigns maximum connection per route value.
*/
private final int maxConnPerRoute;
/**
* user agent.
*/
private final String userAgent;
public HttpClientConfig(int conTimeOutMillis, int readTimeOutMillis, long connTimeToLive, TimeUnit timeUnit,
int connectionRequestTimeout, int maxRedirects, int maxConnTotal, int maxConnPerRoute, String userAgent) {
this.conTimeOutMillis = conTimeOutMillis;
this.readTimeOutMillis = readTimeOutMillis;
this.connTimeToLive = connTimeToLive;
this.connTimeToLiveTimeUnit = timeUnit;
this.connectionRequestTimeout = connectionRequestTimeout;
this.maxRedirects = maxRedirects;
this.maxConnTotal = maxConnTotal;
this.maxConnPerRoute = maxConnPerRoute;
this.userAgent = userAgent;
}
public int getConTimeOutMillis() {
@ -43,10 +91,34 @@ public class HttpClientConfig {
return readTimeOutMillis;
}
public long getConnTimeToLive() {
return connTimeToLive;
}
public TimeUnit getConnTimeToLiveTimeUnit() {
return connTimeToLiveTimeUnit;
}
public int getConnectionRequestTimeout() {
return connectionRequestTimeout;
}
public int getMaxRedirects() {
return maxRedirects;
}
public int getMaxConnTotal() {
return maxConnTotal;
}
public int getMaxConnPerRoute() {
return maxConnPerRoute;
}
public String getUserAgent() {
return userAgent;
}
public static HttpClientConfigBuilder builder() {
return new HttpClientConfigBuilder();
}
@ -57,8 +129,20 @@ public class HttpClientConfig {
private int readTimeOutMillis = -1;
private long connTimeToLive = -1;
private TimeUnit connTimeToLiveTimeUnit = TimeUnit.MILLISECONDS;
private int connectionRequestTimeout = -1;
private int maxRedirects = 50;
private int maxConnTotal = 0;
private int maxConnPerRoute = 0;
private String userAgent;
public HttpClientConfigBuilder setConTimeOutMillis(int conTimeOutMillis) {
this.conTimeOutMillis = conTimeOutMillis;
return this;
@ -69,13 +153,40 @@ public class HttpClientConfig {
return this;
}
public HttpClientConfigBuilder setConnectionTimeToLive(long connTimeToLive, TimeUnit connTimeToLiveTimeUnit) {
this.connTimeToLive = connTimeToLive;
this.connTimeToLiveTimeUnit = connTimeToLiveTimeUnit;
return this;
}
public HttpClientConfigBuilder setConnectionRequestTimeout(int connectionRequestTimeout) {
this.connectionRequestTimeout = connectionRequestTimeout;
return this;
}
public HttpClientConfigBuilder setMaxRedirects(int maxRedirects) {
this.maxRedirects = maxRedirects;
return this;
}
public HttpClientConfigBuilder setMaxConnTotal(int maxConnTotal) {
this.maxConnTotal = maxConnTotal;
return this;
}
public HttpClientConfigBuilder setMaxConnPerRoute(int maxConnPerRoute) {
this.maxConnPerRoute = maxConnPerRoute;
return this;
}
public HttpClientConfigBuilder setUserAgent(String userAgent) {
this.userAgent = userAgent;
return this;
}
public HttpClientConfig build() {
return new HttpClientConfig(conTimeOutMillis, readTimeOutMillis, maxRedirects);
return new HttpClientConfig(conTimeOutMillis, readTimeOutMillis, connTimeToLive, connTimeToLiveTimeUnit,
connectionRequestTimeout, maxRedirects, maxConnTotal, maxConnPerRoute, userAgent);
}
}
}

View File

@ -30,7 +30,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
* Use the same HttpClient object in the same space.
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
* @deprecated Refer to the new {@link HttpClientBeanHolder}
*/
@Deprecated
public class HttpClientManager {
private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientManager.class);

View File

@ -16,15 +16,18 @@
package com.alibaba.nacos.common.http;
import com.alibaba.nacos.common.http.handler.RequestHandler;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicNameValuePair;
@ -70,17 +73,23 @@ public final class HttpUtils {
*
* @param requestBase requestBase {@link HttpRequestBase}
* @param body body
* @param mediaType mediaType {@link ContentType}
* @param header request header
* @throws Exception exception
*/
public static void initRequestEntity(HttpRequestBase requestBase, Object body, String mediaType) throws Exception {
public static void initRequestEntity(HttpRequestBase requestBase, Object body, Header header) throws Exception {
if (body == null) {
return;
}
if (requestBase instanceof HttpEntityEnclosingRequest) {
HttpEntityEnclosingRequest request = (HttpEntityEnclosingRequest) requestBase;
ContentType contentType = ContentType.create(mediaType);
StringEntity entity = new StringEntity(RequestHandler.parse(body), contentType);
MediaType mediaType = MediaType.valueOf(header.getValue(HttpHeaderConsts.CONTENT_TYPE));
ContentType contentType = ContentType.create(mediaType.getType(), mediaType.getCharset());
HttpEntity entity;
if (body instanceof byte[]) {
entity = new ByteArrayEntity((byte[]) body, contentType);
} else {
entity = new StringEntity(body instanceof String ? (String) body : JacksonUtils.toJson(body), contentType);
}
request.setEntity(entity);
}
}
@ -229,7 +238,7 @@ public final class HttpUtils {
* @return {@link URI}
*/
public static URI buildUri(String url, Query query) throws URISyntaxException {
if (!query.isEmpty()) {
if (query != null && !query.isEmpty()) {
url = url + "?" + query.toQueryUrl();
}
return new URI(url);

View File

@ -25,7 +25,9 @@ import java.lang.reflect.Type;
* Nacos async http client interface.
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
* @deprecated Refer to the new {@link com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate}
*/
@Deprecated
@SuppressWarnings("all")
public interface NAsyncHttpClient extends NHttpClient {

View File

@ -22,7 +22,9 @@ import java.io.Closeable;
* Nacos http client interface.
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
* @deprecated Refer to the new {@link com.alibaba.nacos.common.http.client.request.HttpClientRequest}
*/
@Deprecated
@SuppressWarnings("PMD.ClassNamingShouldBeCamelRule")
public interface NHttpClient extends Closeable {

View File

@ -26,7 +26,9 @@ import java.lang.reflect.Type;
* Nacos sync http client.
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
* @deprecated Refer to the new {@link com.alibaba.nacos.common.http.client.NacosRestTemplate}
*/
@Deprecated
@SuppressWarnings("all")
public interface NSyncHttpClient extends NHttpClient {

View File

@ -29,7 +29,9 @@ import java.lang.reflect.Type;
* Nacos async http client.
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
* @deprecated Refer to the new {@link com.alibaba.nacos.common.http.client.request.DefaultAsyncHttpClientRequest}
*/
@Deprecated
class NacosAsyncHttpClient extends BaseHttpClient implements NAsyncHttpClient {
private CloseableHttpAsyncClient asyncClient;

View File

@ -30,7 +30,9 @@ import java.lang.reflect.Type;
* Nacos sync http client.
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
* @deprecated Refer to the new {@link com.alibaba.nacos.common.http.client.request.JdkHttpClientRequest}
*/
@Deprecated
class NacosSyncHttpClient extends BaseHttpClient implements NSyncHttpClient {
private CloseableHttpClient client;

View File

@ -61,34 +61,11 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
* @param header http header param
* @param query http query param
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void get(String url, Header header, Query query, Type responseType, Callback<T> callback)
throws Exception {
public <T> void get(String url, Header header, Query query, Type responseType, Callback<T> callback) {
execute(url, HttpMethod.GET, new RequestHttpEntity(header, query), responseType, callback);
}
/**
* async http get URL request params are expanded using the given map {@code paramValues}.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
*
* <p>{@code callback} Result callback execution
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header headers
* @param paramValues paramValues
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void get(String url, Header header, Map<String, String> paramValues, Type responseType,
Callback<T> callback) throws Exception {
execute(url, HttpMethod.GET, new RequestHttpEntity(header, Query.newInstance().initParams(paramValues)),
responseType, callback);
}
/**
* async get request, may be pulling a lot of data URL request params are expanded using the given query {@link
* Query}, More request parameters can be set via body.
@ -104,10 +81,9 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
* @param body get with body
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void getLarge(String url, Header header, Query query, Object body, Type responseType,
Callback<T> callback) throws Exception {
Callback<T> callback) {
execute(url, HttpMethod.GET_LARGE, new RequestHttpEntity(header, query, body), responseType, callback);
}
@ -124,13 +100,32 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
* @param query http query param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void delete(String url, Header header, Query query, Type responseType, Callback<T> callback)
throws Exception {
public <T> void delete(String url, Header header, Query query, Type responseType, Callback<T> callback) {
execute(url, HttpMethod.DELETE, new RequestHttpEntity(header, query), responseType, callback);
}
/**
* async http delete large request, when the parameter exceeds the URL limit, you can use this method to put the
* parameter into the body pass.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type
*
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param body body
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
*/
public <T> void delete(String url, Header header, String body, Type responseType, Callback<T> callback) {
execute(url, HttpMethod.DELETE_LARGE,
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON), Query.EMPTY, body),
responseType, callback);
}
/**
* async http put Create a new resource by PUTting the given body to http request.
*
@ -147,10 +142,8 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
* @param body http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void put(String url, Header header, Query query, Object body, Type responseType, Callback<T> callback)
throws Exception {
public <T> void put(String url, Header header, Query query, Object body, Type responseType, Callback<T> callback) {
execute(url, HttpMethod.PUT, new RequestHttpEntity(header, query, body), responseType, callback);
}
@ -158,7 +151,7 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
* async http put Json Create a new resource by PUTting the given body to http request, http header contentType
* default 'application/json;charset=UTF-8'.
*
* <p>URL request params are expanded using the given map {@code paramValues}.
* <p>URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type
*
@ -167,16 +160,36 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
*
* @param url url
* @param header http header param
* @param paramValues http query param
* @param query http query param
* @param body http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void putJson(String url, Header header, Map<String, String> paramValues, String body, Type responseType,
Callback<T> callback) throws Exception {
execute(url, HttpMethod.PUT, new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON),
Query.newInstance().initParams(paramValues), body), responseType, callback);
public <T> void putJson(String url, Header header, Query query, String body, Type responseType,
Callback<T> callback) {
execute(url, HttpMethod.PUT,
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON), query, body), responseType,
callback);
}
/**
* async http put Json Create a new resource by PUTting the given body to http request, http header contentType
* default 'application/json;charset=UTF-8'.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type
*
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param body http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
*/
public <T> void putJson(String url, Header header, String body, Type responseType, Callback<T> callback) {
execute(url, HttpMethod.PUT, new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON), body),
responseType, callback);
}
/**
@ -196,10 +209,9 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
* @param bodyValues http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void putForm(String url, Header header, Query query, Map<String, String> bodyValues, Type responseType,
Callback<T> callback) throws Exception {
Callback<T> callback) {
execute(url, HttpMethod.PUT,
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues),
responseType, callback);
@ -209,8 +221,6 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
* async http put from Create a new resource by PUTting the given map {@code bodyValues} to http request, http
* header contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
*
* <p>URL request params are expanded using the given map {@code paramValues}.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
*
* <p>{@code callback} Result callback execution,
@ -218,16 +228,15 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
*
* @param url url
* @param header http header param
* @param paramValues http query param
* @param bodyValues http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void putForm(String url, Header header, Map<String, String> paramValues, Map<String, String> bodyValues,
Type responseType, Callback<T> callback) throws Exception {
execute(url, HttpMethod.PUT, new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
Query.newInstance().initParams(paramValues), bodyValues), responseType, callback);
public <T> void putForm(String url, Header header, Map<String, String> bodyValues, Type responseType,
Callback<T> callback) {
execute(url, HttpMethod.PUT,
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), bodyValues),
responseType, callback);
}
/**
@ -246,10 +255,8 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
* @param body http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void post(String url, Header header, Query query, Object body, Type responseType, Callback<T> callback)
throws Exception {
public <T> void post(String url, Header header, Query query, Object body, Type responseType, Callback<T> callback) {
execute(url, HttpMethod.POST, new RequestHttpEntity(header, query, body), responseType, callback);
}
@ -257,7 +264,7 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
* async http post Json Create a new resource by POSTing the given object to the http request, http header
* contentType default 'application/json;charset=UTF-8'.
*
* <p>URL request params are expanded using the given map {@code paramValues}.
* <p>URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
*
@ -266,16 +273,36 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
*
* @param url url
* @param header http header param
* @param paramValues http query param
* @param query http query param
* @param body http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void postJson(String url, Header header, Map<String, String> paramValues, String body, Type responseType,
Callback<T> callback) throws Exception {
execute(url, HttpMethod.POST, new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON),
Query.newInstance().initParams(paramValues), body), responseType, callback);
public <T> void postJson(String url, Header header, Query query, String body, Type responseType,
Callback<T> callback) {
execute(url, HttpMethod.POST,
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON), query, body), responseType,
callback);
}
/**
* async http post Json Create a new resource by POSTing the given object to the http request, http header
* contentType default 'application/json;charset=UTF-8'.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
*
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param body http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
*/
public <T> void postJson(String url, Header header, String body, Type responseType, Callback<T> callback) {
execute(url, HttpMethod.POST, new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON), body),
responseType, callback);
}
/**
@ -295,10 +322,9 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
* @param bodyValues http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void postForm(String url, Header header, Query query, Map<String, String> bodyValues, Type responseType,
Callback<T> callback) throws Exception {
Callback<T> callback) {
execute(url, HttpMethod.POST,
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues),
responseType, callback);
@ -308,8 +334,6 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
* async http post from Create a new resource by PUTting the given map {@code bodyValues} to http request, http
* header contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
*
* <p>URL request params are expanded using the given map {@code paramValues}.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
*
* <p>{@code callback} Result callback execution,
@ -317,29 +341,31 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
*
* @param url url
* @param header http header param
* @param paramValues http query param
* @param bodyValues http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void postForm(String url, Header header, Map<String, String> paramValues, Map<String, String> bodyValues,
Type responseType, Callback<T> callback) throws Exception {
public <T> void postForm(String url, Header header, Map<String, String> bodyValues, Type responseType,
Callback<T> callback) {
execute(url, HttpMethod.POST,
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
Query.newInstance().initParams(paramValues), bodyValues), responseType, callback);
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), bodyValues),
responseType, callback);
}
@SuppressWarnings("unchecked")
private <T> void execute(String url, String httpMethod, RequestHttpEntity requestEntity, Type type,
Callback<T> callback) throws Exception {
URI uri = HttpUtils.buildUri(url, requestEntity.getQuery());
if (logger.isDebugEnabled()) {
logger.debug("HTTP method: {}, url: {}, body: {}", httpMethod, uri, requestEntity.getBody());
Callback<T> callback) {
try {
URI uri = HttpUtils.buildUri(url, requestEntity.getQuery());
if (logger.isDebugEnabled()) {
logger.debug("HTTP method: {}, url: {}, body: {}", httpMethod, uri, requestEntity.getBody());
}
ResponseHandler<T> responseHandler = super.selectResponseHandler(type);
clientRequest.execute(uri, httpMethod, requestEntity, responseHandler, callback);
} catch (Exception e) {
// When an exception occurs, use Callback to pass it instead of throw it directly.
callback.onError(e);
}
ResponseHandler<T> responseHandler = super.selectResponseHandler(type);
clientRequest.execute(uri, httpMethod, requestEntity, responseHandler, callback);
}
/**

View File

@ -20,7 +20,9 @@ import com.alibaba.nacos.common.http.HttpClientConfig;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.HttpUtils;
import com.alibaba.nacos.common.http.client.handler.ResponseHandler;
import com.alibaba.nacos.common.http.client.request.DefaultHttpClientRequest;
import com.alibaba.nacos.common.http.client.request.HttpClientRequest;
import com.alibaba.nacos.common.http.client.request.JdkHttpClientRequest;
import com.alibaba.nacos.common.http.client.response.HttpClientResponse;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.MediaType;
@ -70,25 +72,6 @@ public class NacosRestTemplate extends AbstractNacosRestTemplate {
return execute(url, HttpMethod.GET, new RequestHttpEntity(header, query), responseType);
}
/**
* http get URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header headers
* @param paramValues paramValues
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> get(String url, Header header, Map<String, String> paramValues, Type responseType)
throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(header,
Query.newInstance().initParams(paramValues));
return execute(url, HttpMethod.GET, requestHttpEntity, responseType);
}
/**
* http get URL request params are expanded using the given query {@link Query}.
*
@ -99,15 +82,14 @@ public class NacosRestTemplate extends AbstractNacosRestTemplate {
* @param url url
* @param config http config
* @param header headers
* @param paramValues paramValues
* @param query http query param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> get(String url, HttpClientConfig config, Header header,
Map<String, String> paramValues, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(config, header,
Query.newInstance().initParams(paramValues));
public <T> HttpRestResult<T> get(String url, HttpClientConfig config, Header header, Query query, Type responseType)
throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(config, header, query);
return execute(url, HttpMethod.GET, requestHttpEntity, responseType);
}
@ -115,6 +97,9 @@ public class NacosRestTemplate extends AbstractNacosRestTemplate {
* get request, may be pulling a lot of data URL request params are expanded using the given query {@link Query},
* More request parameters can be set via body.
*
* <p>This method can only be used when HttpClientRequest is implemented by {@link DefaultHttpClientRequest}, note:
* {@link JdkHttpClientRequest} Implementation does not support this method.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
@ -156,15 +141,14 @@ public class NacosRestTemplate extends AbstractNacosRestTemplate {
* @param url url
* @param config http config
* @param header http header param
* @param paramValues http query param
* @param query http query param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> delete(String url, HttpClientConfig config, Header header,
Map<String, String> paramValues, Type responseType) throws Exception {
return execute(url, HttpMethod.DELETE,
new RequestHttpEntity(config, header, Query.newInstance().initParams(paramValues)), responseType);
public <T> HttpRestResult<T> delete(String url, HttpClientConfig config, Header header, Query query,
Type responseType) throws Exception {
return execute(url, HttpMethod.DELETE, new RequestHttpEntity(config, header, query), responseType);
}
/**
@ -191,22 +175,41 @@ public class NacosRestTemplate extends AbstractNacosRestTemplate {
* http put json Create a new resource by PUTting the given body to http request, http header contentType default
* 'application/json;charset=UTF-8'.
*
* <p>URL request params are expanded using the given map {@code paramValues}.
* <p>URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param paramValues http query param
* @param query http query param
* @param body http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> putJson(String url, Header header, Map<String, String> paramValues, String body,
Type responseType) throws Exception {
public <T> HttpRestResult<T> putJson(String url, Header header, Query query, String body, Type responseType)
throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON),
Query.newInstance().initParams(paramValues), body);
query, body);
return execute(url, HttpMethod.PUT, requestHttpEntity, responseType);
}
/**
* http put json Create a new resource by PUTting the given body to http request, http header contentType default
* 'application/json;charset=UTF-8'.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param body http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> putJson(String url, Header header, String body, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON),
body);
return execute(url, HttpMethod.PUT, requestHttpEntity, responseType);
}
@ -237,23 +240,19 @@ public class NacosRestTemplate extends AbstractNacosRestTemplate {
* http put from Create a new resource by PUTting the given map {@code bodyValues} to http request, http header
* contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
*
* <p>URL request params are expanded using the given map {@code paramValues}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param paramValues http query param
* @param bodyValues http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> putForm(String url, Header header, Map<String, String> paramValues,
Map<String, String> bodyValues, Type responseType) throws Exception {
public <T> HttpRestResult<T> putForm(String url, Header header, Map<String, String> bodyValues, Type responseType)
throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
Query.newInstance().initParams(paramValues), bodyValues);
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), bodyValues);
return execute(url, HttpMethod.PUT, requestHttpEntity, responseType);
}
@ -261,8 +260,6 @@ public class NacosRestTemplate extends AbstractNacosRestTemplate {
* http put from Create a new resource by PUTting the given map {@code bodyValues} to http request, http header
* contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
*
* <p>URL request params are expanded using the given map {@code paramValues}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* <p>{@code config} Specify the request config via {@link HttpClientConfig}
@ -270,17 +267,15 @@ public class NacosRestTemplate extends AbstractNacosRestTemplate {
* @param url url
* @param config http config
* @param header http header param
* @param paramValues http query param
* @param bodyValues http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> putForm(String url, HttpClientConfig config, Header header,
Map<String, String> paramValues, Map<String, String> bodyValues, Type responseType) throws Exception {
Map<String, String> bodyValues, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(config,
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
Query.newInstance().initParams(paramValues), bodyValues);
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), bodyValues);
return execute(url, HttpMethod.PUT, requestHttpEntity, responseType);
}
@ -308,22 +303,41 @@ public class NacosRestTemplate extends AbstractNacosRestTemplate {
* http post json Create a new resource by POSTing the given object to the http request, http header contentType
* default 'application/json;charset=UTF-8'.
*
* <p>URL request params are expanded using the given map {@code paramValues}.
* <p>URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param paramValues http query param
* @param query http query param
* @param body http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> postJson(String url, Header header, Map<String, String> paramValues, String body,
Type responseType) throws Exception {
public <T> HttpRestResult<T> postJson(String url, Header header, Query query, String body, Type responseType)
throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON),
Query.newInstance().initParams(paramValues), body);
query, body);
return execute(url, HttpMethod.POST, requestHttpEntity, responseType);
}
/**
* http post json Create a new resource by POSTing the given object to the http request, http header contentType
* default 'application/json;charset=UTF-8'.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param body http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> postJson(String url, Header header, String body, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON),
body);
return execute(url, HttpMethod.POST, requestHttpEntity, responseType);
}
@ -354,23 +368,19 @@ public class NacosRestTemplate extends AbstractNacosRestTemplate {
* http post from Create a new resource by PUTting the given map {@code bodyValues} to http request, http header
* contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
*
* <p>URL request params are expanded using the given map {@code paramValues}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param paramValues http query param
* @param bodyValues http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> postForm(String url, Header header, Map<String, String> paramValues,
Map<String, String> bodyValues, Type responseType) throws Exception {
public <T> HttpRestResult<T> postForm(String url, Header header, Map<String, String> bodyValues, Type responseType)
throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
Query.newInstance().initParams(paramValues), bodyValues);
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), bodyValues);
return execute(url, HttpMethod.POST, requestHttpEntity, responseType);
}
@ -378,8 +388,6 @@ public class NacosRestTemplate extends AbstractNacosRestTemplate {
* http post from Create a new resource by PUTting the given map {@code bodyValues} to http request, http header
* contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
*
* <p>URL request params are expanded using the given map {@code paramValues}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* <p>{@code config} Specify the request config via {@link HttpClientConfig}
@ -387,17 +395,15 @@ public class NacosRestTemplate extends AbstractNacosRestTemplate {
* @param url url
* @param config http config
* @param header http header param
* @param paramValues http query param
* @param bodyValues http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> postForm(String url, HttpClientConfig config, Header header,
Map<String, String> paramValues, Map<String, String> bodyValues, Type responseType) throws Exception {
Map<String, String> bodyValues, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(config,
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
Query.newInstance().initParams(paramValues), bodyValues);
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), bodyValues);
return execute(url, HttpMethod.POST, requestHttpEntity, responseType);
}
@ -407,18 +413,37 @@ public class NacosRestTemplate extends AbstractNacosRestTemplate {
*
* @param url url
* @param header http header param
* @param paramValues http query param
* @param query http query param
* @param bodyValues http body param
* @param httpMethod http method
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> exchangeForm(String url, Header header, Map<String, String> paramValues,
Map<String, String> bodyValues, String httpMethod, Type responseType) throws Exception {
public <T> HttpRestResult<T> exchangeForm(String url, Header header, Query query, Map<String, String> bodyValues,
String httpMethod, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
Query.newInstance().initParams(paramValues), bodyValues);
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues);
return execute(url, httpMethod, requestHttpEntity, responseType);
}
/**
* Execute the HTTP method to the given URI template, writing the given request entity to the request, and returns
* the response as {@link HttpRestResult}.
*
* @param url url
* @param config HttpClientConfig
* @param header http header param
* @param query http query param
* @param body http body param
* @param httpMethod http method
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> exchange(String url, HttpClientConfig config, Header header, Query query,
Object body, String httpMethod, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(config, header, query, body);
return execute(url, httpMethod, requestHttpEntity, responseType);
}
@ -450,7 +475,7 @@ public class NacosRestTemplate extends AbstractNacosRestTemplate {
if (logger.isDebugEnabled()) {
logger.debug("HTTP method: {}, url: {}, body: {}", httpMethod, uri, requestEntity.getBody());
}
ResponseHandler<T> responseHandler = super.selectResponseHandler(responseType);
HttpClientResponse response = null;
try {

View File

@ -65,7 +65,7 @@ public class DefaultHttpClientRequest implements HttpClientRequest {
&& requestHttpEntity.getBody() instanceof Map) {
HttpUtils.initRequestFromEntity(httpRequestBase, (Map<String, String>) requestHttpEntity.getBody(), headers.getCharset());
} else {
HttpUtils.initRequestEntity(httpRequestBase, requestHttpEntity.getBody(), headers.getValue(HttpHeaderConsts.CONTENT_TYPE));
HttpUtils.initRequestEntity(httpRequestBase, requestHttpEntity.getBody(), headers);
}
replaceDefaultConfig(httpRequestBase, requestHttpEntity.getHttpClientConfig());
return httpRequestBase;

View File

@ -26,6 +26,9 @@ import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.model.RequestHttpEntity;
import com.alibaba.nacos.common.utils.JacksonUtils;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URI;
@ -45,6 +48,30 @@ public class JdkHttpClientRequest implements HttpClientRequest {
this.httpClientConfig = httpClientConfig;
}
/**
* Use specified {@link SSLContext}.
*
* @param sslContext ssl context
*/
@SuppressWarnings("checkstyle:abbreviationaswordinname")
public void setSSLContext(SSLContext sslContext) {
if (sslContext != null) {
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
}
}
/**
* Replace the default HostnameVerifier.
*
* @param hostnameVerifier custom hostnameVerifier
*/
@SuppressWarnings("checkstyle:abbreviationaswordinname")
public void replaceSSLHostnameVerifier(HostnameVerifier hostnameVerifier) {
if (hostnameVerifier != null) {
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
}
}
@Override
public HttpClientResponse execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity)
throws Exception {
@ -63,7 +90,7 @@ public class JdkHttpClientRequest implements HttpClientRequest {
conn.setConnectTimeout(this.httpClientConfig.getConTimeOutMillis());
conn.setReadTimeout(this.httpClientConfig.getReadTimeOutMillis());
conn.setRequestMethod(httpMethod);
if (body != null) {
if (body != null && !"".equals(body)) {
String contentType = headers.getValue(HttpHeaderConsts.CONTENT_TYPE);
String bodyStr = JacksonUtils.toJson(body);
if (MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)) {

View File

@ -16,9 +16,11 @@
package com.alibaba.nacos.common.http.client.response;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.utils.IoUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
@ -36,6 +38,8 @@ public class JdkHttpClientResponse implements HttpClientResponse {
private Header responseHeader;
private static final String CONTENT_ENCODING = "gzip";
public JdkHttpClientResponse(HttpURLConnection conn) {
this.conn = conn;
}
@ -51,8 +55,18 @@ public class JdkHttpClientResponse implements HttpClientResponse {
@Override
public InputStream getBody() throws IOException {
Header headers = getHeaders();
InputStream errorStream = this.conn.getErrorStream();
this.responseStream = (errorStream != null ? errorStream : this.conn.getInputStream());
String contentEncoding = headers.getValue(HttpHeaderConsts.CONTENT_ENCODING);
// Used to process http content_encoding, when content_encoding is GZIP, use GZIPInputStream
if (CONTENT_ENCODING.equals(contentEncoding)) {
byte[] bytes = IoUtils.tryDecompress(this.responseStream);
if (bytes == null) {
throw new IOException("decompress http response error");
}
return new ByteArrayInputStream(bytes);
}
return this.responseStream;
}

View File

@ -18,6 +18,7 @@ package com.alibaba.nacos.common.http.param;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.utils.MapUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import java.util.ArrayList;
@ -45,15 +46,23 @@ public class Header {
addParam(HttpHeaderConsts.CONTENT_TYPE, MediaType.APPLICATION_JSON);
addParam(HttpHeaderConsts.ACCEPT_CHARSET, "UTF-8");
addParam(HttpHeaderConsts.ACCEPT_ENCODING, "gzip");
addParam(HttpHeaderConsts.CONTENT_ENCODING, "gzip");
}
public static Header newInstance() {
return new Header();
}
/**
* Add the key and value to the header.
*
* @param key the key
* @param value the value
* @return header
*/
public Header addParam(String key, String value) {
header.put(key, value);
if (StringUtils.isNotEmpty(key)) {
header.put(key, value);
}
return this;
}
@ -107,7 +116,10 @@ public class Header {
throw new IllegalArgumentException("list size must be a multiple of 2");
}
for (int i = 0; i < list.size(); ) {
header.put(list.get(i++), list.get(i++));
String key = list.get(i++);
if (StringUtils.isNotEmpty(key)) {
header.put(key, list.get(i++));
}
}
return this;
}
@ -118,8 +130,10 @@ public class Header {
* @param params parameters
*/
public void addAll(Map<String, String> params) {
for (Map.Entry<String, String> entry : params.entrySet()) {
addParam(entry.getKey(), entry.getValue());
if (MapUtils.isNotEmpty(params)) {
for (Map.Entry<String, String> entry : params.entrySet()) {
addParam(entry.getKey(), entry.getValue());
}
}
}
@ -131,9 +145,11 @@ public class Header {
* @param headers original response header
*/
public void setOriginalResponseHeader(Map<String, List<String>> headers) {
this.originalResponseHeader.putAll(headers);
for (Map.Entry<String, List<String>> entry : this.originalResponseHeader.entrySet()) {
addParam(entry.getKey(), entry.getValue().get(0));
if (MapUtils.isNotEmpty(headers)) {
this.originalResponseHeader.putAll(headers);
for (Map.Entry<String, List<String>> entry : this.originalResponseHeader.entrySet()) {
addParam(entry.getKey(), entry.getValue().get(0));
}
}
}

View File

@ -16,6 +16,9 @@
package com.alibaba.nacos.common.http.param;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.common.utils.StringUtils;
/**
* Http Media type.
*
@ -23,12 +26,9 @@ package com.alibaba.nacos.common.http.param;
*/
public final class MediaType {
private MediaType() {
}
public static final String APPLICATION_ATOM_XML = "application/atom+xml";
public static final String APPLICATION_FORM_URLENCODED = "application/x-www-form-urlencoded";
public static final String APPLICATION_FORM_URLENCODED = "application/x-www-form-urlencoded;charset=UTF-8";
public static final String APPLICATION_OCTET_STREAM = "application/octet-stream";
@ -36,14 +36,76 @@ public final class MediaType {
public static final String APPLICATION_XHTML_XML = "application/xhtml+xml";
public static final String APPLICATION_XML = "application/xml";
public static final String APPLICATION_XML = "application/xml;charset=UTF-8";
public static final String APPLICATION_JSON = "application/json";
public static final String APPLICATION_JSON = "application/json;charset=UTF-8";
public static final String MULTIPART_FORM_DATA = "multipart/form-data";
public static final String MULTIPART_FORM_DATA = "multipart/form-data;charset=UTF-8";
public static final String TEXT_HTML = "text/html";
public static final String TEXT_HTML = "text/html;charset=UTF-8";
public static final String TEXT_PLAIN = "text/plain";
public static final String TEXT_PLAIN = "text/plain;charset=UTF-8";
private MediaType(String type, String charset) {
this.type = type;
this.charset = charset;
}
/**
* content type.
*/
private final String type;
/**
* content type charset.
*/
private final String charset;
/**
* Parse the given String contentType into a {@code MediaType} object.
*
* @param contentType mediaType
* @return MediaType
*/
public static MediaType valueOf(String contentType) {
if (StringUtils.isEmpty(contentType)) {
throw new IllegalArgumentException("MediaType must not be empty");
}
String[] values = contentType.split(";");
String charset = Constants.ENCODE;
for (String value : values) {
if (value.startsWith("charset=")) {
charset = value.substring("charset=".length());
}
}
return new MediaType(values[0], charset);
}
/**
* Use the given contentType and charset to assemble into a {@code MediaType} object.
*
* @param contentType contentType
* @param charset charset
* @return MediaType
*/
public static MediaType valueOf(String contentType, String charset) {
if (StringUtils.isEmpty(contentType)) {
throw new IllegalArgumentException("MediaType must not be empty");
}
String[] values = contentType.split(";");
return new MediaType(values[0], StringUtils.isEmpty(charset) ? Constants.ENCODE : charset);
}
public String getType() {
return type;
}
public String getCharset() {
return charset;
}
@Override
public String toString() {
return type + ";charset=" + charset;
}
}

View File

@ -16,6 +16,8 @@
package com.alibaba.nacos.common.http.param;
import com.alibaba.nacos.common.utils.MapUtils;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.LinkedHashMap;
@ -68,8 +70,10 @@ public class Query {
* @return this query
*/
public Query initParams(Map<String, String> params) {
for (Map.Entry<String, String> entry : params.entrySet()) {
addParam(entry.getKey(), entry.getValue());
if (MapUtils.isNotEmpty(params)) {
for (Map.Entry<String, String> entry : params.entrySet()) {
addParam(entry.getKey(), entry.getValue());
}
}
return this;
}

View File

@ -26,7 +26,6 @@ import java.util.Map;
* Represents an HTTP request , consisting of headers and body.
*
* @author mai.jh
* @date 2020/5/23
*/
public class RequestHttpEntity {
@ -36,18 +35,26 @@ public class RequestHttpEntity {
private final Query query;
private Object body;
private final Object body;
public RequestHttpEntity(Header header, Query query) {
this(null, header, query);
}
public RequestHttpEntity(Header header, Object body) {
this(null, header, null, body);
}
public RequestHttpEntity(Header header, Query query, Object body) {
this(null, header, query, body);
}
public RequestHttpEntity(HttpClientConfig httpClientConfig, Header header, Query query) {
this(httpClientConfig, header, query, null);
}
public RequestHttpEntity(Header header, Query query, Object body) {
this(null, header, query, body);
public RequestHttpEntity(HttpClientConfig httpClientConfig, Header header, Object body) {
this(httpClientConfig, header, null, body);
}
public RequestHttpEntity(HttpClientConfig httpClientConfig, Header header, Query query, Object body) {

View File

@ -56,7 +56,7 @@ public class DefaultPublisher extends Thread implements EventPublisher {
protected volatile Long lastEventSequence = -1L;
private final AtomicReferenceFieldUpdater<DefaultPublisher, Long> updater = AtomicReferenceFieldUpdater
private static final AtomicReferenceFieldUpdater<DefaultPublisher, Long> UPDATER = AtomicReferenceFieldUpdater
.newUpdater(DefaultPublisher.class, Long.class, "lastEventSequence");
@Override
@ -115,7 +115,7 @@ public class DefaultPublisher extends Thread implements EventPublisher {
}
final Event event = queue.take();
receiveEvent(event);
updater.compareAndSet(this, lastEventSequence, Math.max(lastEventSequence, event.sequence()));
UPDATER.compareAndSet(this, lastEventSequence, Math.max(lastEventSequence, event.sequence()));
}
} catch (Throwable ex) {
LOGGER.error("Event listener exception : {}", ex);

View File

@ -96,6 +96,10 @@ public class DefaultSharePublisher extends DefaultPublisher {
// Get for Map, the algorithm is O(1).
Set<Subscriber> subscribers = subMappings.get(slowEventType);
if (null == subscribers) {
LOGGER.debug("[NotifyCenter] No subscribers for slow event {}", slowEventType.getName());
return;
}
// Notification single event subscriber
for (Subscriber subscriber : subscribers) {

View File

@ -14,14 +14,15 @@
* limitations under the License.
*/
package com.alibaba.nacos.config.server.manager;
package com.alibaba.nacos.common.task;
/**
* AbstractTask.
* Abstract task which can delay and merge.
*
* @author huali
* @author xiweng.yy
*/
public abstract class AbstractTask {
public abstract class AbstractDelayTask implements NacosTask {
/**
* Task time interval between twice processing, unit is millisecond.
@ -38,7 +39,7 @@ public abstract class AbstractTask {
*
* @param task task
*/
public abstract void merge(AbstractTask task);
public abstract void merge(AbstractDelayTask task);
public void setTaskInterval(long interval) {
this.taskInterval = interval;
@ -56,11 +57,7 @@ public abstract class AbstractTask {
return this.lastProcessTime;
}
/**
* TaskManager judge whether to process current this task, subclass could override and implement the logical codes.
*
* @return the result whether to process.
*/
@Override
public boolean shouldProcess() {
return (System.currentTimeMillis() - this.lastProcessTime >= this.taskInterval);
}

View File

@ -0,0 +1,30 @@
/*
* 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.task;
/**
* Abstract task which should be executed immediately.
*
* @author xiweng.yy
*/
public abstract class AbstractExecuteTask implements NacosTask, Runnable {
@Override
public boolean shouldProcess() {
return true;
}
}

View File

@ -0,0 +1,32 @@
/*
* 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.task;
/**
* Nacos task.
*
* @author xiweng.yy
*/
public interface NacosTask {
/**
* Judge Whether this nacos task should do.
*
* @return true means the nacos task should be done, otherwise false
*/
boolean shouldProcess();
}

View File

@ -14,21 +14,20 @@
* limitations under the License.
*/
package com.alibaba.nacos.config.server.manager;
package com.alibaba.nacos.common.task;
/**
* Task processor.
*
* @author Nacos
*/
public interface TaskProcessor {
public interface NacosTaskProcessor {
/**
* Process task.
*
* @param taskType task type.
* @param task task.
* @return process task result.
*/
boolean process(String taskType, AbstractTask task);
boolean process(NacosTask task);
}

View File

@ -0,0 +1,72 @@
/*
* 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.task.engine;
import com.alibaba.nacos.common.task.NacosTask;
import com.alibaba.nacos.common.task.NacosTaskProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
/**
* Abstract nacos task execute engine.
*
* @author xiweng.yy
*/
public abstract class AbstractNacosTaskExecuteEngine<T extends NacosTask> implements NacosTaskExecuteEngine<T> {
private final Logger log;
private final ConcurrentHashMap<Object, NacosTaskProcessor> taskProcessors = new ConcurrentHashMap<Object, NacosTaskProcessor>();
private NacosTaskProcessor defaultTaskProcessor;
public AbstractNacosTaskExecuteEngine(Logger logger) {
this.log = null != logger ? logger : LoggerFactory.getLogger(AbstractNacosTaskExecuteEngine.class.getName());
}
@Override
public void addProcessor(Object key, NacosTaskProcessor taskProcessor) {
taskProcessors.putIfAbsent(key, taskProcessor);
}
@Override
public void removeProcessor(Object key) {
taskProcessors.remove(key);
}
@Override
public NacosTaskProcessor getProcessor(Object key) {
return taskProcessors.containsKey(key) ? taskProcessors.get(key) : defaultTaskProcessor;
}
@Override
public Collection<Object> getAllProcessorKey() {
return taskProcessors.keySet();
}
@Override
public void setDefaultTaskProcessor(NacosTaskProcessor defaultTaskProcessor) {
this.defaultTaskProcessor = defaultTaskProcessor;
}
protected Logger getEngineLog() {
return log;
}
}

View File

@ -0,0 +1,179 @@
/*
* 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.task.engine;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.common.executor.ExecutorFactory;
import com.alibaba.nacos.common.executor.NameThreadFactory;
import com.alibaba.nacos.common.task.AbstractDelayTask;
import com.alibaba.nacos.common.task.NacosTaskProcessor;
import org.slf4j.Logger;
import java.util.Collection;
import java.util.HashSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
/**
* Nacos delay task execute engine.
*
* @author xiweng.yy
*/
public class NacosDelayTaskExecuteEngine extends AbstractNacosTaskExecuteEngine<AbstractDelayTask> {
private final ScheduledExecutorService processingExecutor;
protected final ConcurrentHashMap<Object, AbstractDelayTask> tasks;
protected final ReentrantLock lock = new ReentrantLock();
public NacosDelayTaskExecuteEngine(String name) {
this(name, null);
}
public NacosDelayTaskExecuteEngine(String name, Logger logger) {
this(name, 32, logger, 100L);
}
public NacosDelayTaskExecuteEngine(String name, Logger logger, long processInterval) {
this(name, 32, logger, processInterval);
}
public NacosDelayTaskExecuteEngine(String name, int initCapacity, Logger logger) {
this(name, initCapacity, logger, 100L);
}
public NacosDelayTaskExecuteEngine(String name, int initCapacity, Logger logger, long processInterval) {
super(logger);
tasks = new ConcurrentHashMap<Object, AbstractDelayTask>(initCapacity);
processingExecutor = ExecutorFactory.newSingleScheduledExecutorService(new NameThreadFactory(name));
processingExecutor
.scheduleWithFixedDelay(new ProcessRunnable(), processInterval, processInterval, TimeUnit.MILLISECONDS);
}
@Override
public int size() {
lock.lock();
try {
return tasks.size();
} finally {
lock.unlock();
}
}
@Override
public boolean isEmpty() {
lock.lock();
try {
return tasks.isEmpty();
} finally {
lock.unlock();
}
}
@Override
public AbstractDelayTask removeTask(Object key) {
lock.lock();
try {
AbstractDelayTask task = tasks.get(key);
if (null != task && task.shouldProcess()) {
return tasks.remove(key);
} else {
return null;
}
} finally {
lock.unlock();
}
}
@Override
public Collection<Object> getAllTaskKeys() {
Collection<Object> keys = new HashSet<Object>();
lock.lock();
try {
keys.addAll(tasks.keySet());
} finally {
lock.unlock();
}
return keys;
}
@Override
public void shutdown() throws NacosException {
processingExecutor.shutdown();
}
@Override
public void addTask(Object key, AbstractDelayTask newTask) {
lock.lock();
try {
AbstractDelayTask existTask = tasks.get(key);
if (null != existTask) {
newTask.merge(existTask);
}
tasks.put(key, newTask);
} finally {
lock.unlock();
}
}
/**
* process tasks in execute engine.
*/
protected void processTasks() {
Collection<Object> keys = getAllTaskKeys();
for (Object taskKey : keys) {
AbstractDelayTask task = removeTask(taskKey);
if (null == task) {
continue;
}
NacosTaskProcessor processor = getProcessor(taskKey);
if (null == processor) {
getEngineLog().error("processor not found for task, so discarded. " + task);
continue;
}
try {
// ReAdd task if process failed
if (!processor.process(task)) {
retryFailedTask(taskKey, task);
}
} catch (Throwable e) {
getEngineLog().error("Nacos task execute error : " + e.toString(), e);
retryFailedTask(taskKey, task);
}
}
}
private void retryFailedTask(Object key, AbstractDelayTask task) {
task.setLastProcessTime(System.currentTimeMillis());
addTask(key, task);
}
private class ProcessRunnable implements Runnable {
@Override
public void run() {
try {
processTasks();
} catch (Throwable e) {
getEngineLog().error(e.toString(), e);
}
}
}
}

View File

@ -0,0 +1,111 @@
/*
* 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.task.engine;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.common.task.AbstractExecuteTask;
import com.alibaba.nacos.common.task.NacosTaskProcessor;
import com.alibaba.nacos.common.utils.ThreadUtils;
import org.slf4j.Logger;
import java.util.Collection;
/**
* Nacos execute task execute engine.
*
* @author xiweng.yy
*/
public class NacosExecuteTaskExecuteEngine extends AbstractNacosTaskExecuteEngine<AbstractExecuteTask> {
private final TaskExecuteWorker[] executeWorkers;
public NacosExecuteTaskExecuteEngine(String name, Logger logger) {
this(name, logger, ThreadUtils.getSuitableThreadCount(1));
}
public NacosExecuteTaskExecuteEngine(String name, Logger logger, int dispatchWorkerCount) {
super(logger);
executeWorkers = new TaskExecuteWorker[dispatchWorkerCount];
for (int mod = 0; mod < dispatchWorkerCount; ++mod) {
executeWorkers[mod] = new TaskExecuteWorker(name, mod, dispatchWorkerCount, getEngineLog());
}
}
@Override
public int size() {
int result = 0;
for (TaskExecuteWorker each : executeWorkers) {
result += each.pendingTaskCount();
}
return result;
}
@Override
public boolean isEmpty() {
return 0 == size();
}
@Override
public void addTask(Object tag, AbstractExecuteTask task) {
NacosTaskProcessor processor = getProcessor(tag);
if (null != processor) {
processor.process(task);
return;
}
TaskExecuteWorker worker = getWorker(tag);
worker.process(task);
}
private TaskExecuteWorker getWorker(Object tag) {
int idx = (tag.hashCode() & Integer.MAX_VALUE) % workersCount();
return executeWorkers[idx];
}
private int workersCount() {
return executeWorkers.length;
}
@Override
public AbstractExecuteTask removeTask(Object key) {
throw new UnsupportedOperationException("ExecuteTaskEngine do not support remove task");
}
@Override
public Collection<Object> getAllTaskKeys() {
throw new UnsupportedOperationException("ExecuteTaskEngine do not support get all task keys");
}
@Override
public void shutdown() throws NacosException {
for (TaskExecuteWorker each : executeWorkers) {
each.shutdown();
}
}
/**
* Get workers status.
*
* @return workers status string
*/
public String workersStatus() {
StringBuilder sb = new StringBuilder();
for (TaskExecuteWorker worker : executeWorkers) {
sb.append(worker.status()).append("\n");
}
return sb.toString();
}
}

View File

@ -0,0 +1,106 @@
/*
* 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.task.engine;
import com.alibaba.nacos.common.lifecycle.Closeable;
import com.alibaba.nacos.common.task.NacosTask;
import com.alibaba.nacos.common.task.NacosTaskProcessor;
import java.util.Collection;
/**
* Nacos task execute engine.
*
* @author xiweng.yy
*/
public interface NacosTaskExecuteEngine<T extends NacosTask> extends Closeable {
/**
* Get Task size in execute engine.
*
* @return size of task
*/
int size();
/**
* Whether the execute engine is empty.
*
* @return true if the execute engine has no task to do, otherwise false
*/
boolean isEmpty();
/**
* Add task processor {@link NacosTaskProcessor} for execute engine.
*
* @param key key of task
* @param taskProcessor task processor
*/
void addProcessor(Object key, NacosTaskProcessor taskProcessor);
/**
* Remove task processor {@link NacosTaskProcessor} form execute engine for key.
*
* @param key key of task
*/
void removeProcessor(Object key);
/**
* Try to get {@link NacosTaskProcessor} by key, if non-exist, will return default processor.
*
* @param key key of task
* @return task processor for task key or default processor if task processor for task key non-exist
*/
NacosTaskProcessor getProcessor(Object key);
/**
* Get all processor key.
*
* @return collection of processors
*/
Collection<Object> getAllProcessorKey();
/**
* Set default task processor. If do not find task processor by task key, use this default processor to process
* task.
*
* @param defaultTaskProcessor default task processor
*/
void setDefaultTaskProcessor(NacosTaskProcessor defaultTaskProcessor);
/**
* Add task into execute pool.
*
* @param key key of task
* @param task task
*/
void addTask(Object key, T task);
/**
* Remove task.
*
* @param key key of task
* @return nacos task
*/
T removeTask(Object key);
/**
* Get all task keys.
*
* @return collection of task keys.
*/
Collection<Object> getAllTaskKeys();
}

View File

@ -0,0 +1,127 @@
/*
* 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.task.engine;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.common.lifecycle.Closeable;
import com.alibaba.nacos.common.task.AbstractExecuteTask;
import com.alibaba.nacos.common.task.NacosTask;
import com.alibaba.nacos.common.task.NacosTaskProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Nacos execute task execute worker.
*
* @author xiweng.yy
*/
public final class TaskExecuteWorker implements NacosTaskProcessor, Closeable {
/**
* Max task queue size 32768.
*/
private static final int QUEUE_CAPACITY = 1 << 15;
private final Logger log;
private final String name;
private final BlockingQueue<Runnable> queue;
private final AtomicBoolean closed;
public TaskExecuteWorker(final String name, final int mod, final int total) {
this(name, mod, total, null);
}
public TaskExecuteWorker(final String name, final int mod, final int total, final Logger logger) {
this.name = name + "_" + mod + "%" + total;
this.queue = new ArrayBlockingQueue<Runnable>(QUEUE_CAPACITY);
this.closed = new AtomicBoolean(false);
this.log = null == logger ? LoggerFactory.getLogger(TaskExecuteWorker.class) : logger;
new InnerWorker(name).start();
}
public String getName() {
return name;
}
@Override
public boolean process(NacosTask task) {
if (task instanceof AbstractExecuteTask) {
putTask((Runnable) task);
}
return true;
}
private void putTask(Runnable task) {
try {
queue.put(task);
} catch (InterruptedException ire) {
log.error(ire.toString(), ire);
}
}
public int pendingTaskCount() {
return queue.size();
}
/**
* Worker status.
*/
public String status() {
return name + ", pending tasks: " + pendingTaskCount();
}
@Override
public void shutdown() throws NacosException {
queue.clear();
closed.compareAndSet(false, true);
}
/**
* Inner execute worker.
*/
private class InnerWorker extends Thread {
InnerWorker(String name) {
setDaemon(false);
setName(name);
}
@Override
public void run() {
while (!closed.get()) {
try {
Runnable task = queue.take();
long begin = System.currentTimeMillis();
task.run();
long duration = System.currentTimeMillis() - begin;
if (duration > 1000L) {
log.warn("distro task {} takes {}ms", task, duration);
}
} catch (Throwable e) {
log.error("[DISTRO-FAILED] " + e.toString(), e);
}
}
}
}
}

View File

@ -0,0 +1,71 @@
/*
* 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.tls;
import com.alibaba.nacos.common.utils.IpUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
import java.util.concurrent.ConcurrentHashMap;
/**
* A HostnameVerifier verify ipv4 and localhost.
*
* @author wangwei
*/
public final class SelfHostnameVerifier implements HostnameVerifier {
private static final Logger LOGGER = LoggerFactory.getLogger(SelfHostnameVerifier.class);
private final HostnameVerifier hv;
private static ConcurrentHashMap<String, Boolean> hosts = new ConcurrentHashMap<String, Boolean>();
private static final String[] LOCALHOST_HOSTNAME = new String[] {"localhost", "127.0.0.1"};
public SelfHostnameVerifier(HostnameVerifier hv) {
this.hv = hv;
}
@Override
public boolean verify(String hostname, SSLSession session) {
if (LOCALHOST_HOSTNAME[0].equalsIgnoreCase(hostname) || LOCALHOST_HOSTNAME[1].equals(hostname)) {
return true;
}
if (isIpv4(hostname)) {
return true;
}
return hv.verify(hostname, session);
}
private static boolean isIpv4(String host) {
if (host == null || host.isEmpty()) {
LOGGER.warn("host is empty, isIPv4 = false");
return false;
}
Boolean cacheHostVerify = hosts.get(host);
if (cacheHostVerify != null) {
return cacheHostVerify;
}
boolean isIp = IpUtils.isIpv4(host);
hosts.putIfAbsent(host, isIp);
return isIp;
}
}

View File

@ -0,0 +1,112 @@
/*
* 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.tls;
import com.alibaba.nacos.common.utils.IoUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.SSLException;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Collection;
/**
* A TrustManager tool returns the specified TrustManager.
*
* @author wangwei
*/
public final class SelfTrustManager {
private static final Logger LOGGER = LoggerFactory.getLogger(SelfTrustManager.class);
@SuppressWarnings("checkstyle:WhitespaceAround")
static TrustManager[] trustAll = new TrustManager[] {new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}};
/**
* Returns the result of calling {@link #buildSecureTrustManager} if {@code needAuth} is enable and {@code
* trustCertPath} exists. Returns the {@link trustAll} otherwise.
*
* @param needAuth whether need client auth
* @param trustCertPath trust certificate path
* @return Array of {@link TrustManager }
*/
public static TrustManager[] trustManager(boolean needAuth, String trustCertPath) {
if (needAuth) {
try {
return trustCertPath == null ? null : buildSecureTrustManager(trustCertPath);
} catch (SSLException e) {
LOGGER.warn("degrade trust manager as build failed, " + "will trust all certs.");
return trustAll;
}
} else {
return trustAll;
}
}
private static TrustManager[] buildSecureTrustManager(String trustCertPath) throws SSLException {
TrustManagerFactory selfTmf;
InputStream in = null;
try {
String algorithm = TrustManagerFactory.getDefaultAlgorithm();
selfTmf = TrustManagerFactory.getInstance(algorithm);
KeyStore trustKeyStore = KeyStore.getInstance("JKS");
trustKeyStore.load(null, null);
in = new FileInputStream(trustCertPath);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Collection<X509Certificate> certs = (Collection<X509Certificate>) cf.generateCertificates(in);
int count = 0;
for (Certificate cert : certs) {
trustKeyStore.setCertificateEntry("cert-" + (count++), cert);
}
selfTmf.init(trustKeyStore);
return selfTmf.getTrustManagers();
} catch (Exception e) {
LOGGER.error("build client trustManagerFactory failed", e);
throw new SSLException(e);
} finally {
IoUtils.closeQuietly(in);
}
}
}

View File

@ -0,0 +1,138 @@
/*
* 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.tls;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.common.executor.ExecutorFactory;
import com.alibaba.nacos.common.executor.NameThreadFactory;
import com.alibaba.nacos.common.utils.ClassUtils;
import com.alibaba.nacos.common.utils.IoUtils;
import com.alibaba.nacos.common.utils.MD5Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Certificate file update monitoring
*
* <p>Considering that the current client needs to support jdk 1.6 and module dependencies ,
* the WatchFileCenter in the core module is not used
*
* @author wangwei
*/
public final class TlsFileWatcher {
private static final Logger LOGGER = LoggerFactory.getLogger(TlsFileWatcher.class);
private AtomicBoolean started = new AtomicBoolean(false);
private final int checkInterval = TlsSystemConfig.tlsFileCheckInterval;
private Map<String, String> fileMd5Map = new HashMap<String, String>();
private ConcurrentHashMap<String, FileChangeListener> watchFilesMap = new ConcurrentHashMap<String, FileChangeListener>();
private final ScheduledExecutorService service = ExecutorFactory.Managed
.newSingleScheduledExecutorService(ClassUtils.getCanonicalName(TlsFileWatcher.class),
new NameThreadFactory("com.alibaba.nacos.core.common.tls"));
private static TlsFileWatcher tlsFileWatcher = new TlsFileWatcher();
private TlsFileWatcher() {
start();
}
public static TlsFileWatcher getInstance() {
return tlsFileWatcher;
}
/**
* Add file change listener for specified path.
*
* @param fileChangeListener listener
* @param filePaths file paths
* @throws IOException If an I/O error occurs
*/
public void addFileChangeListener(FileChangeListener fileChangeListener, String... filePaths) throws IOException {
for (String filePath : filePaths) {
if (filePath != null && new File(filePath).exists()) {
watchFilesMap.put(filePath, fileChangeListener);
InputStream in = null;
try {
in = new FileInputStream(filePath);
fileMd5Map.put(filePath, MD5Utils.md5Hex(IoUtils.toString(in, Constants.ENCODE), Constants.ENCODE));
} finally {
IoUtils.closeQuietly(in);
}
}
}
}
/**
* start file watch task. Notify when the MD5 of file changed
*/
public void start() {
if (started.compareAndSet(false, true)) {
service.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
for (Map.Entry<String, FileChangeListener> item : watchFilesMap.entrySet()) {
String filePath = item.getKey();
String newHash;
InputStream in = null;
try {
in = new FileInputStream(filePath);
newHash = MD5Utils.md5Hex(IoUtils.toString(in, Constants.ENCODE), Constants.ENCODE);
} catch (Exception ignored) {
LOGGER.warn(" service has exception when calculate the file MD5. " + ignored);
continue;
} finally {
IoUtils.closeQuietly(in);
}
if (!newHash.equals(fileMd5Map.get(filePath))) {
LOGGER.info(filePath + " file hash changed,need reload sslcontext");
fileMd5Map.put(filePath, newHash);
item.getValue().onChanged(filePath);
LOGGER.info(filePath + " onChanged success!");
}
}
}
}, 1, checkInterval, TimeUnit.MINUTES);
}
}
public interface FileChangeListener {
/**
* listener onChanged event.
*
* @param filePath Path of changed file
*/
void onChanged(String filePath);
}
}

View File

@ -0,0 +1,66 @@
/*
* 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.tls;
import javax.net.ssl.SSLContext;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
/**
* Utils for build {@link SSLContext}.
*
* <p>Currently only supports client-side
*
* <h3>Making your client support TLS without authentication</h3>
* <pre>
* System.setProperty({@link TlsSystemConfig#TLS_ENABLE}, "true");
* </pre>
*
* <h3>Making your client support TLS one-way authentication</h3>
*
* <pre>
* System.setProperty({@link TlsSystemConfig#TLS_ENABLE}, "true");
* System.setProperty({@link TlsSystemConfig#CLIENT_AUTH}, "true");
* System.setProperty({@link TlsSystemConfig#CLIENT_TRUST_CERT}, "trustCert");
* </pre>
*
* @author wangwei
* @date 2020/8/19 2:59 PM
*/
public final class TlsHelper {
/**
* Returns a {@link org.apache.http.ssl.SSLContexts}.
*
* <p>For example</p>
* <code>HttpsURLConnection.setDefaultSSLSocketFactory(TlsHelper.buildSslContext(true).getSocketFactory());</code>
*
* @param forClient whether for client
* @return {@link SSLContext}
* @throws NoSuchAlgorithmException Not support the specified algorithm
* @throws KeyManagementException KeyManagement exception
*/
public static SSLContext buildSslContext(boolean forClient)
throws NoSuchAlgorithmException, KeyManagementException {
SSLContext sslcontext = SSLContext.getInstance("TLS");
sslcontext.init(null, SelfTrustManager
.trustManager(TlsSystemConfig.tlsClientAuthServer, TlsSystemConfig.tlsClientTrustCertPath),
new java.security.SecureRandom());
return sslcontext;
}
}

View File

@ -0,0 +1,117 @@
/*
* 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.tls;
/**
* tls system config.
*
* @author wangwei
*/
public final class TlsSystemConfig {
public static final String TLS_TEST_MODE_ENABLE = "tls.test";
public static final String TLS_ENABLE = "tls.enable";
public static final String CLIENT_AUTH = "tls.client.authServer";
public static final String CLIENT_KEYPATH = "tls.client.keyPath";
public static final String CLIENT_KEYPASSWORD = "tls.client.keyPassword";
public static final String CLIENT_CERTPATH = "tls.client.certPath";
public static final String CLIENT_TRUST_CERT = "tls.client.trustCertPath";
public static final String SERVER_AUTH = "tls.server.authClient";
public static final String SERVER_KEYPATH = "tls.server.keyPath";
public static final String SERVER_KEYPASSWORD = "tls.server.keyPassword";
public static final String SERVER_CERTPATH = "tls.server.certPath";
public static final String SERVER_TRUST_CERT = "tls.server.trustCertPath";
public static final String CHECK_INTERVAL = "checkIntervalTlsFile";
/**
* To determine whether use SSL in client-side.
*/
public static boolean tlsEnable = Boolean.parseBoolean(System.getProperty(TLS_ENABLE, "false"));
/**
* To determine whether use test mode when initialize TLS context.
*/
public static boolean tlsTestModeEnable = Boolean.parseBoolean(System.getProperty(TLS_TEST_MODE_ENABLE, "false"));
/**
* To determine whether verify the server endpoint's certificate strictly.
*/
public static boolean tlsClientAuthServer = Boolean.parseBoolean(System.getProperty(CLIENT_AUTH, "false"));
/**
* To determine whether verify the client endpoint's certificate strictly.
*/
public static boolean tlsServerAuthClient = Boolean.parseBoolean(System.getProperty(SERVER_AUTH, "false"));
/**
* The store path of client-side private key.
*/
public static String tlsClientKeyPath = System.getProperty(CLIENT_KEYPATH, null);
/**
* The password of the client-side private key.
*/
public static String tlsClientKeyPassword = System.getProperty(CLIENT_KEYPASSWORD, null);
/**
* The store path of client-side X.509 certificate chain in PEM format.
*/
public static String tlsClientCertPath = System.getProperty(CLIENT_CERTPATH, null);
/**
* The store path of trusted certificates for verifying the server endpoint's certificate.
*/
public static String tlsClientTrustCertPath = System.getProperty(CLIENT_TRUST_CERT, null);
/**
* The store path of server-side private key.
*/
public static String tlsServerKeyPath = System.getProperty(SERVER_KEYPATH, null);
/**
* The password of the server-side private key.
*/
public static String tlsServerKeyPassword = System.getProperty(SERVER_KEYPASSWORD, null);
/**
* The store path of server-side X.509 certificate chain in PEM format.
*/
public static String tlsServerCertPath = System.getProperty(SERVER_CERTPATH, null);
/**
* The store path of trusted certificates for verifying the client endpoint's certificate.
*/
public static String tlsServerTrustCertPath = System.getProperty(SERVER_TRUST_CERT, null);
/**
* tls file check interval , default is 10 min.
*/
public static int tlsFileCheckInterval = Integer.parseInt(System.getProperty(CHECK_INTERVAL, "10"));
}

View File

@ -0,0 +1,33 @@
/*
* 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.utils;
/**
* Represents an operation that accepts two input arguments and returns no result.
*
* @author wangwei
*/
public interface BiConsumer<T, U> {
/**
* Performs this operation on the given arguments.
*
* @param t the first input argument
* @param u the second input argument
*/
void accept(T t, U u);
}

View File

@ -51,7 +51,11 @@ public final class ConvertUtils {
if (StringUtils.isBlank(val)) {
return defaultValue;
}
return Integer.parseInt(val);
try {
return Integer.parseInt(val);
} catch (NumberFormatException exception) {
return defaultValue;
}
}
/**
@ -77,7 +81,11 @@ public final class ConvertUtils {
if (StringUtils.isBlank(val)) {
return defaultValue;
}
return Long.parseLong(val);
try {
return Long.parseLong(val);
} catch (NumberFormatException exception) {
return defaultValue;
}
}
/**
@ -92,7 +100,11 @@ public final class ConvertUtils {
if (StringUtils.isBlank(val)) {
return defaultValue;
}
return Boolean.parseBoolean(val);
try {
return Boolean.parseBoolean(val);
} catch (NumberFormatException exception) {
return defaultValue;
}
}
// The following utility functions are extracted from <link>org.apache.commons.lang3</link>
@ -126,7 +138,7 @@ public final class ConvertUtils {
* @return the boolean value of the string, {@code false} if no match or the String is null
*/
public static boolean toBoolean(final String str) {
return toBooleanObject(str) == Boolean.TRUE;
return Boolean.TRUE.equals(toBooleanObject(str));
}
/**

View File

@ -26,8 +26,10 @@ public class HttpMethod {
public static final String GET = "GET";
// this is only use in nacos, Custom request type, essentially a get request
/**
* this is only use in nacos, Custom request type, essentially a GET request, Mainly used for GET request parameters
* are relatively large,can not be placed on the URL, so it needs to be placed in the body.
*/
public static final String GET_LARGE = "GET-LARGE";
public static final String HEAD = "HEAD";
@ -40,6 +42,12 @@ public class HttpMethod {
public static final String DELETE = "DELETE";
/**
* this is only use in nacos, Custom request type, essentially a DELETE request, Mainly used for DELETE request
* parameters are relatively large, can not be placed on the URL, so it needs to be placed in the body.
*/
public static final String DELETE_LARGE = "DELETE_LARGE";
public static final String OPTIONS = "OPTIONS";
public static final String TRACE = "TRACE";

View File

@ -50,9 +50,9 @@ public class IoUtils {
*
* @param raw compress stream
* @return byte array after decompress
* @throws Exception exception
* @throws IOException exception
*/
public static byte[] tryDecompress(InputStream raw) throws Exception {
public static byte[] tryDecompress(InputStream raw) throws IOException {
GZIPInputStream gis = null;
ByteArrayOutputStream out = null;
try {
@ -60,7 +60,7 @@ public class IoUtils {
out = new ByteArrayOutputStream();
copy(gis, out);
return out.toByteArray();
} catch (Exception e) {
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {

View File

@ -14,9 +14,7 @@
* limitations under the License.
*/
package com.alibaba.nacos.client.utils;
import com.alibaba.nacos.common.utils.StringUtils;
package com.alibaba.nacos.common.utils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -26,7 +24,7 @@ import java.util.regex.Pattern;
*
* @author Nacos
*/
public class IpUtil {
public class IpUtils {
private static final Pattern IPV4_PATTERN = Pattern
.compile("^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$");
@ -48,4 +46,4 @@ public class IpUtil {
Matcher mat = pattern.matcher(data);
return mat.find();
}
}
}

View File

@ -129,11 +129,11 @@ public class MapUtils {
/**
* ComputeIfAbsent lazy load.
*
* @param target target Map data.
* @param key map key.
* @param target target Map data.
* @param key map key.
* @param mappingFunction funtion which is need to be executed.
* @param param1 function's parameter value1.
* @param param2 function's parameter value1.
* @param param1 function's parameter value1.
* @param param2 function's parameter value1.
* @return
*/
@NotThreadSafe
@ -153,5 +153,4 @@ public class MapUtils {
}
return val;
}
}

View File

@ -94,9 +94,19 @@ public final class ThreadUtils {
* @return thread count
*/
public static int getSuitableThreadCount() {
return getSuitableThreadCount(THREAD_MULTIPLER);
}
/**
* Through the number of cores, calculate the appropriate number of threads.
*
* @param threadMultiple multiple time of cores
* @return thread count
*/
public static int getSuitableThreadCount(int threadMultiple) {
final int coreCount = Runtime.getRuntime().availableProcessors();
int workerCount = 1;
while (workerCount < coreCount * THREAD_MULTIPLER) {
while (workerCount < coreCount * threadMultiple) {
workerCount <<= 1;
}
return workerCount;

View File

@ -17,6 +17,7 @@
package com.alibaba.nacos.common.utils;
import java.io.InputStream;
import java.util.Comparator;
import java.util.Properties;
/**
@ -55,4 +56,36 @@ public class VersionUtils {
}
}
}
private static final Comparator<String> STRING_COMPARATOR = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
};
/**
* compare two version who is latest.
*
* @param versionA version A, like x.y.z(-beta)
* @param versionB version B, like x.y.z(-beta)
* @return compare result
*/
public static int compareVersion(final String versionA, final String versionB) {
final String[] sA = versionA.split("\\.");
final String[] sB = versionB.split("\\.");
int expectSize = 3;
if (sA.length != expectSize || sB.length != expectSize) {
throw new IllegalArgumentException("version must be like x.y.z(-beta)");
}
int first = Objects.compare(sA[0], sB[0], STRING_COMPARATOR);
if (first != 0) {
return first;
}
int second = Objects.compare(sA[1], sB[1], STRING_COMPARATOR);
if (second != 0) {
return second;
}
return Objects.compare(sA[2].split("-")[0], sB[2].split("-")[0], STRING_COMPARATOR);
}
}

View File

@ -0,0 +1,62 @@
/*
* 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.param;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* MediaTypeTest.
*
* @author mai.jh
*/
public class MediaTypeTest {
@Test
public void testValueOf() {
MediaType mediaType = MediaType.valueOf(MediaType.APPLICATION_FORM_URLENCODED);
String type = "application/x-www-form-urlencoded";
String charset = "UTF-8";
assertEquals(type, mediaType.getType());
assertEquals(charset, mediaType.getCharset());
assertEquals(MediaType.APPLICATION_FORM_URLENCODED, mediaType.toString());
}
@Test
public void testValueOf2() {
MediaType mediaType = MediaType.valueOf(MediaType.APPLICATION_FORM_URLENCODED, "ISO-8859-1");
String type = "application/x-www-form-urlencoded";
String charset = "ISO-8859-1";
String excepted = "application/x-www-form-urlencoded;charset=ISO-8859-1";
assertEquals(type, mediaType.getType());
assertEquals(charset, mediaType.getCharset());
assertEquals(excepted, mediaType.toString());
}
@Test
public void testValueOf3() {
MediaType mediaType = MediaType.valueOf("application/x-www-form-urlencoded", "ISO-8859-1");
String type = "application/x-www-form-urlencoded";
String charset = "ISO-8859-1";
String excepted = "application/x-www-form-urlencoded;charset=ISO-8859-1";
assertEquals(type, mediaType.getType());
assertEquals(charset, mediaType.getCharset());
assertEquals(excepted, mediaType.toString());
}
}

View File

@ -132,6 +132,7 @@ public class NotifyCenterTest {
return ExpireEvent.class;
}
@Override
public boolean ignoreExpireEvent() {
return true;
}

View File

@ -0,0 +1,113 @@
/*
* 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.task.engine;
import com.alibaba.nacos.common.task.AbstractDelayTask;
import com.alibaba.nacos.common.task.NacosTaskProcessor;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.internal.verification.Times;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class NacosDelayTaskExecuteEngineTest {
private NacosDelayTaskExecuteEngine nacosDelayTaskExecuteEngine;
@Mock
private NacosTaskProcessor taskProcessor;
@Mock
private NacosTaskProcessor testTaskProcessor;
private AbstractDelayTask abstractTask;
@Before
public void setUp() throws Exception {
nacosDelayTaskExecuteEngine = new NacosDelayTaskExecuteEngine(NacosDelayTaskExecuteEngineTest.class.getName());
nacosDelayTaskExecuteEngine.setDefaultTaskProcessor(taskProcessor);
abstractTask = new AbstractDelayTask() {
@Override
public void merge(AbstractDelayTask task) {
}
};
}
@After
public void tearDown() throws Exception {
nacosDelayTaskExecuteEngine.shutdown();
}
@Test
public void testSize() {
assertEquals(0, nacosDelayTaskExecuteEngine.size());
nacosDelayTaskExecuteEngine.addTask("test", abstractTask);
assertEquals(1, nacosDelayTaskExecuteEngine.size());
nacosDelayTaskExecuteEngine.removeTask("test");
assertEquals(0, nacosDelayTaskExecuteEngine.size());
}
@Test
public void testIsEmpty() {
assertTrue(nacosDelayTaskExecuteEngine.isEmpty());
nacosDelayTaskExecuteEngine.addTask("test", abstractTask);
assertFalse(nacosDelayTaskExecuteEngine.isEmpty());
nacosDelayTaskExecuteEngine.removeTask("test");
assertTrue(nacosDelayTaskExecuteEngine.isEmpty());
}
@Test
public void testAddProcessor() throws InterruptedException {
when(testTaskProcessor.process(abstractTask)).thenReturn(true);
nacosDelayTaskExecuteEngine.addProcessor("test", testTaskProcessor);
nacosDelayTaskExecuteEngine.addTask("test", abstractTask);
TimeUnit.MILLISECONDS.sleep(200);
verify(testTaskProcessor).process(abstractTask);
verify(taskProcessor, never()).process(abstractTask);
}
@Test
public void testRemoveProcessor() throws InterruptedException {
when(taskProcessor.process(abstractTask)).thenReturn(true);
nacosDelayTaskExecuteEngine.addProcessor("test", testTaskProcessor);
nacosDelayTaskExecuteEngine.removeProcessor("test");
nacosDelayTaskExecuteEngine.addTask("test", abstractTask);
TimeUnit.MILLISECONDS.sleep(200);
verify(testTaskProcessor, never()).process(abstractTask);
verify(taskProcessor).process(abstractTask);
}
@Test
public void testRetryTaskAfterFail() throws InterruptedException {
when(taskProcessor.process(abstractTask)).thenReturn(false, true);
nacosDelayTaskExecuteEngine.addTask("test", abstractTask);
TimeUnit.MILLISECONDS.sleep(300);
verify(taskProcessor, new Times(2)).process(abstractTask);
}
}

View File

@ -0,0 +1,60 @@
/*
* 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.task.engine;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.common.task.AbstractExecuteTask;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.verify;
@RunWith(MockitoJUnitRunner.class)
public class NacosExecuteTaskExecuteEngineTest {
private NacosExecuteTaskExecuteEngine executeTaskExecuteEngine;
@Before
public void setUp() {
executeTaskExecuteEngine = new NacosExecuteTaskExecuteEngine("TEST", null);
}
@After
public void tearDown() throws NacosException {
executeTaskExecuteEngine.shutdown();
}
@Mock
private AbstractExecuteTask task;
@Test
public void testAddTask() throws InterruptedException {
executeTaskExecuteEngine.addTask("test", task);
TimeUnit.SECONDS.sleep(1);
verify(task).run();
assertTrue(executeTaskExecuteEngine.isEmpty());
assertEquals(0, executeTaskExecuteEngine.size());
}
}

View File

@ -0,0 +1,66 @@
/*
* 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.utils;
import org.junit.Assert;
import org.junit.Test;
public class VersionUtilsTest {
@Test
public void testVersionCompareLt() {
final String versionA = "1.2.0";
final String versionB = "1.2.1";
Assert.assertTrue(VersionUtils.compareVersion(versionA, versionB) < 0);
}
@Test
public void testVersionCompareGt() {
final String versionA = "1.2.2";
final String versionB = "1.2.1";
Assert.assertTrue(VersionUtils.compareVersion(versionA, versionB) > 0);
}
@Test
public void testVersionCompareEt() {
final String versionA = "1.2.1";
final String versionB = "1.2.1";
Assert.assertEquals(0, VersionUtils.compareVersion(versionA, versionB));
}
@Test
public void testVersionCompareLtWithChar() {
final String versionA = "1.2.0-beta";
final String versionB = "1.2.1";
Assert.assertTrue(VersionUtils.compareVersion(versionA, versionB) < 0);
}
@Test
public void testVersionCompareGtWithChar() {
final String versionA = "1.2.2-beta";
final String versionB = "1.2.1-beta";
Assert.assertTrue(VersionUtils.compareVersion(versionA, versionB) > 0);
}
@Test
public void testVersionCompareEtWithChar() {
final String versionA = "1.2.1";
final String versionB = "1.2.1-beta";
Assert.assertEquals(0, VersionUtils.compareVersion(versionA, versionB));
}
}

Some files were not shown because too many files have changed in this diff Show More