Merge branch 'develop' of https://github.com/alibaba/nacos into new_develop
This commit is contained in:
commit
9e7cf30554
@ -13,136 +13,145 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.api.exception;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import com.alibaba.nacos.api.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* Nacos Exception
|
||||
* Nacos Exception.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class NacosException extends Exception {
|
||||
|
||||
/**
|
||||
* serialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = -3913902031489277776L;
|
||||
|
||||
private int errCode;
|
||||
|
||||
private String errMsg;
|
||||
|
||||
private Throwable causeThrowable;
|
||||
|
||||
public NacosException() {
|
||||
}
|
||||
|
||||
public NacosException(int errCode, String errMsg) {
|
||||
super(errMsg);
|
||||
this.errCode = errCode;
|
||||
this.errMsg = errMsg;
|
||||
}
|
||||
|
||||
public NacosException(int errCode, Throwable throwable) {
|
||||
super(throwable);
|
||||
this.errCode = errCode;
|
||||
setCauseThrowable(throwable);
|
||||
}
|
||||
|
||||
public NacosException(int errCode, String errMsg, Throwable throwable) {
|
||||
super(errMsg, throwable);
|
||||
this.errCode = errCode;
|
||||
this.errMsg = errMsg;
|
||||
setCauseThrowable(throwable);
|
||||
}
|
||||
|
||||
public int getErrCode() {
|
||||
return errCode;
|
||||
}
|
||||
|
||||
public String getErrMsg() {
|
||||
if (!StringUtils.isBlank(this.errMsg)) {
|
||||
return errMsg;
|
||||
}
|
||||
if (this.causeThrowable != null) {
|
||||
return causeThrowable.getMessage();
|
||||
}
|
||||
return Constants.NULL;
|
||||
}
|
||||
|
||||
public void setErrCode(int errCode) {
|
||||
this.errCode = errCode;
|
||||
}
|
||||
|
||||
public void setErrMsg(String errMsg) {
|
||||
this.errMsg = errMsg;
|
||||
}
|
||||
|
||||
public void setCauseThrowable(Throwable throwable) {
|
||||
this.causeThrowable = getCauseThrowable(throwable);
|
||||
}
|
||||
|
||||
private Throwable getCauseThrowable(Throwable t) {
|
||||
if (t.getCause() == null) {
|
||||
return t;
|
||||
}
|
||||
return getCauseThrowable(t.getCause());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ErrCode:" + getErrCode() + ", ErrMsg:" + getErrMsg();
|
||||
}
|
||||
|
||||
/**
|
||||
* client error code
|
||||
* -400 -503 throw exception to user
|
||||
*/
|
||||
/**
|
||||
* invalid param(参数错误)
|
||||
*/
|
||||
public static final int CLIENT_INVALID_PARAM = -400;
|
||||
/**
|
||||
* over client threshold(超过server端的限流阈值)
|
||||
*/
|
||||
public static final int CLIENT_OVER_THRESHOLD = -503;
|
||||
|
||||
/**
|
||||
* server error code
|
||||
* 400 403 throw exception to user
|
||||
* 500 502 503 change ip and retry
|
||||
*/
|
||||
|
||||
/**
|
||||
* invalid param(参数错误)
|
||||
*/
|
||||
public static final int INVALID_PARAM = 400;
|
||||
/**
|
||||
* no right(鉴权失败)
|
||||
*/
|
||||
public static final int NO_RIGHT = 403;
|
||||
/**
|
||||
* not found
|
||||
*/
|
||||
public static final int NOT_FOUND = 404;
|
||||
/**
|
||||
* conflict(写并发冲突)
|
||||
*/
|
||||
public static final int CONFLICT = 409;
|
||||
/**
|
||||
* server error(server异常,如超时)
|
||||
*/
|
||||
public static final int SERVER_ERROR = 500;
|
||||
/**
|
||||
* bad gateway(路由异常,如nginx后面的Server挂掉)
|
||||
*/
|
||||
public static final int BAD_GATEWAY = 502;
|
||||
/**
|
||||
* over threshold(超过server端的限流阈值)
|
||||
*/
|
||||
public static final int OVER_THRESHOLD = 503;
|
||||
|
||||
public static final int RESOURCE_NOT_FOUND = -404;
|
||||
|
||||
/**
|
||||
* serialVersionUID.
|
||||
*/
|
||||
private static final long serialVersionUID = -3913902031489277776L;
|
||||
|
||||
private int errCode;
|
||||
|
||||
private String errMsg;
|
||||
|
||||
private Throwable causeThrowable;
|
||||
|
||||
public NacosException() {
|
||||
}
|
||||
|
||||
public NacosException(final int errCode, final String errMsg) {
|
||||
super(errMsg);
|
||||
this.errCode = errCode;
|
||||
this.errMsg = errMsg;
|
||||
}
|
||||
|
||||
public NacosException(final int errCode, final Throwable throwable) {
|
||||
super(throwable);
|
||||
this.errCode = errCode;
|
||||
this.setCauseThrowable(throwable);
|
||||
}
|
||||
|
||||
public NacosException(final int errCode, final String errMsg, final Throwable throwable) {
|
||||
super(errMsg, throwable);
|
||||
this.errCode = errCode;
|
||||
this.errMsg = errMsg;
|
||||
this.setCauseThrowable(throwable);
|
||||
}
|
||||
|
||||
public int getErrCode() {
|
||||
return this.errCode;
|
||||
}
|
||||
|
||||
public String getErrMsg() {
|
||||
if (!StringUtils.isBlank(this.errMsg)) {
|
||||
return this.errMsg;
|
||||
}
|
||||
if (this.causeThrowable != null) {
|
||||
return this.causeThrowable.getMessage();
|
||||
}
|
||||
return Constants.NULL;
|
||||
}
|
||||
|
||||
public void setErrCode(final int errCode) {
|
||||
this.errCode = errCode;
|
||||
}
|
||||
|
||||
public void setErrMsg(final String errMsg) {
|
||||
this.errMsg = errMsg;
|
||||
}
|
||||
|
||||
public void setCauseThrowable(final Throwable throwable) {
|
||||
this.causeThrowable = this.getCauseThrowable(throwable);
|
||||
}
|
||||
|
||||
private Throwable getCauseThrowable(final Throwable t) {
|
||||
if (t.getCause() == null) {
|
||||
return t;
|
||||
}
|
||||
return this.getCauseThrowable(t.getCause());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ErrCode:" + getErrCode() + ", ErrMsg:" + getErrMsg();
|
||||
}
|
||||
|
||||
/*
|
||||
* client error code.
|
||||
* -400 -503 throw exception to user.
|
||||
*/
|
||||
|
||||
/**
|
||||
* invalid param(参数错误).
|
||||
*/
|
||||
public static final int CLIENT_INVALID_PARAM = -400;
|
||||
|
||||
/**
|
||||
* over client threshold(超过server端的限流阈值).
|
||||
*/
|
||||
public static final int CLIENT_OVER_THRESHOLD = -503;
|
||||
|
||||
/*
|
||||
* server error code.
|
||||
* 400 403 throw exception to user
|
||||
* 500 502 503 change ip and retry
|
||||
*/
|
||||
|
||||
/**
|
||||
* invalid param(参数错误).
|
||||
*/
|
||||
public static final int INVALID_PARAM = 400;
|
||||
|
||||
/**
|
||||
* no right(鉴权失败).
|
||||
*/
|
||||
public static final int NO_RIGHT = 403;
|
||||
|
||||
/**
|
||||
* not found.
|
||||
*/
|
||||
public static final int NOT_FOUND = 404;
|
||||
|
||||
/**
|
||||
* conflict(写并发冲突).
|
||||
*/
|
||||
public static final int CONFLICT = 409;
|
||||
|
||||
/**
|
||||
* server error(server异常,如超时).
|
||||
*/
|
||||
public static final int SERVER_ERROR = 500;
|
||||
|
||||
/**
|
||||
* bad gateway(路由异常,如nginx后面的Server挂掉).
|
||||
*/
|
||||
public static final int BAD_GATEWAY = 502;
|
||||
|
||||
/**
|
||||
* over threshold(超过server端的限流阈值).
|
||||
*/
|
||||
public static final int OVER_THRESHOLD = 503;
|
||||
|
||||
public static final int RESOURCE_NOT_FOUND = -404;
|
||||
}
|
||||
|
@ -13,238 +13,240 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.api.naming.pojo;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.naming.PreservedMetadataKeys;
|
||||
import com.alibaba.nacos.api.utils.StringUtils;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.alibaba.nacos.api.common.Constants.NUMBER_PATTERN;
|
||||
|
||||
/**
|
||||
* Instance
|
||||
* Instance.
|
||||
*
|
||||
* @author nkorange
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
public class Instance {
|
||||
|
||||
|
||||
/**
|
||||
* unique id of this instance.
|
||||
*/
|
||||
private String instanceId;
|
||||
|
||||
|
||||
/**
|
||||
* instance ip
|
||||
* instance ip.
|
||||
*/
|
||||
private String ip;
|
||||
|
||||
|
||||
/**
|
||||
* instance port
|
||||
* instance port.
|
||||
*/
|
||||
private int port;
|
||||
|
||||
|
||||
/**
|
||||
* instance weight
|
||||
* instance weight.
|
||||
*/
|
||||
private double weight = 1.0D;
|
||||
|
||||
|
||||
/**
|
||||
* instance health status
|
||||
* instance health status.
|
||||
*/
|
||||
private boolean healthy = true;
|
||||
|
||||
|
||||
/**
|
||||
* If instance is enabled to accept request
|
||||
* If instance is enabled to accept request.
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
|
||||
/**
|
||||
* If instance is ephemeral
|
||||
* If instance is ephemeral.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private boolean ephemeral = true;
|
||||
|
||||
|
||||
/**
|
||||
* cluster information of instance
|
||||
* cluster information of instance.
|
||||
*/
|
||||
private String clusterName;
|
||||
|
||||
|
||||
/**
|
||||
* Service information of instance
|
||||
* Service information of instance.
|
||||
*/
|
||||
private String serviceName;
|
||||
|
||||
|
||||
/**
|
||||
* user extended attributes
|
||||
* user extended attributes.
|
||||
*/
|
||||
private Map<String, String> metadata = new HashMap<String, String>();
|
||||
|
||||
|
||||
public String getInstanceId() {
|
||||
return instanceId;
|
||||
return this.instanceId;
|
||||
}
|
||||
|
||||
public void setInstanceId(String instanceId) {
|
||||
|
||||
public void setInstanceId(final String instanceId) {
|
||||
this.instanceId = instanceId;
|
||||
}
|
||||
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
return this.ip;
|
||||
}
|
||||
|
||||
public void setIp(String ip) {
|
||||
|
||||
public void setIp(final String ip) {
|
||||
this.ip = ip;
|
||||
}
|
||||
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
return this.port;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
|
||||
public void setPort(final int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
|
||||
public double getWeight() {
|
||||
return weight;
|
||||
return this.weight;
|
||||
}
|
||||
|
||||
public void setWeight(double weight) {
|
||||
|
||||
public void setWeight(final double weight) {
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
|
||||
public boolean isHealthy() {
|
||||
return healthy;
|
||||
return this.healthy;
|
||||
}
|
||||
|
||||
public void setHealthy(boolean healthy) {
|
||||
|
||||
public void setHealthy(final boolean healthy) {
|
||||
this.healthy = healthy;
|
||||
}
|
||||
|
||||
|
||||
public String getClusterName() {
|
||||
return clusterName;
|
||||
return this.clusterName;
|
||||
}
|
||||
|
||||
public void setClusterName(String clusterName) {
|
||||
|
||||
public void setClusterName(final String clusterName) {
|
||||
this.clusterName = clusterName;
|
||||
}
|
||||
|
||||
|
||||
public String getServiceName() {
|
||||
return serviceName;
|
||||
return this.serviceName;
|
||||
}
|
||||
|
||||
public void setServiceName(String serviceName) {
|
||||
|
||||
public void setServiceName(final String serviceName) {
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
|
||||
|
||||
public Map<String, String> getMetadata() {
|
||||
return metadata;
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
public void setMetadata(Map<String, String> metadata) {
|
||||
|
||||
public void setMetadata(final Map<String, String> metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public void addMetadata(String key, String value) {
|
||||
if (this.metadata == null) {
|
||||
this.metadata = new HashMap<String, String>(4);
|
||||
|
||||
/**
|
||||
* add meta data.
|
||||
*
|
||||
* @param key meta data key
|
||||
* @param value meta data value
|
||||
*/
|
||||
public void addMetadata(final String key, final String value) {
|
||||
if (metadata == null) {
|
||||
metadata = new HashMap<String, String>(4);
|
||||
}
|
||||
this.metadata.put(key, value);
|
||||
metadata.put(key, value);
|
||||
}
|
||||
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
|
||||
public void setEnabled(final boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
|
||||
public boolean isEphemeral() {
|
||||
return ephemeral;
|
||||
return this.ephemeral;
|
||||
}
|
||||
|
||||
public void setEphemeral(boolean ephemeral) {
|
||||
|
||||
public void setEphemeral(final boolean ephemeral) {
|
||||
this.ephemeral = ephemeral;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Instance{" +
|
||||
"instanceId='" + instanceId + '\'' +
|
||||
", ip='" + ip + '\'' +
|
||||
", port=" + port +
|
||||
", weight=" + weight +
|
||||
", healthy=" + healthy +
|
||||
", enabled=" + enabled +
|
||||
", ephemeral=" + ephemeral +
|
||||
", clusterName='" + clusterName + '\'' +
|
||||
", serviceName='" + serviceName + '\'' +
|
||||
", metadata=" + metadata +
|
||||
'}';
|
||||
return "Instance{" + "instanceId='" + instanceId + '\'' + ", ip='" + ip + '\'' + ", port=" + port
|
||||
+ ", weight=" + weight + ", healthy=" + healthy + ", enabled=" + enabled + ", ephemeral="
|
||||
+ ephemeral + ", clusterName='" + clusterName + '\'' + ", serviceName='" + serviceName
|
||||
+ '\'' + ", metadata=" + metadata + '}';
|
||||
}
|
||||
|
||||
|
||||
public String toInetAddr() {
|
||||
return ip + ":" + port;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public boolean equals(final Object obj) {
|
||||
if (!(obj instanceof Instance)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Instance host = (Instance) obj;
|
||||
return strEquals(host.toString(), toString());
|
||||
|
||||
final Instance host = (Instance) obj;
|
||||
return Instance.strEquals(host.toString(), toString());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return toString().hashCode();
|
||||
}
|
||||
|
||||
private static boolean strEquals(String str1, String str2) {
|
||||
|
||||
private static boolean strEquals(final String str1, final String str2) {
|
||||
return str1 == null ? str2 == null : str1.equals(str2);
|
||||
}
|
||||
|
||||
|
||||
public long getInstanceHeartBeatInterval() {
|
||||
return getMetaDataByKeyWithDefault(PreservedMetadataKeys.HEART_BEAT_INTERVAL, Constants.DEFAULT_HEART_BEAT_INTERVAL);
|
||||
return getMetaDataByKeyWithDefault(PreservedMetadataKeys.HEART_BEAT_INTERVAL,
|
||||
Constants.DEFAULT_HEART_BEAT_INTERVAL);
|
||||
}
|
||||
|
||||
|
||||
public long getInstanceHeartBeatTimeOut() {
|
||||
return getMetaDataByKeyWithDefault(PreservedMetadataKeys.HEART_BEAT_TIMEOUT, Constants.DEFAULT_HEART_BEAT_TIMEOUT);
|
||||
return getMetaDataByKeyWithDefault(PreservedMetadataKeys.HEART_BEAT_TIMEOUT,
|
||||
Constants.DEFAULT_HEART_BEAT_TIMEOUT);
|
||||
}
|
||||
|
||||
|
||||
public long getIpDeleteTimeout() {
|
||||
return getMetaDataByKeyWithDefault(PreservedMetadataKeys.IP_DELETE_TIMEOUT, Constants.DEFAULT_IP_DELETE_TIMEOUT);
|
||||
return getMetaDataByKeyWithDefault(PreservedMetadataKeys.IP_DELETE_TIMEOUT,
|
||||
Constants.DEFAULT_IP_DELETE_TIMEOUT);
|
||||
}
|
||||
|
||||
|
||||
public String getInstanceIdGenerator() {
|
||||
return getMetaDataByKeyWithDefault(PreservedMetadataKeys.INSTANCE_ID_GENERATOR, Constants.DEFAULT_INSTANCE_ID_GENERATOR);
|
||||
return getMetaDataByKeyWithDefault(PreservedMetadataKeys.INSTANCE_ID_GENERATOR,
|
||||
Constants.DEFAULT_INSTANCE_ID_GENERATOR);
|
||||
}
|
||||
|
||||
private long getMetaDataByKeyWithDefault( String key, long defaultValue) {
|
||||
|
||||
private long getMetaDataByKeyWithDefault(final String key, final long defaultValue) {
|
||||
if (getMetadata() == null || getMetadata().isEmpty()) {
|
||||
return defaultValue;
|
||||
}
|
||||
String value = getMetadata().get(key);
|
||||
final String value = getMetadata().get(key);
|
||||
if (!StringUtils.isEmpty(value) && value.matches(NUMBER_PATTERN)) {
|
||||
return Long.parseLong(value);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private String getMetaDataByKeyWithDefault( String key, String defaultValue) {
|
||||
|
||||
private String getMetaDataByKeyWithDefault(final String key, final String defaultValue) {
|
||||
if (getMetadata() == null || getMetadata().isEmpty()) {
|
||||
return defaultValue;
|
||||
}
|
||||
return getMetadata().get(key);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -18,9 +18,9 @@ package com.alibaba.nacos.api.naming.pojo.healthcheck.impl;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;
|
||||
import com.alibaba.nacos.api.utils.StringUtils;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.google.common.base.Objects;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@ -32,50 +32,51 @@ import java.util.Map;
|
||||
* @author yangyi
|
||||
*/
|
||||
public class Http extends AbstractHealthChecker {
|
||||
|
||||
public static final String TYPE = "HTTP";
|
||||
|
||||
|
||||
private String path = "";
|
||||
|
||||
|
||||
private String headers = "";
|
||||
|
||||
|
||||
private int expectedResponseCode = 200;
|
||||
|
||||
|
||||
public Http() {
|
||||
super(TYPE);
|
||||
super(Http.TYPE);
|
||||
}
|
||||
|
||||
|
||||
public int getExpectedResponseCode() {
|
||||
return expectedResponseCode;
|
||||
return this.expectedResponseCode;
|
||||
}
|
||||
|
||||
public void setExpectedResponseCode(int expectedResponseCode) {
|
||||
|
||||
public void setExpectedResponseCode(final int expectedResponseCode) {
|
||||
this.expectedResponseCode = expectedResponseCode;
|
||||
}
|
||||
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
return this.path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
|
||||
public void setPath(final String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
|
||||
public String getHeaders() {
|
||||
return headers;
|
||||
return this.headers;
|
||||
}
|
||||
|
||||
public void setHeaders(String headers) {
|
||||
|
||||
public void setHeaders(final String headers) {
|
||||
this.headers = headers;
|
||||
}
|
||||
|
||||
|
||||
@JsonIgnore
|
||||
public Map<String, String> getCustomHeaders() {
|
||||
if (StringUtils.isBlank(headers)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<String, String> headerMap = new HashMap<String, String>(16);
|
||||
for (String s : headers.split(Constants.NAMING_HTTP_HEADER_SPILIER)) {
|
||||
String[] splits = s.split(":");
|
||||
final Map<String, String> headerMap = new HashMap<String, String>(16);
|
||||
for (final String s : headers.split(Constants.NAMING_HTTP_HEADER_SPILIER)) {
|
||||
final String[] splits = s.split(":");
|
||||
if (splits.length != 2) {
|
||||
continue;
|
||||
}
|
||||
@ -83,24 +84,24 @@ public class Http extends AbstractHealthChecker {
|
||||
}
|
||||
return headerMap;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(path, headers, expectedResponseCode);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public boolean equals(final Object obj) {
|
||||
if (!(obj instanceof Http)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Http other = (Http) obj;
|
||||
|
||||
|
||||
final Http other = (Http) obj;
|
||||
|
||||
if (!StringUtils.equals(type, other.getType())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!StringUtils.equals(path, other.getPath())) {
|
||||
return false;
|
||||
}
|
||||
@ -109,13 +110,13 @@ public class Http extends AbstractHealthChecker {
|
||||
}
|
||||
return expectedResponseCode == other.getExpectedResponseCode();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Http clone() throws CloneNotSupportedException {
|
||||
Http config = new Http();
|
||||
config.setPath(this.getPath());
|
||||
config.setHeaders(this.getHeaders());
|
||||
config.setExpectedResponseCode(this.getExpectedResponseCode());
|
||||
final Http config = new Http();
|
||||
config.setPath(getPath());
|
||||
config.setHeaders(getHeaders());
|
||||
config.setExpectedResponseCode(getExpectedResponseCode());
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,8 @@
|
||||
|
||||
package com.alibaba.nacos.api.naming.pojo.healthcheck.impl;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;
|
||||
import com.alibaba.nacos.api.utils.StringUtils;
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
@ -27,72 +26,73 @@ import com.google.common.base.Objects;
|
||||
* @author yangyi
|
||||
*/
|
||||
public class Mysql extends AbstractHealthChecker {
|
||||
|
||||
public static final String TYPE = "MYSQL";
|
||||
|
||||
|
||||
private String user;
|
||||
|
||||
|
||||
private String pwd;
|
||||
|
||||
|
||||
private String cmd;
|
||||
|
||||
|
||||
public Mysql() {
|
||||
super(TYPE);
|
||||
super(Mysql.TYPE);
|
||||
}
|
||||
|
||||
|
||||
public String getCmd() {
|
||||
return cmd;
|
||||
return this.cmd;
|
||||
}
|
||||
|
||||
|
||||
public String getPwd() {
|
||||
return pwd;
|
||||
return this.pwd;
|
||||
}
|
||||
|
||||
|
||||
public String getUser() {
|
||||
return user;
|
||||
return this.user;
|
||||
}
|
||||
|
||||
public void setUser(String user) {
|
||||
|
||||
public void setUser(final String user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public void setCmd(String cmd) {
|
||||
|
||||
public void setCmd(final String cmd) {
|
||||
this.cmd = cmd;
|
||||
}
|
||||
|
||||
public void setPwd(String pwd) {
|
||||
|
||||
public void setPwd(final String pwd) {
|
||||
this.pwd = pwd;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(user, pwd, cmd);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public boolean equals(final Object obj) {
|
||||
if (!(obj instanceof Mysql)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Mysql other = (Mysql) obj;
|
||||
|
||||
|
||||
final Mysql other = (Mysql) obj;
|
||||
|
||||
if (!StringUtils.equals(user, other.getUser())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!StringUtils.equals(pwd, other.getPwd())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return StringUtils.equals(cmd, other.getCmd());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Mysql clone() throws CloneNotSupportedException {
|
||||
Mysql config = new Mysql();
|
||||
config.setUser(this.getUser());
|
||||
config.setPwd(this.getPwd());
|
||||
config.setCmd(this.getCmd());
|
||||
final Mysql config = new Mysql();
|
||||
config.setUser(getUser());
|
||||
config.setPwd(getPwd());
|
||||
config.setCmd(getCmd());
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
@ -13,26 +13,26 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.api.naming.utils;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import com.alibaba.nacos.api.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* NamingUtils.
|
||||
*
|
||||
* @author nkorange
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class NamingUtils {
|
||||
|
||||
public static String getGroupedName(String serviceName, String groupName) {
|
||||
StringBuilder resultGroupedName = new StringBuilder()
|
||||
.append(groupName)
|
||||
.append(Constants.SERVICE_INFO_SPLITER)
|
||||
.append(serviceName);
|
||||
return resultGroupedName.toString().intern();
|
||||
|
||||
public static String getGroupedName(final String serviceName, final String groupName) {
|
||||
final String resultGroupedName = groupName + Constants.SERVICE_INFO_SPLITER + serviceName;
|
||||
return resultGroupedName.intern();
|
||||
}
|
||||
|
||||
public static String getServiceName(String serviceNameWithGroup) {
|
||||
|
||||
public static String getServiceName(final String serviceNameWithGroup) {
|
||||
if (StringUtils.isBlank(serviceNameWithGroup)) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
@ -41,8 +41,8 @@ public class NamingUtils {
|
||||
}
|
||||
return serviceNameWithGroup.split(Constants.SERVICE_INFO_SPLITER)[1];
|
||||
}
|
||||
|
||||
public static String getGroupName(String serviceNameWithGroup) {
|
||||
|
||||
public static String getGroupName(final String serviceNameWithGroup) {
|
||||
if (StringUtils.isBlank(serviceNameWithGroup)) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
187
api/src/main/java/com/alibaba/nacos/api/utils/StringUtils.java
Normal file
187
api/src/main/java/com/alibaba/nacos/api/utils/StringUtils.java
Normal file
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* 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.api.utils;
|
||||
|
||||
/**
|
||||
* StringUtils. copy from apache common-lang3.
|
||||
*
|
||||
* @author <a href="mailto:lin-mt@outlook.com">lin-mt</a>
|
||||
*/
|
||||
public class StringUtils {
|
||||
|
||||
/**
|
||||
* The empty String {@code ""}.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final String EMPTY = "";
|
||||
|
||||
/**
|
||||
* <p>Checks if a CharSequence is empty ("") or null.</p>
|
||||
*
|
||||
* <pre>
|
||||
* StringUtils.isEmpty(null) = true
|
||||
* StringUtils.isEmpty("") = true
|
||||
* StringUtils.isEmpty(" ") = false
|
||||
* StringUtils.isEmpty("bob") = false
|
||||
* StringUtils.isEmpty(" bob ") = false
|
||||
* </pre>
|
||||
*
|
||||
* <p>NOTE: This method changed in Lang version 2.0.
|
||||
* It no longer trims the CharSequence. That functionality is available in isBlank().</p>
|
||||
*
|
||||
* @param cs the CharSequence to check, may be null
|
||||
* @return {@code true} if the CharSequence is empty or null
|
||||
* @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence)
|
||||
*/
|
||||
public static boolean isEmpty(final CharSequence cs) {
|
||||
return cs == null || cs.length() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Checks if a CharSequence is whitespace, empty ("") or null.</p>
|
||||
*
|
||||
* <pre>
|
||||
* StringUtils.isBlank(null) = true
|
||||
* StringUtils.isBlank("") = true
|
||||
* StringUtils.isBlank(" ") = true
|
||||
* StringUtils.isBlank("bob") = false
|
||||
* StringUtils.isBlank(" bob ") = false
|
||||
* </pre>
|
||||
*
|
||||
* @param cs the CharSequence to check, may be null
|
||||
* @return {@code true} if the CharSequence is null, empty or whitespace
|
||||
* @since 2.0
|
||||
* @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence)
|
||||
*/
|
||||
public static boolean isBlank(final CharSequence cs) {
|
||||
final int strLen;
|
||||
if (cs == null || (strLen = cs.length()) == 0) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < strLen; i++) {
|
||||
if (!Character.isWhitespace(cs.charAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Trim
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* <p>Removes control characters (char <= 32) from both
|
||||
* ends of this String, handling {@code null} by returning {@code null}.</p>
|
||||
*
|
||||
* <p>The String is trimmed using {@link String#trim()}.
|
||||
* Trim removes start and end characters <= 32.</p>
|
||||
*
|
||||
* <pre>
|
||||
* StringUtils.trim(null) = null
|
||||
* StringUtils.trim("") = ""
|
||||
* StringUtils.trim(" ") = ""
|
||||
* StringUtils.trim("abc") = "abc"
|
||||
* StringUtils.trim(" abc ") = "abc"
|
||||
* </pre>
|
||||
*
|
||||
* @param str the String to be trimmed, may be null
|
||||
* @return the trimmed string, {@code null} if null String input
|
||||
*/
|
||||
public static String trim(final String str) {
|
||||
return str == null ? null : str.trim();
|
||||
}
|
||||
|
||||
// Equals
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* <p>Compares two CharSequences, returning {@code true} if they represent
|
||||
* equal sequences of characters.</p>
|
||||
*
|
||||
* <p>{@code null}s are handled without exceptions. Two {@code null}
|
||||
* references are considered to be equal. The comparison is case sensitive.</p>
|
||||
*
|
||||
* <pre>
|
||||
* StringUtils.equals(null, null) = true
|
||||
* StringUtils.equals(null, "abc") = false
|
||||
* StringUtils.equals("abc", null) = false
|
||||
* StringUtils.equals("abc", "abc") = true
|
||||
* StringUtils.equals("abc", "ABC") = false
|
||||
* </pre>
|
||||
*
|
||||
* @param cs1 the first CharSequence, may be {@code null}
|
||||
* @param cs2 the second CharSequence, may be {@code null}
|
||||
* @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null}
|
||||
* @see Object#equals(Object)
|
||||
* @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence)
|
||||
*/
|
||||
public static boolean equals(final CharSequence cs1, final CharSequence cs2) {
|
||||
if (cs1 == cs2) {
|
||||
return true;
|
||||
}
|
||||
if (cs1 == null || cs2 == null) {
|
||||
return false;
|
||||
}
|
||||
if (cs1 instanceof String && cs2 instanceof String) {
|
||||
return cs1.equals(cs2);
|
||||
}
|
||||
return StringUtils.regionMatches(cs1, false, 0, cs2, 0, Math.max(cs1.length(), cs2.length()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Green implementation of regionMatches.
|
||||
*
|
||||
* @param cs the {@code CharSequence} to be processed
|
||||
* @param ignoreCase whether or not to be case insensitive
|
||||
* @param thisStart the index to start on the {@code cs} CharSequence
|
||||
* @param substring the {@code CharSequence} to be looked for
|
||||
* @param start the index to start on the {@code substring} CharSequence
|
||||
* @param length character length of the region
|
||||
* @return whether the region matched
|
||||
*/
|
||||
public static boolean regionMatches(final CharSequence cs, final boolean ignoreCase, final int thisStart,
|
||||
final CharSequence substring, final int start, final int length) {
|
||||
if (cs instanceof String && substring instanceof String) {
|
||||
return ((String) cs).regionMatches(ignoreCase, thisStart, (String) substring, start, length);
|
||||
}
|
||||
int index1 = thisStart;
|
||||
int index2 = start;
|
||||
int tmpLen = length;
|
||||
|
||||
while (tmpLen-- > 0) {
|
||||
final char c1 = cs.charAt(index1++);
|
||||
final char c2 = substring.charAt(index2++);
|
||||
|
||||
if (c1 == c2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ignoreCase) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The same check as in String.regionMatches():
|
||||
if (Character.toUpperCase(c1) != Character.toUpperCase(c2) && Character.toLowerCase(c1) != Character
|
||||
.toLowerCase(c2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -23,7 +23,9 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class ServiceInfoTest {
|
||||
|
||||
|
@ -30,7 +30,7 @@ import java.io.IOException;
|
||||
|
||||
public class AbstractHealthCheckerTest {
|
||||
|
||||
private ObjectMapper objectMapper = new ObjectMapper();
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
@ -16,12 +16,13 @@
|
||||
|
||||
package com.alibaba.nacos.api.naming.pojo.healthcheck;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Tcp;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class HealthCheckerFactoryTest {
|
||||
|
||||
@Test
|
||||
|
@ -16,8 +16,6 @@
|
||||
|
||||
package com.alibaba.nacos.api.naming.pojo.healthcheck.impl;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Before;
|
||||
@ -26,6 +24,9 @@ import org.junit.Test;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class MysqlTest {
|
||||
|
||||
private ObjectMapper objectMapper;
|
||||
|
@ -16,6 +16,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.utils.HttpMethod;
|
||||
import com.alibaba.nacos.common.utils.IoUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
@ -35,7 +36,9 @@ import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
|
||||
|
||||
/**
|
||||
* @author nkorange
|
||||
* @deprecated Use NacosRestTemplate{@link NacosRestTemplate} unified http client
|
||||
*/
|
||||
@Deprecated
|
||||
public class HttpClient {
|
||||
|
||||
public static final int READ_TIME_OUT_MILLIS = Integer
|
||||
|
@ -16,17 +16,19 @@
|
||||
|
||||
package com.alibaba.nacos.client.naming.net;
|
||||
|
||||
import com.alibaba.nacos.common.http.*;
|
||||
import com.alibaba.nacos.common.http.AbstractHttpClientFactory;
|
||||
import com.alibaba.nacos.common.http.HttpClientBeanHolder;
|
||||
import com.alibaba.nacos.common.http.HttpClientConfig;
|
||||
import com.alibaba.nacos.common.http.HttpClientFactory;
|
||||
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
|
||||
|
||||
/**
|
||||
* http Manager
|
||||
*
|
||||
* @author mai.jh
|
||||
* @date 2020/6/14
|
||||
*/
|
||||
public class NamingHttpClientManager {
|
||||
|
||||
|
||||
private static final int READ_TIME_OUT_MILLIS = Integer
|
||||
.getInteger("com.alibaba.nacos.client.naming.rtimeout", 50000);
|
||||
private static final int CON_TIME_OUT_MILLIS = Integer
|
||||
@ -34,22 +36,22 @@ public class NamingHttpClientManager {
|
||||
private static final boolean ENABLE_HTTPS = Boolean
|
||||
.getBoolean("com.alibaba.nacos.client.naming.tls.enable");
|
||||
private static final int MAX_REDIRECTS = 5;
|
||||
|
||||
|
||||
private static final HttpClientFactory HTTP_CLIENT_FACTORY = new NamingHttpClientFactory();
|
||||
|
||||
|
||||
public static String getPrefix() {
|
||||
if (ENABLE_HTTPS) {
|
||||
return "https://";
|
||||
}
|
||||
return "http://";
|
||||
}
|
||||
|
||||
|
||||
public static NacosRestTemplate getNacosRestTemplate() {
|
||||
return HttpClientBeanHolder.getNacosRestTemplate(HTTP_CLIENT_FACTORY);
|
||||
}
|
||||
|
||||
|
||||
private static class NamingHttpClientFactory extends AbstractHttpClientFactory {
|
||||
|
||||
|
||||
@Override
|
||||
protected HttpClientConfig buildHttpClientConfig() {
|
||||
return HttpClientConfig.builder()
|
||||
|
@ -37,15 +37,19 @@ import com.alibaba.nacos.client.security.SecurityProxy;
|
||||
import com.alibaba.nacos.client.utils.AppNameUtils;
|
||||
import com.alibaba.nacos.client.utils.TemplateUtils;
|
||||
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
|
||||
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.lifecycle.Closeable;
|
||||
import com.alibaba.nacos.common.utils.*;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.apache.http.HttpStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@ -53,6 +57,7 @@ import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Collections;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
@ -67,6 +72,8 @@ import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
|
||||
*/
|
||||
public class NamingProxy implements Closeable {
|
||||
|
||||
private NacosRestTemplate nacosRestTemplate = NamingHttpClientManager.getNacosRestTemplate();
|
||||
|
||||
private static final int DEFAULT_SERVER_PORT = 8848;
|
||||
|
||||
private int serverPort = DEFAULT_SERVER_PORT;
|
||||
@ -144,15 +151,14 @@ public class NamingProxy implements Closeable {
|
||||
|
||||
try {
|
||||
String urlString = "http://" + endpoint + "/nacos/serverlist";
|
||||
List<String> headers = builderHeaders();
|
||||
|
||||
HttpClient.HttpResult result = HttpClient.httpGet(urlString, headers, null, UtilAndComs.ENCODING);
|
||||
if (HttpURLConnection.HTTP_OK != result.code) {
|
||||
Header header = builderHeader();
|
||||
HttpRestResult<String> restResult = nacosRestTemplate.get(urlString, header, Query.EMPTY, String.class);
|
||||
if (!restResult.ok()) {
|
||||
throw new IOException("Error while requesting: " + urlString + "'. Server returned: "
|
||||
+ result.code);
|
||||
+ restResult.getCode());
|
||||
}
|
||||
|
||||
String content = result.content;
|
||||
String content = restResult.getData();
|
||||
List<String> list = new ArrayList<String>();
|
||||
for (String line : IoUtils.readLines(new StringReader(content))) {
|
||||
if (!line.trim().isEmpty()) {
|
||||
@ -333,10 +339,10 @@ public class NamingProxy implements Closeable {
|
||||
NAMING_LOGGER.debug("[BEAT] {} sending beat to server: {}", namespaceId, beatInfo.toString());
|
||||
}
|
||||
Map<String, String> params = new HashMap<String, String>(8);
|
||||
String body = StringUtils.EMPTY;
|
||||
Map<String, String> bodyMap = new HashMap<String, String>(2);
|
||||
if (!lightBeatEnabled) {
|
||||
try {
|
||||
body = "beat=" + URLEncoder.encode(JacksonUtils.toJson(beatInfo), "UTF-8");
|
||||
bodyMap.put("beat", URLEncoder.encode(JacksonUtils.toJson(beatInfo), "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new NacosException(NacosException.SERVER_ERROR, "encode beatInfo error", e);
|
||||
}
|
||||
@ -346,7 +352,7 @@ public class NamingProxy implements Closeable {
|
||||
params.put(CommonParams.CLUSTER_NAME, beatInfo.getCluster());
|
||||
params.put("ip", beatInfo.getIp());
|
||||
params.put("port", String.valueOf(beatInfo.getPort()));
|
||||
String result = reqAPI(UtilAndComs.NACOS_URL_BASE + "/instance/beat", params, body, HttpMethod.PUT);
|
||||
String result = reqAPI(UtilAndComs.NACOS_URL_BASE + "/instance/beat", params, bodyMap, HttpMethod.PUT);
|
||||
return JacksonUtils.toObj(result);
|
||||
}
|
||||
|
||||
@ -399,10 +405,10 @@ public class NamingProxy implements Closeable {
|
||||
}
|
||||
|
||||
public String reqAPI(String api, Map<String, String> params, String method) throws NacosException {
|
||||
return reqAPI(api, params, StringUtils.EMPTY, method);
|
||||
return reqAPI(api, params, Collections.EMPTY_MAP, method);
|
||||
}
|
||||
|
||||
public String reqAPI(String api, Map<String, String> params, String body, String method) throws NacosException {
|
||||
public String reqAPI(String api, Map<String, String> params, Map<String, String> body, String method) throws NacosException {
|
||||
return reqAPI(api, params, body, getServerList(), method);
|
||||
}
|
||||
|
||||
@ -414,16 +420,16 @@ public class NamingProxy implements Closeable {
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
public String callServer(String api, Map<String, String> params, String body, String curServer) throws NacosException {
|
||||
public String callServer(String api, Map<String, String> params, Map<String, String> body, String curServer) throws NacosException {
|
||||
return callServer(api, params, body, curServer, HttpMethod.GET);
|
||||
}
|
||||
|
||||
public String callServer(String api, Map<String, String> params, String body, String curServer, String method)
|
||||
public String callServer(String api, Map<String, String> params, Map<String, String> body, String curServer, String method)
|
||||
throws NacosException {
|
||||
long start = System.currentTimeMillis();
|
||||
long end = 0;
|
||||
injectSecurityInfo(params);
|
||||
List<String> headers = builderHeaders();
|
||||
Header header = builderHeader();
|
||||
|
||||
String url;
|
||||
if (curServer.startsWith(UtilAndComs.HTTPS) || curServer.startsWith(UtilAndComs.HTTP)) {
|
||||
@ -432,27 +438,30 @@ public class NamingProxy implements Closeable {
|
||||
if (!curServer.contains(UtilAndComs.SERVER_ADDR_IP_SPLITER)) {
|
||||
curServer = curServer + UtilAndComs.SERVER_ADDR_IP_SPLITER + serverPort;
|
||||
}
|
||||
url = HttpClient.getPrefix() + curServer + api;
|
||||
url = NamingHttpClientManager.getPrefix() + curServer + api;
|
||||
}
|
||||
|
||||
HttpClient.HttpResult result = HttpClient.request(url, headers, params, body, UtilAndComs.ENCODING, method);
|
||||
end = System.currentTimeMillis();
|
||||
try {
|
||||
HttpRestResult<String> restResult = nacosRestTemplate.exchangeForm(url, header, params, body, method, String.class);
|
||||
end = System.currentTimeMillis();
|
||||
|
||||
MetricsMonitor.getNamingRequestMonitor(method, url, String.valueOf(result.code))
|
||||
.observe(end - start);
|
||||
MetricsMonitor.getNamingRequestMonitor(method, url, String.valueOf(restResult.getCode()))
|
||||
.observe(end - start);
|
||||
|
||||
if (HttpURLConnection.HTTP_OK == result.code) {
|
||||
return result.content;
|
||||
if (restResult.ok()) {
|
||||
return restResult.getData();
|
||||
}
|
||||
if (HttpStatus.SC_NOT_MODIFIED == restResult.getCode()) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
throw new NacosException(restResult.getCode(), restResult.getData());
|
||||
} catch (Exception e) {
|
||||
NAMING_LOGGER.error("[NA] failed to request", e);
|
||||
throw new NacosException(NacosException.SERVER_ERROR, e);
|
||||
}
|
||||
|
||||
if (HttpURLConnection.HTTP_NOT_MODIFIED == result.code) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
throw new NacosException(result.code, result.content);
|
||||
}
|
||||
|
||||
public String reqAPI(String api, Map<String, String> params, String body, List<String> servers, String method) throws NacosException {
|
||||
public String reqAPI(String api, Map<String, String> params, Map<String, String> body, List<String> servers, String method) throws NacosException {
|
||||
|
||||
params.put(CommonParams.NAMESPACE_ID, getNamespaceId());
|
||||
|
||||
@ -526,14 +535,15 @@ public class NamingProxy implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> builderHeaders() {
|
||||
List<String> headers = Arrays.asList(
|
||||
HttpHeaderConsts.CLIENT_VERSION_HEADER, VersionUtils.version,
|
||||
HttpHeaderConsts.USER_AGENT_HEADER, UtilAndComs.VERSION,
|
||||
"Accept-Encoding", "gzip,deflate,sdch",
|
||||
"Connection", "Keep-Alive",
|
||||
"RequestId", UuidUtils.generateUuid(), "Request-Module", "Naming");
|
||||
return headers;
|
||||
public Header builderHeader() {
|
||||
Header header = Header.newInstance();
|
||||
header.addParam(HttpHeaderConsts.CLIENT_VERSION_HEADER, VersionUtils.version);
|
||||
header.addParam(HttpHeaderConsts.USER_AGENT_HEADER, UtilAndComs.VERSION);
|
||||
header.addParam(HttpHeaderConsts.ACCEPT_ENCODING, "gzip,deflate,sdch");
|
||||
header.addParam(HttpHeaderConsts.CONNECTION, "Keep-Alive");
|
||||
header.addParam(HttpHeaderConsts.REQUEST_ID, UuidUtils.generateUuid());
|
||||
header.addParam(HttpHeaderConsts.REQUEST_MODULE, "Naming");
|
||||
return header;
|
||||
}
|
||||
|
||||
private static String getSignData(String serviceName) {
|
||||
|
@ -17,18 +17,21 @@ package com.alibaba.nacos.client.security;
|
||||
|
||||
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.client.naming.net.HttpClient;
|
||||
import com.alibaba.nacos.common.utils.HttpMethod;
|
||||
import com.alibaba.nacos.client.naming.net.NamingHttpClientManager;
|
||||
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.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
||||
import org.apache.commons.codec.Charsets;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.HttpURLConnection;
|
||||
import java.util.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@ -43,6 +46,8 @@ public class SecurityProxy {
|
||||
|
||||
private static final String LOGIN_URL = "/v1/auth/users/login";
|
||||
|
||||
private NacosRestTemplate nacosRestTemplate = NamingHttpClientManager.getNacosRestTemplate();
|
||||
|
||||
private String contextPath;
|
||||
|
||||
/**
|
||||
@ -110,28 +115,31 @@ public class SecurityProxy {
|
||||
|
||||
if (StringUtils.isNotBlank(username)) {
|
||||
Map<String, String> params = new HashMap<String, String>(2);
|
||||
Map<String, String> bodyMap = new HashMap<>(2);
|
||||
params.put("username", username);
|
||||
String body = "password=" + password;
|
||||
bodyMap.put("password", password);
|
||||
String url = "http://" + server + contextPath + LOGIN_URL;
|
||||
|
||||
if (server.contains(Constants.HTTP_PREFIX)) {
|
||||
url = server + contextPath + LOGIN_URL;
|
||||
}
|
||||
|
||||
HttpClient.HttpResult result = HttpClient.request(url, new ArrayList<String>(2),
|
||||
params, body, Charsets.UTF_8.name(), HttpMethod.POST);
|
||||
|
||||
if (result.code != HttpURLConnection.HTTP_OK) {
|
||||
SECURITY_LOGGER.error("login failed: {}", JacksonUtils.toJson(result));
|
||||
try {
|
||||
HttpRestResult<String> restResult = nacosRestTemplate.postForm(url, Header.EMPTY, params, bodyMap, String.class);
|
||||
if (!restResult.ok()) {
|
||||
SECURITY_LOGGER.error("login failed: {}", JacksonUtils.toJson(restResult));
|
||||
return false;
|
||||
}
|
||||
JsonNode obj = JacksonUtils.toObj(restResult.getData());
|
||||
if (obj.has(Constants.ACCESS_TOKEN)) {
|
||||
accessToken = obj.get(Constants.ACCESS_TOKEN).asText();
|
||||
tokenTtl = obj.get(Constants.TOKEN_TTL).asInt();
|
||||
tokenRefreshWindow = tokenTtl / 10;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
SECURITY_LOGGER.error("[SecurityProxy] login http request failed" +
|
||||
" url: {}, params: {}, bodyMap: {}, errorMsg: {}", url, params, bodyMap, e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
JsonNode obj = JacksonUtils.toObj(result.content);
|
||||
if (obj.has(Constants.ACCESS_TOKEN)) {
|
||||
accessToken = obj.get(Constants.ACCESS_TOKEN).asText();
|
||||
tokenTtl = obj.get(Constants.TOKEN_TTL).asInt();
|
||||
tokenRefreshWindow = tokenTtl / 10;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation that marks a method as not thread safe.
|
||||
*
|
||||
* @author zongtanghu
|
||||
*/
|
||||
@Documented
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface NotThreadSafe {
|
||||
|
||||
}
|
@ -193,7 +193,7 @@ public enum BaseHttpMethod {
|
||||
* @throws Exception exception
|
||||
*/
|
||||
public void initFromEntity(Map<String, String> body, String charset) throws Exception {
|
||||
if (body.isEmpty()) {
|
||||
if (body == null || body.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<NameValuePair> params = new ArrayList<NameValuePair>(body.size());
|
||||
|
@ -37,15 +37,9 @@ public final class HttpClientBeanHolder {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientManager.class);
|
||||
|
||||
private static final int TIMEOUT = Integer.getInteger("nacos.http.timeout", 5000);
|
||||
|
||||
private static final HttpClientConfig HTTP_CLIENT_CONFIG = HttpClientConfig.builder().setConTimeOutMillis(TIMEOUT)
|
||||
.setReadTimeOutMillis(TIMEOUT >> 1).build();
|
||||
|
||||
private static final Map<String, NacosRestTemplate> SINGLETON_REST = new HashMap<String, NacosRestTemplate>(10);
|
||||
|
||||
private static final Map<String, NacosAsyncRestTemplate> SINGLETON_ASYNC_REST = new HashMap<String, NacosAsyncRestTemplate>(
|
||||
10);
|
||||
private static final Map<String, NacosAsyncRestTemplate> SINGLETON_ASYNC_REST = new HashMap<String, NacosAsyncRestTemplate>(10);
|
||||
|
||||
private static final AtomicBoolean ALREADY_SHUTDOWN = new AtomicBoolean(false);
|
||||
|
||||
|
@ -26,7 +26,6 @@ import java.io.InputStream;
|
||||
* Represents a client-side HTTP response.
|
||||
*
|
||||
* @author mai.jh
|
||||
* @date 2020/5/23
|
||||
*/
|
||||
public interface HttpClientResponse extends Closeable {
|
||||
|
||||
|
@ -197,7 +197,7 @@ public class NacosAsyncRestTemplate {
|
||||
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> void putFrom(String url, Header header, Query query, Map<String, String> bodyValues, Type responseType,
|
||||
public <T> void putForm(String url, Header header, Query query, Map<String, String> bodyValues, Type responseType,
|
||||
Callback<T> callback) throws Exception {
|
||||
execute(url, HttpMethod.PUT,
|
||||
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues),
|
||||
@ -223,7 +223,7 @@ public class NacosAsyncRestTemplate {
|
||||
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> void putFrom(String url, Header header, Map<String, String> paramValues, Map<String, String> bodyValues,
|
||||
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);
|
||||
@ -296,7 +296,7 @@ public class NacosAsyncRestTemplate {
|
||||
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> void postFrom(String url, Header header, Query query, Map<String, String> bodyValues, Type responseType,
|
||||
public <T> void postForm(String url, Header header, Query query, Map<String, String> bodyValues, Type responseType,
|
||||
Callback<T> callback) throws Exception {
|
||||
execute(url, HttpMethod.POST,
|
||||
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues),
|
||||
@ -322,7 +322,7 @@ public class NacosAsyncRestTemplate {
|
||||
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> void postFrom(String url, Header header, Map<String, String> paramValues, Map<String, String> bodyValues,
|
||||
public <T> void postForm(String url, Header header, Map<String, String> paramValues, Map<String, String> bodyValues,
|
||||
Type responseType, Callback<T> callback) throws Exception {
|
||||
execute(url, HttpMethod.POST,
|
||||
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
|
||||
|
@ -35,7 +35,6 @@ import java.util.Map;
|
||||
* Nacos rest template Interface specifying a basic set of RESTful operations.
|
||||
*
|
||||
* @author mai.jh
|
||||
* @date 2020/5/24
|
||||
* @see HttpClientRequest
|
||||
* @see HttpClientResponse
|
||||
*/
|
||||
@ -178,7 +177,7 @@ public class NacosRestTemplate {
|
||||
* @return {@link HttpRestResult}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> HttpRestResult<T> putFrom(String url, Header header, Query query, Map<String, String> bodyValues,
|
||||
public <T> HttpRestResult<T> putForm(String url, Header header, Query query, Map<String, String> bodyValues,
|
||||
Type responseType) throws Exception {
|
||||
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(
|
||||
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues);
|
||||
@ -201,7 +200,7 @@ public class NacosRestTemplate {
|
||||
* @return {@link HttpRestResult}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> HttpRestResult<T> putFrom(String url, Header header, Map<String, String> paramValues,
|
||||
public <T> HttpRestResult<T> putForm(String url, Header header, Map<String, String> paramValues,
|
||||
Map<String, String> bodyValues, Type responseType) throws Exception {
|
||||
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(
|
||||
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
|
||||
@ -268,7 +267,7 @@ public class NacosRestTemplate {
|
||||
* @return {@link HttpRestResult}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> HttpRestResult<T> postFrom(String url, Header header, Query query, Map<String, String> bodyValues,
|
||||
public <T> HttpRestResult<T> postForm(String url, Header header, Query query, Map<String, String> bodyValues,
|
||||
Type responseType) throws Exception {
|
||||
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(
|
||||
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues);
|
||||
@ -291,7 +290,7 @@ public class NacosRestTemplate {
|
||||
* @return {@link HttpRestResult}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> HttpRestResult<T> postFrom(String url, Header header, Map<String, String> paramValues,
|
||||
public <T> HttpRestResult<T> postForm(String url, Header header, Map<String, String> paramValues,
|
||||
Map<String, String> bodyValues, Type responseType) throws Exception {
|
||||
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(
|
||||
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
|
||||
@ -299,6 +298,28 @@ public class NacosRestTemplate {
|
||||
return execute(url, HttpMethod.POST, 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 header http header param
|
||||
* @param paramValues 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{
|
||||
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(
|
||||
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
|
||||
Query.newInstance().initParams(paramValues),
|
||||
bodyValues);
|
||||
return execute(url, httpMethod, requestHttpEntity, responseType);
|
||||
}
|
||||
|
||||
private <T> HttpRestResult<T> execute(String url, String httpMethod, RequestHttpEntity requestEntity,
|
||||
Type responseType) throws Exception {
|
||||
URI uri = HttpUtils.buildUri(url, requestEntity.getQuery());
|
||||
|
@ -78,14 +78,22 @@ public final class ResponseHandler {
|
||||
String contentType = headers.getValue(HttpHeaderConsts.CONTENT_TYPE);
|
||||
InputStream body = response.getBody();
|
||||
T extractBody = null;
|
||||
final boolean typeToStr = String.class.toString().equals(type.toString());
|
||||
if (contentType != null && contentType.startsWith(MediaType.APPLICATION_JSON) && HttpStatus.SC_OK == response
|
||||
.getStatusCode()) {
|
||||
extractBody = convert(body, type);
|
||||
.getStatusCode()) {
|
||||
// When the type is string type and the response contentType is [application/json],
|
||||
// then it should be serialized as string
|
||||
if (typeToStr) {
|
||||
extractBody = (T) IoUtils.toString(body, headers.getCharset());
|
||||
} else {
|
||||
extractBody = convert(body, type);
|
||||
}
|
||||
}
|
||||
if (extractBody == null) {
|
||||
if (!String.class.toString().equals(type.toString())) {
|
||||
if (!typeToStr) {
|
||||
LOGGER.error(
|
||||
"if the response contentType is not [application/json]," + " only support to java.lang.String");
|
||||
"if the response contentType is not [application/json]," +
|
||||
" only support to java.lang.String");
|
||||
throw new NacosDeserializationException(type);
|
||||
}
|
||||
extractBody = (T) IoUtils.toString(body, headers.getCharset());
|
||||
|
@ -0,0 +1,210 @@
|
||||
/*
|
||||
* 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.notify;
|
||||
|
||||
import com.alibaba.nacos.common.notify.listener.Subscriber;
|
||||
import com.alibaba.nacos.common.utils.ConcurrentHashSet;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import com.alibaba.nacos.common.utils.CollectionUtils;
|
||||
import com.alibaba.nacos.common.utils.ClassUtils;
|
||||
import com.alibaba.nacos.common.utils.Objects;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
|
||||
|
||||
import static com.alibaba.nacos.common.notify.NotifyCenter.ringBufferSize;
|
||||
|
||||
/**
|
||||
* The default event publisher implementation.
|
||||
*
|
||||
* <p>Internally, use {@link ArrayBlockingQueue <Event/>} as a message staging queue.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
* @author zongtanghu
|
||||
*/
|
||||
public class DefaultPublisher extends Thread implements EventPublisher {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NotifyCenter.class);
|
||||
|
||||
private volatile boolean initialized = false;
|
||||
|
||||
private volatile boolean shutdown = false;
|
||||
|
||||
private Class<? extends Event> eventType;
|
||||
|
||||
private final ConcurrentHashSet<Subscriber> subscribers = new ConcurrentHashSet<Subscriber>();
|
||||
|
||||
private int queueMaxSize = -1;
|
||||
|
||||
private BlockingQueue<Event> queue;
|
||||
|
||||
private volatile Long lastEventSequence = -1L;
|
||||
|
||||
private final AtomicReferenceFieldUpdater<DefaultPublisher, Long> updater = AtomicReferenceFieldUpdater
|
||||
.newUpdater(DefaultPublisher.class, Long.class, "lastEventSequence");
|
||||
|
||||
@Override
|
||||
public void init(Class<? extends Event> type, int bufferSize) {
|
||||
setDaemon(true);
|
||||
setName("nacos.publisher-" + type.getName());
|
||||
this.eventType = type;
|
||||
this.queueMaxSize = bufferSize;
|
||||
this.queue = new ArrayBlockingQueue<Event>(bufferSize);
|
||||
start();
|
||||
}
|
||||
|
||||
public ConcurrentHashSet<Subscriber> getSubscribers() {
|
||||
return subscribers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void start() {
|
||||
if (!initialized) {
|
||||
// start just called once
|
||||
super.start();
|
||||
if (queueMaxSize == -1) {
|
||||
queueMaxSize = ringBufferSize;
|
||||
}
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
public long currentEventSize() {
|
||||
return queue.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
openEventHandler();
|
||||
}
|
||||
|
||||
void openEventHandler() {
|
||||
try {
|
||||
// To ensure that messages are not lost, enable EventHandler when
|
||||
// waiting for the first Subscriber to register
|
||||
for (; ; ) {
|
||||
if (shutdown || hasSubscriber()) {
|
||||
break;
|
||||
}
|
||||
ThreadUtils.sleep(1000L);
|
||||
}
|
||||
|
||||
for (; ; ) {
|
||||
if (shutdown) {
|
||||
break;
|
||||
}
|
||||
final Event event = queue.take();
|
||||
receiveEvent(event);
|
||||
updater.compareAndSet(this, lastEventSequence, Math.max(lastEventSequence, event.sequence()));
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
LOGGER.error("Event listener exception : {}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasSubscriber() {
|
||||
return CollectionUtils.isNotEmpty(subscribers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSubscriber(Subscriber subscriber) {
|
||||
subscribers.add(subscriber);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSubscriber(Subscriber subscriber) {
|
||||
subscribers.remove(subscriber);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean publish(Event event) {
|
||||
checkIsStart();
|
||||
boolean success = this.queue.offer(event);
|
||||
if (!success) {
|
||||
LOGGER.warn("Unable to plug in due to interruption, synchronize sending time, event : {}", event);
|
||||
receiveEvent(event);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void checkIsStart() {
|
||||
if (!initialized) {
|
||||
throw new IllegalStateException("Publisher does not start");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
this.shutdown = true;
|
||||
this.queue.clear();
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void receiveEvent(Event event) {
|
||||
final long currentEventSequence = event.sequence();
|
||||
final String sourceName = ClassUtils.getName(event);
|
||||
|
||||
// Notification single event listener
|
||||
for (Subscriber subscriber : subscribers) {
|
||||
// Whether to ignore expiration events
|
||||
if (subscriber.ignoreExpireEvent() && lastEventSequence > currentEventSequence) {
|
||||
LOGGER.debug("[NotifyCenter] the {} is unacceptable to this subscriber, because had expire",
|
||||
event.getClass());
|
||||
continue;
|
||||
}
|
||||
|
||||
final String targetName = ClassUtils.getName(subscriber.subscribeType());
|
||||
if (!Objects.equals(sourceName, targetName)) {
|
||||
continue;
|
||||
}
|
||||
notifySubscriber(subscriber, event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifySubscriber(final Subscriber subscriber, final Event event) {
|
||||
|
||||
LOGGER.debug("[NotifyCenter] the {} will received by {}", event, subscriber);
|
||||
|
||||
final Runnable job = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
subscriber.onEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
final Executor executor = subscriber.executor();
|
||||
|
||||
if (executor != null) {
|
||||
executor.execute(job);
|
||||
} else {
|
||||
try {
|
||||
job.run();
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Event callback exception : {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.notify;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* An abstract class for event.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
* @author zongtanghu
|
||||
*/
|
||||
@SuppressWarnings({"PMD.AbstractClassShouldStartWithAbstractNamingRule"})
|
||||
public abstract class Event implements Serializable {
|
||||
|
||||
private static final AtomicLong SEQUENCE = new AtomicLong(0);
|
||||
|
||||
private final long sequence = SEQUENCE.getAndIncrement();
|
||||
|
||||
/**
|
||||
* Event sequence number, which can be used to handle the sequence of events.
|
||||
*
|
||||
* @return sequence num, It's best to make sure it's monotone.
|
||||
*/
|
||||
public long sequence() {
|
||||
return sequence;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.notify;
|
||||
|
||||
import com.alibaba.nacos.common.lifecycle.Closeable;
|
||||
import com.alibaba.nacos.common.notify.listener.Subscriber;
|
||||
|
||||
/**
|
||||
* Event publisher.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
* @author zongtanghu
|
||||
*/
|
||||
public interface EventPublisher extends Closeable {
|
||||
|
||||
/**
|
||||
* Initializes the event publisher.
|
||||
*
|
||||
* @param type {@link Event >}
|
||||
* @param bufferSize Message staging queue size
|
||||
*/
|
||||
void init(Class<? extends Event> type, int bufferSize);
|
||||
|
||||
/**
|
||||
* The number of currently staged events.
|
||||
*
|
||||
* @return event size
|
||||
*/
|
||||
long currentEventSize();
|
||||
|
||||
/**
|
||||
* Add listener.
|
||||
*
|
||||
* @param subscriber {@link Subscriber}
|
||||
*/
|
||||
void addSubscriber(Subscriber subscriber);
|
||||
|
||||
/**
|
||||
* Remove listener.
|
||||
*
|
||||
* @param subscriber {@link Subscriber}
|
||||
*/
|
||||
void removeSubscriber(Subscriber subscriber);
|
||||
|
||||
/**
|
||||
* publish event.
|
||||
*
|
||||
* @param event {@link Event}
|
||||
* @return publish event is success
|
||||
*/
|
||||
boolean publish(Event event);
|
||||
|
||||
/**
|
||||
* Notify listener.
|
||||
*
|
||||
* @param subscriber {@link Subscriber}
|
||||
* @param event {@link Event}
|
||||
*/
|
||||
void notifySubscriber(Subscriber subscriber, Event event);
|
||||
}
|
@ -0,0 +1,323 @@
|
||||
/*
|
||||
* 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.notify;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.common.JustForTest;
|
||||
import com.alibaba.nacos.common.notify.listener.Subscriber;
|
||||
import com.alibaba.nacos.common.notify.listener.SmartSubscriber;
|
||||
import com.alibaba.nacos.common.utils.BiFunction;
|
||||
import com.alibaba.nacos.common.utils.ClassUtils;
|
||||
import com.alibaba.nacos.common.utils.MapUtils;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static com.alibaba.nacos.api.exception.NacosException.SERVER_ERROR;
|
||||
|
||||
/**
|
||||
* Unified Event Notify Center.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
* @author zongtanghu
|
||||
*/
|
||||
public class NotifyCenter {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NotifyCenter.class);
|
||||
|
||||
public static int ringBufferSize = 16384;
|
||||
|
||||
public static int shareBufferSize = 1024;
|
||||
|
||||
private static final AtomicBoolean CLOSED = new AtomicBoolean(false);
|
||||
|
||||
private static BiFunction<Class<? extends Event>, Integer, EventPublisher> publisherFactory = null;
|
||||
|
||||
private static final NotifyCenter INSTANCE = new NotifyCenter();
|
||||
|
||||
private EventPublisher sharePublisher;
|
||||
|
||||
private static Class<? extends EventPublisher> clazz = null;
|
||||
|
||||
/**
|
||||
* Publisher management container.
|
||||
*/
|
||||
private final Map<String, EventPublisher> publisherMap = new ConcurrentHashMap<String, EventPublisher>(16);
|
||||
|
||||
static {
|
||||
// Internal ArrayBlockingQueue buffer size. For applications with high write throughput,
|
||||
// this value needs to be increased appropriately. default value is 16384
|
||||
String ringBufferSizeProperty = "nacos.core.notify.ring-buffer-size";
|
||||
ringBufferSize = Integer.getInteger(ringBufferSizeProperty, 16384);
|
||||
|
||||
// The size of the public publisher's message staging queue buffer
|
||||
String shareBufferSizeProperty = "nacos.core.notify.share-buffer-size";
|
||||
shareBufferSize = Integer.getInteger(shareBufferSizeProperty, 1024);
|
||||
|
||||
final ServiceLoader<EventPublisher> loader = ServiceLoader.load(EventPublisher.class);
|
||||
Iterator<EventPublisher> iterator = loader.iterator();
|
||||
|
||||
if (iterator.hasNext()) {
|
||||
clazz = iterator.next().getClass();
|
||||
} else {
|
||||
clazz = DefaultPublisher.class;
|
||||
}
|
||||
|
||||
publisherFactory = new BiFunction<Class<? extends Event>, Integer, EventPublisher>() {
|
||||
|
||||
@Override
|
||||
public EventPublisher apply(Class<? extends Event> cls, Integer buffer) throws NacosException {
|
||||
try {
|
||||
EventPublisher publisher = clazz.newInstance();
|
||||
publisher.init(cls, buffer);
|
||||
return publisher;
|
||||
} catch (Throwable ex) {
|
||||
LOGGER.error("Service class newInstance has error : {}", ex);
|
||||
throw new NacosException(SERVER_ERROR, ex);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
INSTANCE.sharePublisher = publisherFactory.apply(SlowEvent.class, shareBufferSize);
|
||||
} catch (Throwable ex) {
|
||||
LOGGER.error("Service class newInstance has error : {}", ex);
|
||||
}
|
||||
|
||||
ThreadUtils.addShutdownHook(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
shutdown();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@JustForTest
|
||||
public static Map<String, EventPublisher> getPublisherMap() {
|
||||
return INSTANCE.publisherMap;
|
||||
}
|
||||
|
||||
@JustForTest
|
||||
public static EventPublisher getPublisher(Class<? extends Event> topic) {
|
||||
if (ClassUtils.isAssignableFrom(SlowEvent.class, topic)) {
|
||||
return INSTANCE.sharePublisher;
|
||||
}
|
||||
return INSTANCE.publisherMap.get(topic.getCanonicalName());
|
||||
}
|
||||
|
||||
@JustForTest
|
||||
public static EventPublisher getSharePublisher() {
|
||||
return INSTANCE.sharePublisher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown the serveral publisher instance which notifycenter has.
|
||||
*/
|
||||
public static void shutdown() {
|
||||
if (!CLOSED.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
LOGGER.warn("[NotifyCenter] Start destroying Publisher");
|
||||
|
||||
for (Map.Entry<String, EventPublisher> entry : INSTANCE.publisherMap.entrySet()) {
|
||||
try {
|
||||
EventPublisher eventPublisher = entry.getValue();
|
||||
eventPublisher.shutdown();
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("[EventPublisher] shutdown has error : {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
INSTANCE.sharePublisher.shutdown();
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("[SharePublisher] shutdown has error : {}", e);
|
||||
}
|
||||
|
||||
LOGGER.warn("[NotifyCenter] Destruction of the end");
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a Subscriber. If the Publisher concerned by the Subscriber does not exist, then PublihserMap will
|
||||
* preempt a placeholder Publisher first.
|
||||
*
|
||||
* @param consumer subscriber
|
||||
* @param <T> event type
|
||||
*/
|
||||
public static <T> void registerSubscriber(final Subscriber consumer) throws NacosException {
|
||||
final Class<? extends Event> cls = consumer.subscribeType();
|
||||
// If you want to listen to multiple events, you do it separately,
|
||||
// based on subclass's subscribeTypes method return list, it can register to publisher.
|
||||
if (consumer instanceof SmartSubscriber) {
|
||||
for (Class<? extends Event> subscribeType : ((SmartSubscriber) consumer).subscribeTypes()) {
|
||||
addSubscriber(consumer, subscribeType);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (ClassUtils.isAssignableFrom(SlowEvent.class, cls)) {
|
||||
INSTANCE.sharePublisher.addSubscriber(consumer);
|
||||
return;
|
||||
}
|
||||
|
||||
addSubscriber(consumer, consumer.subscribeType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a subscriber to pusblisher.
|
||||
*
|
||||
* @param consumer subscriber instance.
|
||||
* @param subscribeType subscribeType.
|
||||
* @throws NacosException BiFunction mappingFunction may throw a NacosException.
|
||||
*/
|
||||
private static void addSubscriber(final Subscriber consumer, Class<? extends Event> subscribeType)
|
||||
throws NacosException {
|
||||
|
||||
final String topic = ClassUtils.getCanonicalName(subscribeType);
|
||||
MapUtils.computeIfAbsent(INSTANCE.publisherMap, topic, publisherFactory, subscribeType, ringBufferSize);
|
||||
EventPublisher publisher = INSTANCE.publisherMap.get(topic);
|
||||
publisher.addSubscriber(consumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deregister subscriber.
|
||||
*
|
||||
* @param consumer subscriber instance.
|
||||
*/
|
||||
public static <T> void deregisterSubscriber(final Subscriber consumer) {
|
||||
final Class<? extends Event> cls = consumer.subscribeType();
|
||||
if (consumer instanceof SmartSubscriber) {
|
||||
for (Class<? extends Event> subscribeType : ((SmartSubscriber) consumer).subscribeTypes()) {
|
||||
removeSubscriber(consumer, subscribeType);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (ClassUtils.isAssignableFrom(SlowEvent.class, cls)) {
|
||||
INSTANCE.sharePublisher.removeSubscriber(consumer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (removeSubscriber(consumer, consumer.subscribeType())) {
|
||||
return;
|
||||
}
|
||||
throw new NoSuchElementException("The subcriber has no event publisher");
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove subscriber.
|
||||
*
|
||||
* @param consumer subscriber instance.
|
||||
* @param subscribeType subscribeType.
|
||||
* @return whether remove subscriber successfully or not.
|
||||
*/
|
||||
private static boolean removeSubscriber(final Subscriber consumer, Class<? extends Event> subscribeType) {
|
||||
|
||||
final String topic = ClassUtils.getCanonicalName(subscribeType);
|
||||
if (INSTANCE.publisherMap.containsKey(topic)) {
|
||||
EventPublisher publisher = INSTANCE.publisherMap.get(topic);
|
||||
publisher.removeSubscriber(consumer);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request publisher publish event Publishers load lazily, calling publisher. Start () only when the event is
|
||||
* actually published.
|
||||
*
|
||||
* @param event class Instances of the event.
|
||||
*/
|
||||
public static boolean publishEvent(final Event event) {
|
||||
try {
|
||||
return publishEvent(event.getClass(), event);
|
||||
} catch (Throwable ex) {
|
||||
LOGGER.error("There was an exception to the message publishing : {}", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request publisher publish event Publishers load lazily, calling publisher.
|
||||
*
|
||||
* @param eventType class Instances type of the event type.
|
||||
* @param event event instance.
|
||||
*/
|
||||
private static boolean publishEvent(final Class<? extends Event> eventType, final Event event) {
|
||||
final String topic = ClassUtils.getCanonicalName(eventType);
|
||||
if (ClassUtils.isAssignableFrom(SlowEvent.class, eventType)) {
|
||||
return INSTANCE.sharePublisher.publish(event);
|
||||
}
|
||||
|
||||
if (INSTANCE.publisherMap.containsKey(topic)) {
|
||||
EventPublisher publisher = INSTANCE.publisherMap.get(topic);
|
||||
return publisher.publish(event);
|
||||
}
|
||||
throw new NoSuchElementException("There are no [" + topic + "] publishers for this event, please register");
|
||||
}
|
||||
|
||||
/**
|
||||
* Register to share-publisher.
|
||||
*
|
||||
* @param eventType class Instances type of the event type.
|
||||
* @return share publisher instance.
|
||||
*/
|
||||
public static EventPublisher registerToSharePublisher(final Class<? extends SlowEvent> eventType) {
|
||||
return INSTANCE.sharePublisher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register publisher.
|
||||
*
|
||||
* @param eventType class Instances type of the event type.
|
||||
* @param queueMaxSize the publisher's queue max size.
|
||||
*/
|
||||
public static EventPublisher registerToPublisher(final Class<? extends Event> eventType, final int queueMaxSize)
|
||||
throws NacosException {
|
||||
if (ClassUtils.isAssignableFrom(SlowEvent.class, eventType)) {
|
||||
return INSTANCE.sharePublisher;
|
||||
}
|
||||
|
||||
final String topic = ClassUtils.getCanonicalName(eventType);
|
||||
MapUtils.computeIfAbsent(INSTANCE.publisherMap, topic, publisherFactory, eventType, queueMaxSize);
|
||||
EventPublisher publisher = INSTANCE.publisherMap.get(topic);
|
||||
return publisher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deregister publisher.
|
||||
*
|
||||
* @param eventType class Instances type of the event type.
|
||||
*/
|
||||
public static void deregisterPublisher(final Class<? extends Event> eventType) {
|
||||
final String topic = ClassUtils.getCanonicalName(eventType);
|
||||
EventPublisher publisher = INSTANCE.publisherMap.remove(topic);
|
||||
try {
|
||||
publisher.shutdown();
|
||||
} catch (Throwable ex) {
|
||||
LOGGER.error("There was an exception when publisher shutdown : {}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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.notify;
|
||||
|
||||
/**
|
||||
* This event share one event-queue.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
* @author zongtanghu
|
||||
*/
|
||||
@SuppressWarnings("PMD.AbstractClassShouldStartWithAbstractNamingRule")
|
||||
public abstract class SlowEvent extends Event {
|
||||
|
||||
@Override
|
||||
public long sequence() {
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.notify.listener;
|
||||
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Subscribers to multiple events can be listened to.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
* @author zongtanghu
|
||||
*/
|
||||
@SuppressWarnings("PMD.AbstractClassShouldStartWithAbstractNamingRule")
|
||||
public abstract class SmartSubscriber extends Subscriber {
|
||||
|
||||
/**
|
||||
* Returns which event type are smartsubscriber interested in.
|
||||
*
|
||||
* @return The interestd event types.
|
||||
*/
|
||||
public abstract List<Class<? extends Event>> subscribeTypes();
|
||||
|
||||
@Override
|
||||
public final Class<? extends Event> subscribeType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean ignoreExpireEvent() {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.notify.listener;
|
||||
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* An abstract subscriber class for subscriber interface.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
* @author zongtanghu
|
||||
*/
|
||||
@SuppressWarnings("PMD.AbstractClassShouldStartWithAbstractNamingRule")
|
||||
public abstract class Subscriber<T extends Event> {
|
||||
|
||||
/**
|
||||
* Event callback.
|
||||
*
|
||||
* @param event {@link Event}
|
||||
*/
|
||||
public abstract void onEvent(T event);
|
||||
|
||||
/**
|
||||
* Type of this subscriber's subscription.
|
||||
*
|
||||
* @return Class which extends {@link Event}
|
||||
*/
|
||||
public abstract Class<? extends Event> subscribeType();
|
||||
|
||||
/**
|
||||
* It is up to the listener to determine whether the callback is asynchronous or synchronous.
|
||||
*
|
||||
* @return {@link Executor}
|
||||
*/
|
||||
public Executor executor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to ignore expired events.
|
||||
*
|
||||
* @return default value is {@link Boolean#FALSE}
|
||||
*/
|
||||
public boolean ignoreExpireEvent() {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 com.alibaba.nacos.api.exception.NacosException;
|
||||
|
||||
/**
|
||||
* Represents a function that accepts two arguments and produces a result.
|
||||
* The following utility functions are extracted from org.apache.commons.lang3.
|
||||
*
|
||||
* <p>This is a <a href="package-summary.html">functional interface</a>
|
||||
* whose functional method is {@link #apply(Object, Object)}.
|
||||
*
|
||||
* @author zongtanghu
|
||||
*
|
||||
*/
|
||||
public interface BiFunction<T, U, R> {
|
||||
|
||||
/**
|
||||
* Applies this function to the two given arguments.
|
||||
*
|
||||
* @param t the first function argument
|
||||
* @param u the second function argument
|
||||
* @return the function result
|
||||
* @throws NacosException function throws NacosException
|
||||
*/
|
||||
R apply(T t, U u) throws NacosException;
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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 com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
|
||||
|
||||
import static com.alibaba.nacos.api.exception.NacosException.SERVER_ERROR;
|
||||
|
||||
/**
|
||||
* Utils for Class.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public final class ClassUtils {
|
||||
|
||||
/**
|
||||
* Finds and returns class by className.
|
||||
*
|
||||
* @param className String value for className.
|
||||
* @return class Instances of the class represent classes and interfaces.
|
||||
*/
|
||||
public static Class findClassByName(String className) {
|
||||
try {
|
||||
return Class.forName(className);
|
||||
} catch (Exception e) {
|
||||
throw new NacosRuntimeException(SERVER_ERROR, "this class name not found");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the class or interface represented by this object is either the same as, or is a superclass or
|
||||
* superinterface of, the class or interface represented by the specified parameter.
|
||||
*
|
||||
* @param clazz Instances of the class represent classes and interfaces.
|
||||
* @param cls Instances of the class represent classes and interfaces.
|
||||
* @return the value indicating whether objects of the type can be assigned to objects of this class.
|
||||
*/
|
||||
public static boolean isAssignableFrom(Class clazz, Class cls) {
|
||||
Objects.requireNonNull(cls, "cls");
|
||||
return clazz.isAssignableFrom(cls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets and returns the class name.
|
||||
*
|
||||
* @param cls Instances of the class represent classes and interfaces.
|
||||
* @return the name of the class or interface represented by this object.
|
||||
*/
|
||||
public static String getName(Class cls) {
|
||||
Objects.requireNonNull(cls, "cls");
|
||||
return cls.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets and returns className.
|
||||
*
|
||||
* @param obj Object instance.
|
||||
* @return className.
|
||||
*/
|
||||
public static String getName(Object obj) {
|
||||
Objects.requireNonNull(obj, "obj");
|
||||
return obj.getClass().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets and returns the canonical name of the underlying class.
|
||||
*
|
||||
* @param cls Instances of the class represent classes and interfaces.
|
||||
* @return The canonical name of the underlying class.
|
||||
*/
|
||||
public static String getCanonicalName(Class cls) {
|
||||
Objects.requireNonNull(cls, "cls");
|
||||
return cls.getCanonicalName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets and returns the canonical name of the underlying class.
|
||||
*
|
||||
* @param obj Object instance.
|
||||
* @return The canonical name of the underlying class.
|
||||
*/
|
||||
public static String getCanonicalName(Object obj) {
|
||||
Objects.requireNonNull(obj, "obj");
|
||||
return obj.getClass().getCanonicalName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets and returns the simple name of the underlying class.
|
||||
*
|
||||
* @param cls Instances of the class represent classes and interfaces.
|
||||
* @return the simple name of the underlying class.
|
||||
*/
|
||||
public static String getSimplaName(Class cls) {
|
||||
Objects.requireNonNull(cls, "cls");
|
||||
return cls.getSimpleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets and returns the simple name of the underlying class as given in the source code.
|
||||
*
|
||||
* @param obj Object instance.
|
||||
* @return the simple name of the underlying class.
|
||||
*/
|
||||
public static String getSimplaName(Object obj) {
|
||||
Objects.requireNonNull(obj, "obj");
|
||||
return obj.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
}
|
@ -16,6 +16,9 @@
|
||||
|
||||
package com.alibaba.nacos.common.utils;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.common.NotThreadSafe;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Dictionary;
|
||||
import java.util.Map;
|
||||
@ -124,4 +127,32 @@ public class MapUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ComputeIfAbsent lazy load.
|
||||
*
|
||||
* @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.
|
||||
* @return
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public static Object computeIfAbsent(Map target, Object key, BiFunction mappingFunction, Object param1,
|
||||
Object param2) throws NacosException {
|
||||
|
||||
Objects.requireNonNull(key, "key");
|
||||
Objects.requireNonNull(key, "mappingFunction");
|
||||
Objects.requireNonNull(key, "param1");
|
||||
Objects.requireNonNull(key, "param2");
|
||||
|
||||
Object val = target.get(key);
|
||||
if (val == null) {
|
||||
Object ret = mappingFunction.apply(param1, param2);
|
||||
target.put(key, ret);
|
||||
return ret;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -48,14 +48,14 @@ Volunteer wanted.
|
||||
#### checkstyle
|
||||
[chechstyle-idea-install](https://plugins.jetbrains.com/plugin/1065-checkstyle-idea)
|
||||
|
||||
1. Preferences/Settings --> Other Settings --> Checkstyle
|
||||
1. `Preferences/Settings --> Other Settings --> Checkstyle` OR `Preferences/Settings --> Tools --> Checkstyle`
|
||||
2. Set checkstyle version at least 8.30 and scan scope `All resource(including tests)` in checkstyle plugin.
|
||||
3. Import `style/NacosCheckStyle.xml` to checkstyle plugin.
|
||||
4. Scan and check your modified code by plugin.
|
||||
|
||||
[chechstyle插件idea安装](https://plugins.jetbrains.com/plugin/1065-checkstyle-idea)
|
||||
|
||||
1. Preferences/Settings --> Other Settings --> Checkstyle
|
||||
1. `Preferences/Settings --> Other Settings --> Checkstyle` 或者 `Preferences/Settings --> Tools --> Checkstyle`
|
||||
2. 在checkstyle插件中设置checkstyle版本至少为8.30,并将扫描作用域设置为`All resource(including tests)`
|
||||
3. 导入源代码下`style/NacosCheckStyle.xml`文件到checkstyle插件。
|
||||
4. 用checkstyle插件扫描你修改的代码。
|
||||
|
@ -88,14 +88,14 @@ public class NacosAsyncRestTemplate_ITCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_url_post_from() throws Exception{
|
||||
public void test_url_post_form() throws Exception{
|
||||
String url = IP + CONFIG_INSTANCE_PATH + "/instance";
|
||||
Map<String, String> param = new HashMap<>();
|
||||
param.put("serviceName", "app-test");
|
||||
param.put("port", "8080");
|
||||
param.put("ip", "11.11.11.11");
|
||||
CallbackMap<String> callbackMap = new CallbackMap<>();
|
||||
nacosRestTemplate.postFrom(url, Header.newInstance(), Query.newInstance(), param, String.class, callbackMap);
|
||||
nacosRestTemplate.postForm(url, Header.newInstance(), Query.newInstance(), param, String.class, callbackMap);
|
||||
Thread.sleep(2000);
|
||||
HttpRestResult<String> restResult = callbackMap.getRestResult();
|
||||
System.out.println(restResult.getData());
|
||||
@ -104,14 +104,14 @@ public class NacosAsyncRestTemplate_ITCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_url_put_from() throws Exception{
|
||||
public void test_url_put_form() throws Exception{
|
||||
String url = IP + CONFIG_INSTANCE_PATH + "/instance";
|
||||
Map<String, String> param = new HashMap<>();
|
||||
param.put("serviceName", "app-test-change");
|
||||
param.put("port", "8080");
|
||||
param.put("ip", "11.11.11.11");
|
||||
CallbackMap<String> callbackMap = new CallbackMap<>();
|
||||
nacosRestTemplate.putFrom(url, Header.newInstance(), Query.newInstance(), param, String.class, callbackMap);
|
||||
nacosRestTemplate.postForm(url, Header.newInstance(), Query.newInstance(), param, String.class, callbackMap);
|
||||
Thread.sleep(2000);
|
||||
HttpRestResult<String> restResult = callbackMap.getRestResult();
|
||||
System.out.println(restResult.getData());
|
||||
|
@ -69,7 +69,7 @@ public class NacosRestTemplate_ITCase {
|
||||
param.put("dataId", "test-1");
|
||||
param.put("group", "DEFAULT_GROUP");
|
||||
param.put("content", "aaa=b");
|
||||
HttpRestResult<String> restResult = nacosRestTemplate.postFrom(url, Header.newInstance(), Query.EMPTY, param, String.class);
|
||||
HttpRestResult<String> restResult = nacosRestTemplate.postForm(url, Header.newInstance(), Query.EMPTY, param, String.class);
|
||||
Assert.assertTrue(restResult.ok());
|
||||
System.out.println(restResult.getData());
|
||||
System.out.println(restResult.getHeader());
|
||||
@ -87,13 +87,13 @@ public class NacosRestTemplate_ITCase {
|
||||
|
||||
|
||||
@Test
|
||||
public void test_url_post_from() throws Exception{
|
||||
public void test_url_post_form() throws Exception{
|
||||
String url = IP + INSTANCE_PATH + "/instance";
|
||||
Map<String, String> param = new HashMap<>();
|
||||
param.put("serviceName", "app-test");
|
||||
param.put("port", "8080");
|
||||
param.put("ip", "11.11.11.11");
|
||||
HttpRestResult<String> restResult = nacosRestTemplate.postFrom(url, Header.newInstance(), Query.newInstance(), param, String.class);
|
||||
HttpRestResult<String> restResult = nacosRestTemplate.postForm(url, Header.newInstance(), Query.newInstance(), param, String.class);
|
||||
Assert.assertTrue(restResult.ok());
|
||||
System.out.println(restResult.getData());
|
||||
}
|
||||
@ -105,7 +105,7 @@ public class NacosRestTemplate_ITCase {
|
||||
param.put("serviceName", "app-test-change");
|
||||
param.put("port", "8080");
|
||||
param.put("ip", "11.11.11.11");
|
||||
HttpRestResult<String> restResult = nacosRestTemplate.putFrom(url, Header.newInstance(), Query.newInstance(), param, String.class);
|
||||
HttpRestResult<String> restResult = nacosRestTemplate.putForm(url, Header.newInstance(), Query.newInstance(), param, String.class);
|
||||
Assert.assertTrue(restResult.ok());
|
||||
System.out.println(restResult.getData());
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ public class AutoDeregisterInstance_ITCase {
|
||||
}
|
||||
|
||||
@After
|
||||
public void destroy() {
|
||||
public void destroy() throws Exception{
|
||||
NamingBase.destoryServer(port);
|
||||
}
|
||||
|
||||
|
@ -16,10 +16,13 @@
|
||||
package com.alibaba.nacos.test.naming;
|
||||
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
import com.alibaba.nacos.client.naming.net.HttpClient;
|
||||
import com.alibaba.nacos.client.naming.net.NamingHttpClientManager;
|
||||
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
|
||||
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.test.base.HttpClient4Test;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.junit.Assert;
|
||||
|
||||
@ -30,6 +33,7 @@ import java.util.*;
|
||||
*/
|
||||
public class NamingBase extends HttpClient4Test {
|
||||
|
||||
private static final NacosRestTemplate nacosRestTemplate = NamingHttpClientManager.getNacosRestTemplate();
|
||||
|
||||
public static final String TEST_DOM_1 = "nacos.test.1";
|
||||
public static final String TEST_IP_4_DOM_1 = "127.0.0.1";
|
||||
@ -166,39 +170,32 @@ public class NamingBase extends HttpClient4Test {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void prepareServer(int localPort) {
|
||||
public static void prepareServer(int localPort) throws Exception{
|
||||
prepareServer(localPort, "UP");
|
||||
}
|
||||
|
||||
public static void prepareServer(int localPort, String status) {
|
||||
public static void prepareServer(int localPort, String status) throws Exception {
|
||||
String url = "http://127.0.0.1:" + localPort + "/nacos/v1/ns/operator/switches?entry=overriddenServerStatus&value=" + status;
|
||||
List<String> headers = new ArrayList<String>();
|
||||
headers.add(HttpHeaderConsts.USER_AGENT_HEADER);
|
||||
headers.add("Nacos-Server");
|
||||
HttpClient.HttpResult result =
|
||||
HttpClient.request(url, headers, new HashMap<String, String>(), StringUtils.EMPTY, "UTF-8", "PUT");
|
||||
Header header = Header.newInstance();
|
||||
header.addParam(HttpHeaderConsts.USER_AGENT_HEADER, "Nacos-Server");
|
||||
HttpRestResult<String> result = nacosRestTemplate.putForm(url, header, Query.EMPTY, new HashMap<>(), String.class);
|
||||
System.out.println(result);
|
||||
Assert.assertEquals(HttpStatus.SC_OK, result.code);
|
||||
|
||||
Assert.assertEquals(HttpStatus.SC_OK, result.getCode());
|
||||
|
||||
url = "http://127.0.0.1:" + localPort + "/nacos/v1/ns/operator/switches?entry=autoChangeHealthCheckEnabled&value=" + false;
|
||||
headers = new ArrayList<String>();
|
||||
headers.add(HttpHeaderConsts.USER_AGENT_HEADER);
|
||||
headers.add("Nacos-Server");
|
||||
result =
|
||||
HttpClient.request(url, headers, new HashMap<String, String>(), StringUtils.EMPTY, "UTF-8", "PUT");
|
||||
|
||||
result = nacosRestTemplate.putForm(url, header, Query.EMPTY, new HashMap<>(), String.class);
|
||||
System.out.println(result);
|
||||
Assert.assertEquals(HttpStatus.SC_OK, result.code);
|
||||
Assert.assertEquals(HttpStatus.SC_OK, result.getCode());
|
||||
}
|
||||
|
||||
public static void destoryServer(int localPort) {
|
||||
public static void destoryServer(int localPort) throws Exception{
|
||||
String url = "http://127.0.0.1:" + localPort + "/nacos/v1/ns/operator/switches?entry=autoChangeHealthCheckEnabled&value=" + true;
|
||||
List<String> headers = new ArrayList<String>();
|
||||
headers.add(HttpHeaderConsts.USER_AGENT_HEADER);
|
||||
headers.add("Nacos-Server");
|
||||
HttpClient.HttpResult result =
|
||||
HttpClient.request(url, headers, new HashMap<String, String>(), StringUtils.EMPTY, "UTF-8", "PUT");
|
||||
Header header = Header.newInstance();
|
||||
header.addParam(HttpHeaderConsts.USER_AGENT_HEADER, "Nacos-Server");
|
||||
|
||||
HttpRestResult<String> result = nacosRestTemplate.putForm(url, header, Query.EMPTY, new HashMap<>(), String.class);
|
||||
System.out.println(result);
|
||||
Assert.assertEquals(HttpStatus.SC_OK, result.code);
|
||||
Assert.assertEquals(HttpStatus.SC_OK, result.getCode());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user