[ISSUE #2842] Replace Fastjson with Jackson for naming instance and health checker.
This commit is contained in:
yanlinly 2020-05-25 21:44:02 +08:00 committed by GitHub
commit cae9c6d2f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 1192 additions and 636 deletions

View File

@ -21,7 +21,7 @@ import com.alibaba.nacos.address.constant.AddressServerConstants;
import com.alibaba.nacos.address.misc.Loggers; import com.alibaba.nacos.address.misc.Loggers;
import com.alibaba.nacos.address.util.AddressServerParamCheckUtil; import com.alibaba.nacos.address.util.AddressServerParamCheckUtil;
import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker; import com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;
import com.alibaba.nacos.naming.core.Cluster; import com.alibaba.nacos.naming.core.Cluster;
import com.alibaba.nacos.naming.core.Instance; import com.alibaba.nacos.naming.core.Instance;
import com.alibaba.nacos.naming.core.Service; import com.alibaba.nacos.naming.core.Service;

View File

@ -48,6 +48,14 @@
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId> <artifactId>fastjson</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>

View File

@ -1,291 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.api.naming.pojo;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.serializer.SerializeWriter;
import com.alibaba.nacos.api.common.Constants;
import org.apache.commons.lang3.StringUtils;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import com.google.common.base.Objects;
/**
* @author nkorange
*/
public abstract class AbstractHealthChecker implements Cloneable {
protected String type = "unknown";
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
/**
* Clone all fields of this instance to another one
*
* @return Another instance with exactly the same fields.
* @throws CloneNotSupportedException
*/
@Override
public abstract AbstractHealthChecker clone() throws CloneNotSupportedException;
/**
* used to JsonAdapter
*/
public void jsonAdapterCallback(SerializeWriter writer) {
// do nothing
}
public static class None extends AbstractHealthChecker {
public static final String TYPE = "NONE";
public None() {
this.setType(TYPE);
}
@Override
public AbstractHealthChecker clone() throws CloneNotSupportedException {
return new None();
}
}
public static class Http extends AbstractHealthChecker {
public static final String TYPE = "HTTP";
private String path = "";
private String headers = "";
private int expectedResponseCode = 200;
public Http() {
this.type = TYPE;
}
public int getExpectedResponseCode() {
return expectedResponseCode;
}
public void setExpectedResponseCode(int expectedResponseCode) {
this.expectedResponseCode = expectedResponseCode;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getHeaders() {
return headers;
}
public void setHeaders(String headers) {
this.headers = headers;
}
@JSONField(serialize = false)
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(":");
if (splits.length != 2) {
continue;
}
headerMap.put(StringUtils.trim(splits[0]), StringUtils.trim(splits[1]));
}
return headerMap;
}
/**
* used to JsonAdapter
*
* @param writer
*/
@Override
public void jsonAdapterCallback(SerializeWriter writer) {
writer.writeFieldValue(',', "path", getPath());
writer.writeFieldValue(',', "headers", getHeaders());
}
@Override
public int hashCode() {
return Objects.hashCode(path, headers, expectedResponseCode);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Http)) {
return false;
}
Http other = (Http) obj;
if (!strEquals(type, other.getType())) {
return false;
}
if (!strEquals(path, other.getPath())) {
return false;
}
if (!strEquals(headers, other.getHeaders())) {
return false;
}
return expectedResponseCode == other.getExpectedResponseCode();
}
@Override
public Http clone() throws CloneNotSupportedException {
Http config = new Http();
config.setPath(this.getPath());
config.setHeaders(this.getHeaders());
config.setType(this.getType());
config.setExpectedResponseCode(this.getExpectedResponseCode());
return config;
}
}
public static class Tcp extends AbstractHealthChecker {
public static final String TYPE = "TCP";
public Tcp() {
this.type = TYPE;
}
@Override
public int hashCode() {
return Objects.hashCode(TYPE);
}
@Override
public boolean equals(Object obj) {
return obj instanceof Tcp;
}
@Override
public Tcp clone() throws CloneNotSupportedException {
Tcp config = new Tcp();
config.setType(this.type);
return config;
}
}
public static class Mysql extends AbstractHealthChecker {
public static final String TYPE = "MYSQL";
private String user;
private String pwd;
private String cmd;
public Mysql() {
this.type = TYPE;
}
public String getCmd() {
return cmd;
}
public String getPwd() {
return pwd;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public void setCmd(String cmd) {
this.cmd = cmd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
/**
* used to JsonAdapter
*
* @param writer
*/
@Override
public void jsonAdapterCallback(SerializeWriter writer) {
writer.writeFieldValue(',', "user", getUser());
writer.writeFieldValue(',', "pwd", getPwd());
writer.writeFieldValue(',', "cmd", getCmd());
}
@Override
public int hashCode() {
return Objects.hashCode(user, pwd, cmd);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Mysql)) {
return false;
}
Mysql other = (Mysql) obj;
if (!strEquals(user, other.getUser())) {
return false;
}
if (!strEquals(pwd, other.getPwd())) {
return false;
}
return strEquals(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());
config.setType(this.getType());
return config;
}
}
private static boolean strEquals(String str1, String str2) {
return str1 == null ? str2 == null : str1.equals(str2);
}
}

View File

@ -18,6 +18,9 @@ package com.alibaba.nacos.api.naming.pojo;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;
import com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Tcp;
/** /**
* Cluster * Cluster
* *
@ -38,7 +41,7 @@ public class Cluster {
/** /**
* Health check config of this cluster * Health check config of this cluster
*/ */
private AbstractHealthChecker healthChecker = new AbstractHealthChecker.Tcp(); private AbstractHealthChecker healthChecker = new Tcp();
/** /**
* Default registered port for instances in this cluster. * Default registered port for instances in this cluster.

View File

@ -15,9 +15,14 @@
*/ */
package com.alibaba.nacos.api.naming.pojo; package com.alibaba.nacos.api.naming.pojo;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.naming.PreservedMetadataKeys; import com.alibaba.nacos.api.naming.PreservedMetadataKeys;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.HashMap; import java.util.HashMap;
@ -30,6 +35,7 @@ import static com.alibaba.nacos.api.common.Constants.NUMBER_PATTERN;
* *
* @author nkorange * @author nkorange
*/ */
@JsonInclude(Include.NON_NULL)
public class Instance { public class Instance {
/** /**
@ -173,7 +179,13 @@ public class Instance {
@Override @Override
public String toString() { public String toString() {
return JSON.toJSONString(this); ObjectMapper objectMapper = new ObjectMapper();
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
try {
return objectMapper.writeValueAsString(this);
} catch (JsonProcessingException e) {
throw new RuntimeException("Instance toJson failed", e);
}
} }
public String toInetAddr() { public String toInetAddr() {

View File

@ -0,0 +1,75 @@
/*
* 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.naming.pojo.healthcheck;
import com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker.None;
import com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Http;
import com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Mysql;
import com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Tcp;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
/**
* @author nkorange
*/
@JsonTypeInfo(use = Id.NAME, property = "type", defaultImpl = None.class)
@JsonSubTypes({
@JsonSubTypes.Type(name = Http.TYPE, value = Http.class),
@JsonSubTypes.Type(name = Mysql.TYPE, value = Mysql.class),
@JsonSubTypes.Type(name = Tcp.TYPE, value = Tcp.class)
})
public abstract class AbstractHealthChecker implements Cloneable {
@JsonIgnore
protected final String type;
protected AbstractHealthChecker(String type) {
this.type = type;
}
public String getType() {
return type;
}
/**
* Clone all fields of this instance to another one.
*
* @return Another instance with exactly the same fields
* @throws CloneNotSupportedException clone not supported exception
*/
@Override
public abstract AbstractHealthChecker clone() throws CloneNotSupportedException;
/**
* Default implementation of Health checker.
*/
public static class None extends AbstractHealthChecker {
public static final String TYPE = "NONE";
public None() {
super(TYPE);
}
@Override
public AbstractHealthChecker clone() throws CloneNotSupportedException {
return new None();
}
}
}

View File

@ -13,9 +13,11 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.alibaba.nacos.naming.healthcheck; package com.alibaba.nacos.api.naming.pojo.healthcheck;
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker; import com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Http;
import com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Mysql;
import com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Tcp;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -29,37 +31,36 @@ public enum HealthCheckType {
/** /**
* TCP type * TCP type
*/ */
TCP("tcp", AbstractHealthChecker.Tcp.class), TCP(Tcp.class),
/** /**
* HTTP type * HTTP type
*/ */
HTTP("http", AbstractHealthChecker.Http.class), HTTP(Http.class),
/** /**
* MySQL type * MySQL type
*/ */
MYSQL("mysql", AbstractHealthChecker.Mysql.class), MYSQL(Mysql.class),
/** /**
* No check * No check
*/ */
NONE("none", AbstractHealthChecker.None.class); NONE(AbstractHealthChecker.None.class);
private String name; private final Class<? extends AbstractHealthChecker> healthCheckerClass;
private Class healthCheckerClass; private static final Map<String, Class<? extends AbstractHealthChecker>> EXTEND = new ConcurrentHashMap<String, Class<? extends AbstractHealthChecker>>();
private static Map<String, Class> EXTEND = HealthCheckType(Class<? extends AbstractHealthChecker> healthCheckerClass) {
new ConcurrentHashMap<>();
HealthCheckType(String name, Class healthCheckerClass) {
this.name = name;
this.healthCheckerClass = healthCheckerClass; this.healthCheckerClass = healthCheckerClass;
} }
public static void registerHealthChecker(String type, Class healthCheckerClass){ public static void registerHealthChecker(String type, Class<? extends AbstractHealthChecker> healthCheckerClass){
EXTEND.putIfAbsent(type, healthCheckerClass); if (!EXTEND.containsKey(type)) {
EXTEND.put(type, healthCheckerClass);
HealthCheckerFactory.registerSubType(healthCheckerClass, type);
}
} }
public static Class ofHealthCheckerClass(String type){ public static Class<? extends AbstractHealthChecker> ofHealthCheckerClass(String type){
HealthCheckType enumType; HealthCheckType enumType;
try { try {
enumType = valueOf(type); enumType = valueOf(type);
@ -69,12 +70,12 @@ public enum HealthCheckType {
return enumType.healthCheckerClass; return enumType.healthCheckerClass;
} }
public static List<Class> getLoadedHealthCheckerClasses(){ public static List<Class<? extends AbstractHealthChecker>> getLoadedHealthCheckerClasses(){
List<Class> all = new ArrayList<>(); List<Class<? extends AbstractHealthChecker>> all = new ArrayList<Class<? extends AbstractHealthChecker>>();
for(HealthCheckType type : values()){ for(HealthCheckType type : values()){
all.add(type.healthCheckerClass); all.add(type.healthCheckerClass);
} }
for(Map.Entry<String, Class> entry : EXTEND.entrySet()){ for(Map.Entry<String, Class<? extends AbstractHealthChecker>> entry : EXTEND.entrySet()){
all.add(entry.getValue()); all.add(entry.getValue());
} }
return all; return all;

View File

@ -0,0 +1,97 @@
/*
* 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.naming.pojo.healthcheck;
import java.io.IOException;
import com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker.None;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.NamedType;
/**
* health checker factory.
*
* @author yangyi
*/
public class HealthCheckerFactory {
private static final ObjectMapper MAPPER = new ObjectMapper();
static {
MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
}
/**
* Register new sub type of health checker to factory for serialize and deserialize.
*
* @param extendHealthChecker extend health checker
*/
public static void registerSubType(AbstractHealthChecker extendHealthChecker) {
registerSubType(extendHealthChecker.getClass(), extendHealthChecker.getType());
}
/**
* Register new sub type of health checker to factory for serialize and deserialize.
*
* @param extendHealthCheckerClass extend health checker
* @param typeName typeName of health checker
*/
public static void registerSubType(Class<? extends AbstractHealthChecker> extendHealthCheckerClass, String typeName) {
MAPPER.registerSubtypes(new NamedType(extendHealthCheckerClass, typeName));
}
/**
* Create default {@link None} health checker.
*
* @return new none health checker
*/
public static None createNoneHealthChecker() {
return new None();
}
/**
* Deserialize and create a instance of health checker.
*
* @param jsonString json string of health checker
* @return new instance
*/
public static AbstractHealthChecker deserialize(String jsonString) {
try {
return MAPPER.readValue(jsonString, AbstractHealthChecker.class);
} catch (IOException e) {
// TODO replace with NacosDeserializeException.
throw new RuntimeException("Deserialize health checker from json failed", e);
}
}
/**
* Serialize a instance of health checker to json
*
* @param healthChecker health checker instance
* @return son string after serializing
*/
public static String serialize(AbstractHealthChecker healthChecker) {
try {
return MAPPER.writeValueAsString(healthChecker);
} catch (JsonProcessingException e) {
// TODO replace with NacosSerializeException.
throw new RuntimeException("Serialize health checker to json failed", e);
}
}
}

View File

@ -0,0 +1,121 @@
/*
* 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.naming.pojo.healthcheck.impl;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;
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;
import java.util.Map;
/**
* Implementation of health checker for HTTP.
*
* @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);
}
public int getExpectedResponseCode() {
return expectedResponseCode;
}
public void setExpectedResponseCode(int expectedResponseCode) {
this.expectedResponseCode = expectedResponseCode;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getHeaders() {
return headers;
}
public void setHeaders(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(":");
if (splits.length != 2) {
continue;
}
headerMap.put(StringUtils.trim(splits[0]), StringUtils.trim(splits[1]));
}
return headerMap;
}
@Override
public int hashCode() {
return Objects.hashCode(path, headers, expectedResponseCode);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Http)) {
return false;
}
Http other = (Http) obj;
if (!StringUtils.equals(type, other.getType())) {
return false;
}
if (!StringUtils.equals(path, other.getPath())) {
return false;
}
if (!StringUtils.equals(headers, other.getHeaders())) {
return false;
}
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());
return config;
}
}

View File

@ -0,0 +1,98 @@
/*
* 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.naming.pojo.healthcheck.impl;
import org.apache.commons.lang3.StringUtils;
import com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;
import com.google.common.base.Objects;
/**
* Implementation of health checker for MYSQL.
*
* @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);
}
public String getCmd() {
return cmd;
}
public String getPwd() {
return pwd;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public void setCmd(String cmd) {
this.cmd = cmd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public int hashCode() {
return Objects.hashCode(user, pwd, cmd);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Mysql)) {
return false;
}
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());
return config;
}
}

View File

@ -0,0 +1,49 @@
/*
* 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.naming.pojo.healthcheck.impl;
import com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;
import com.google.common.base.Objects;
/**
* Implementation of health checker for TCP.
*
* @author yangyi
*/
public class Tcp extends AbstractHealthChecker {
public static final String TYPE = "TCP";
public Tcp() {
super(TYPE);
}
@Override
public int hashCode() {
return Objects.hashCode(TYPE);
}
@Override
public boolean equals(Object obj) {
return obj instanceof Tcp;
}
@Override
public Tcp clone() throws CloneNotSupportedException {
return new Tcp();
}
}

View File

@ -15,6 +15,8 @@
*/ */
package com.alibaba.nacos.api.selector; package com.alibaba.nacos.api.selector;
import com.fasterxml.jackson.annotation.JsonIgnore;
/** /**
* Abstract selector that only contains a type * Abstract selector that only contains a type
* *
@ -26,13 +28,14 @@ public abstract class AbstractSelector {
/** /**
* The type of this selector, each child class should announce its own unique type. * The type of this selector, each child class should announce its own unique type.
*/ */
private String type; @JsonIgnore
private final String type;
protected AbstractSelector(String type) {
this.type = type;
}
public String getType() { public String getType() {
return type; return type;
} }
protected void setType(String type) {
this.type = type;
}
} }

View File

@ -29,7 +29,7 @@ public class ExpressionSelector extends AbstractSelector {
private String expression; private String expression;
public ExpressionSelector() { public ExpressionSelector() {
this.setType(SelectorType.label.name()); super(SelectorType.label.name());
} }
public String getExpression() { public String getExpression() {

View File

@ -23,6 +23,6 @@ package com.alibaba.nacos.api.selector;
public class NoneSelector extends AbstractSelector { public class NoneSelector extends AbstractSelector {
public NoneSelector() { public NoneSelector() {
this.setType(SelectorType.none.name()); super(SelectorType.none.name());
} }
} }

View File

@ -0,0 +1,57 @@
/*
* 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.naming.pojo.healthcheck;
import org.junit.Before;
import org.junit.Test;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.NamedType;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
public class AbstractHealthCheckerTest {
private ObjectMapper objectMapper = new ObjectMapper();
@Before
public void setUp() {
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
objectMapper.registerSubtypes(new NamedType(TestChecker.class, TestChecker.TYPE));
}
@Test
public void testSerialize() throws JsonProcessingException {
TestChecker testChecker = new TestChecker();
testChecker.setTestValue("");
String actual = objectMapper.writeValueAsString(testChecker);
assertTrue(actual.contains("\"testValue\":\"\""));
assertTrue(actual.contains("\"type\":\"TEST\""));
}
@Test
public void testDeserialize() throws IOException {
String testChecker = "{\"type\":\"TEST\",\"testValue\":\"\"}";
TestChecker actual = objectMapper.readValue(testChecker, TestChecker.class);
assertEquals("", actual.getTestValue());
assertEquals(TestChecker.TYPE, actual.getType());
}
}

View File

@ -0,0 +1,55 @@
/*
* 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.naming.pojo.healthcheck;
import static org.junit.Assert.*;
import org.junit.Test;
import com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Tcp;
public class HealthCheckerFactoryTest {
@Test
public void testSerialize() {
Tcp tcp = new Tcp();
String actual = HealthCheckerFactory.serialize(tcp);
assertTrue(actual.contains("\"type\":\"TCP\""));
}
@Test
public void testSerializeExtend() {
HealthCheckerFactory.registerSubType(TestChecker.class, TestChecker.TYPE);
TestChecker testChecker = new TestChecker();
String actual = HealthCheckerFactory.serialize(testChecker);
assertTrue(actual.contains("\"type\":\"TEST\""));
}
@Test
public void testDeserialize() {
String tcpString = "{\"type\":\"TCP\"}";
AbstractHealthChecker actual = HealthCheckerFactory.deserialize(tcpString);
assertEquals(Tcp.class, actual.getClass());
}
@Test
public void testDeserializeExtend() {
String tcpString = "{\"type\":\"TEST\",\"testValue\":null}";
AbstractHealthChecker actual = HealthCheckerFactory.deserialize(tcpString);
assertEquals(TestChecker.class, actual.getClass());
}
}

View File

@ -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.api.naming.pojo.healthcheck;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
public class TestChecker extends AbstractHealthChecker {
@JsonTypeInfo(use = Id.NAME, property = "type")
public static final String TYPE = "TEST";
private String testValue;
public String getTestValue() {
return testValue;
}
public void setTestValue(String testValue) {
this.testValue = testValue;
}
public TestChecker() {
super(TYPE);
}
@Override
public AbstractHealthChecker clone() throws CloneNotSupportedException {
return null;
}
}

View File

@ -0,0 +1,80 @@
/*
* 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.naming.pojo.healthcheck.impl;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.Map;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class HttpTest {
private ObjectMapper objectMapper;
private Http http;
@Before
public void setUp() {
objectMapper = new ObjectMapper();
http = new Http();
}
@Test
public void testGetExpectedResponseCodeWithEmpty() {
http.setHeaders("");
assertTrue(http.getCustomHeaders().isEmpty());
}
@Test
public void testGetExpectedResponseCodeWithoutEmpty() {
http.setHeaders("x:a|y:");
Map<String, String> actual = http.getCustomHeaders();
assertFalse(actual.isEmpty());
assertEquals(1, actual.size());
assertEquals("a", actual.get("x"));
}
@Test
public void testSerialize() throws JsonProcessingException {
http.setHeaders("x:a|y:");
http.setPath("/x");
String actual = objectMapper.writeValueAsString(http);
assertTrue(actual.contains("\"path\":\"/x\""));
assertTrue(actual.contains("\"type\":\"HTTP\""));
assertTrue(actual.contains("\"headers\":\"x:a|y:\""));
assertTrue(actual.contains("\"expectedResponseCode\":200"));
}
@Test
public void testDeserialize() throws IOException {
String testChecker = "{\"type\":\"HTTP\",\"path\":\"/x\",\"headers\":\"x:a|y:\",\"expectedResponseCode\":200}";
Http actual = objectMapper.readValue(testChecker, Http.class);
assertEquals("x:a|y:", actual.getHeaders());
assertEquals("/x", actual.getPath());
assertEquals(200, actual.getExpectedResponseCode());
assertEquals("x:a|y:", actual.getHeaders());
assertEquals(Http.TYPE, actual.getType());
}
}

View File

@ -0,0 +1,62 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.api.naming.pojo.healthcheck.impl;
import static org.junit.Assert.*;
import java.io.IOException;
import org.junit.Before;
import org.junit.Test;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class MysqlTest {
private ObjectMapper objectMapper;
private Mysql mysql;
@Before
public void setUp() throws Exception {
mysql = new Mysql();
mysql.setUser("user");
mysql.setPwd("pwd");
mysql.setCmd("cmd");
objectMapper = new ObjectMapper();
}
@Test
public void testSerialize() throws JsonProcessingException {
String actual = objectMapper.writeValueAsString(mysql);
assertTrue(actual.contains("\"user\":\"user\""));
assertTrue(actual.contains("\"type\":\"MYSQL\""));
assertTrue(actual.contains("\"pwd\":\"pwd\""));
assertTrue(actual.contains("\"cmd\":\"cmd\""));
}
@Test
public void testDeserialize() throws IOException {
String testChecker = "{\"type\":\"MYSQL\",\"user\":\"user\",\"pwd\":\"pwd\",\"cmd\":\"cmd\"}";
Mysql actual = objectMapper.readValue(testChecker, Mysql.class);
assertEquals("cmd", actual.getCmd());
assertEquals("pwd", actual.getPwd());
assertEquals("user", actual.getUser());
assertEquals(Mysql.TYPE, actual.getType());
}
}

View File

@ -18,6 +18,7 @@ package com.alibaba.nacos.common.utils;
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.NamedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
@ -55,4 +56,8 @@ public final class JacksonUtils {
public static <T> T toObj(String json, Type type) throws Exception { public static <T> T toObj(String json, Type type) throws Exception {
return mapper.readValue(json, mapper.constructType(type)); return mapper.readValue(json, mapper.constructType(type));
} }
public static void registerSubtype(Class<?> clz, String type) {
mapper.registerSubtypes(new NamedType(clz, type));
}
} }

View File

@ -15,19 +15,17 @@
*/ */
package com.alibaba.nacos.naming.controllers; package com.alibaba.nacos.naming.controllers;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.CommonParams; import com.alibaba.nacos.api.naming.CommonParams;
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker; import com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;
import com.alibaba.nacos.api.naming.pojo.healthcheck.HealthCheckerFactory;
import com.alibaba.nacos.core.auth.ActionTypes; import com.alibaba.nacos.core.auth.ActionTypes;
import com.alibaba.nacos.core.auth.Secured; import com.alibaba.nacos.core.auth.Secured;
import com.alibaba.nacos.core.utils.WebUtils; import com.alibaba.nacos.core.utils.WebUtils;
import com.alibaba.nacos.naming.core.Cluster; import com.alibaba.nacos.naming.core.Cluster;
import com.alibaba.nacos.naming.core.Service; import com.alibaba.nacos.naming.core.Service;
import com.alibaba.nacos.naming.core.ServiceManager; import com.alibaba.nacos.naming.core.ServiceManager;
import com.alibaba.nacos.naming.healthcheck.HealthCheckType;
import com.alibaba.nacos.naming.misc.Loggers; import com.alibaba.nacos.naming.misc.Loggers;
import com.alibaba.nacos.naming.misc.UtilsAndCommons; import com.alibaba.nacos.naming.misc.UtilsAndCommons;
import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.BooleanUtils;
@ -77,14 +75,7 @@ public class ClusterController {
cluster.setDefCkport(NumberUtils.toInt(checkPort)); cluster.setDefCkport(NumberUtils.toInt(checkPort));
cluster.setUseIPPort4Check(BooleanUtils.toBoolean(useInstancePort4Check)); cluster.setUseIPPort4Check(BooleanUtils.toBoolean(useInstancePort4Check));
JSONObject healthCheckObj = JSON.parseObject(healthChecker); AbstractHealthChecker abstractHealthChecker = HealthCheckerFactory.deserialize(healthChecker);
AbstractHealthChecker abstractHealthChecker;
String type = healthCheckObj.getString("type");
Class<AbstractHealthChecker> healthCheckClass = HealthCheckType.ofHealthCheckerClass(type);
if(healthCheckClass == null){
throw new NacosException(NacosException.INVALID_PARAM, "unknown health check type:" + healthChecker);
}
abstractHealthChecker = JSON.parseObject(healthChecker, healthCheckClass);
cluster.setHealthChecker(abstractHealthChecker); cluster.setHealthChecker(abstractHealthChecker);
cluster.setMetadata(UtilsAndCommons.parseMetadata(metadata)); cluster.setMetadata(UtilsAndCommons.parseMetadata(metadata));

View File

@ -18,7 +18,7 @@ package com.alibaba.nacos.naming.controllers;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.naming.CommonParams; import com.alibaba.nacos.api.naming.CommonParams;
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker; import com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;
import com.alibaba.nacos.core.auth.ActionTypes; import com.alibaba.nacos.core.auth.ActionTypes;
import com.alibaba.nacos.core.auth.Secured; import com.alibaba.nacos.core.auth.Secured;
import com.alibaba.nacos.core.utils.ApplicationUtils; import com.alibaba.nacos.core.utils.ApplicationUtils;
@ -26,7 +26,7 @@ import com.alibaba.nacos.core.utils.WebUtils;
import com.alibaba.nacos.naming.core.Instance; import com.alibaba.nacos.naming.core.Instance;
import com.alibaba.nacos.naming.core.Service; import com.alibaba.nacos.naming.core.Service;
import com.alibaba.nacos.naming.core.ServiceManager; import com.alibaba.nacos.naming.core.ServiceManager;
import com.alibaba.nacos.naming.healthcheck.HealthCheckType; import com.alibaba.nacos.api.naming.pojo.healthcheck.HealthCheckType;
import com.alibaba.nacos.naming.misc.Loggers; import com.alibaba.nacos.naming.misc.Loggers;
import com.alibaba.nacos.naming.misc.UtilsAndCommons; import com.alibaba.nacos.naming.misc.UtilsAndCommons;
import com.alibaba.nacos.naming.push.PushService; import com.alibaba.nacos.naming.push.PushService;
@ -121,11 +121,11 @@ public class HealthController {
@GetMapping("checkers") @GetMapping("checkers")
public ResponseEntity checkers() { public ResponseEntity checkers() {
List<Class> classes = HealthCheckType.getLoadedHealthCheckerClasses(); List<Class<? extends AbstractHealthChecker>> classes = HealthCheckType.getLoadedHealthCheckerClasses();
Map<String, AbstractHealthChecker> checkerMap = new HashMap<>(8); Map<String, AbstractHealthChecker> checkerMap = new HashMap<>(8);
for (Class clazz : classes) { for (Class<? extends AbstractHealthChecker> clazz : classes) {
try { try {
AbstractHealthChecker checker = (AbstractHealthChecker) clazz.newInstance(); AbstractHealthChecker checker = clazz.newInstance();
checkerMap.put(checker.getType(), checker); checkerMap.put(checker.getType(), checker);
} catch (InstantiationException | IllegalAccessException e) { } catch (InstantiationException | IllegalAccessException e) {
Loggers.EVT_LOG.error("checkers error ", e); Loggers.EVT_LOG.error("checkers error ", e);

View File

@ -15,11 +15,12 @@
*/ */
package com.alibaba.nacos.naming.core; package com.alibaba.nacos.naming.core;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.nacos.naming.healthcheck.HealthCheckReactor; import com.alibaba.nacos.naming.healthcheck.HealthCheckReactor;
import com.alibaba.nacos.naming.healthcheck.HealthCheckStatus; import com.alibaba.nacos.naming.healthcheck.HealthCheckStatus;
import com.alibaba.nacos.naming.healthcheck.HealthCheckTask; import com.alibaba.nacos.naming.healthcheck.HealthCheckTask;
import com.alibaba.nacos.naming.misc.Loggers; import com.alibaba.nacos.naming.misc.Loggers;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -43,19 +44,19 @@ public class Cluster extends com.alibaba.nacos.api.naming.pojo.Cluster implement
private int defIPPort = -1; private int defIPPort = -1;
@JSONField(serialize = false) @JsonIgnore
private HealthCheckTask checkTask; private HealthCheckTask checkTask;
@JSONField(serialize = false) @JsonIgnore
private Set<Instance> persistentInstances = new HashSet<>(); private Set<Instance> persistentInstances = new HashSet<>();
@JSONField(serialize = false) @JsonIgnore
private Set<Instance> ephemeralInstances = new HashSet<>(); private Set<Instance> ephemeralInstances = new HashSet<>();
@JSONField(serialize = false) @JsonIgnore
private Service service; private Service service;
@JSONField(serialize = false) @JsonIgnore
private volatile boolean inited = false; private volatile boolean inited = false;
private Map<String, String> metadata = new ConcurrentHashMap<>(); private Map<String, String> metadata = new ConcurrentHashMap<>();

View File

@ -15,13 +15,16 @@
*/ */
package com.alibaba.nacos.naming.core; package com.alibaba.nacos.naming.core;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.naming.healthcheck.HealthCheckStatus; import com.alibaba.nacos.naming.healthcheck.HealthCheckStatus;
import com.alibaba.nacos.naming.misc.Loggers; import com.alibaba.nacos.naming.misc.Loggers;
import com.alibaba.nacos.naming.misc.UtilsAndCommons; import com.alibaba.nacos.naming.misc.UtilsAndCommons;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import org.apache.commons.lang3.math.NumberUtils; import org.apache.commons.lang3.math.NumberUtils;
import java.util.Set; import java.util.Set;
@ -34,6 +37,7 @@ import java.util.regex.Pattern;
* *
* @author nkorange * @author nkorange
*/ */
@JsonInclude(Include.NON_NULL)
public class Instance extends com.alibaba.nacos.api.naming.pojo.Instance implements Comparable { public class Instance extends com.alibaba.nacos.api.naming.pojo.Instance implements Comparable {
private static final double MAX_WEIGHT_VALUE = 10000.0D; private static final double MAX_WEIGHT_VALUE = 10000.0D;
@ -42,7 +46,7 @@ public class Instance extends com.alibaba.nacos.api.naming.pojo.Instance impleme
private volatile long lastBeat = System.currentTimeMillis(); private volatile long lastBeat = System.currentTimeMillis();
@JSONField(serialize = false) @JsonIgnore
private volatile boolean mockValid = false; private volatile boolean mockValid = false;
private volatile boolean marked = false; private volatile boolean marked = false;
@ -173,7 +177,11 @@ public class Instance extends com.alibaba.nacos.api.naming.pojo.Instance impleme
} }
public String toJSON() { public String toJSON() {
return JSON.toJSONString(this); try {
return JacksonUtils.toJson(this);
} catch (Exception e) {
throw new RuntimeException("Instance toJSON failed", e);
}
} }
@ -181,7 +189,7 @@ public class Instance extends com.alibaba.nacos.api.naming.pojo.Instance impleme
Instance ip; Instance ip;
try { try {
ip = JSON.parseObject(json, Instance.class); ip = JacksonUtils.toObj(json, Instance.class);
} catch (Exception e) { } catch (Exception e) {
ip = fromString(json); ip = fromString(json);
} }
@ -224,7 +232,7 @@ public class Instance extends com.alibaba.nacos.api.naming.pojo.Instance impleme
&& this.isEphemeral() == other.isEphemeral(); && this.isEphemeral() == other.isEphemeral();
} }
@JSONField(serialize = false) @JsonIgnore
public String getDatumKey() { public String getDatumKey() {
if (getPort() > 0) { if (getPort() > 0) {
return getIp() + ":" + getPort() + ":" + UtilsAndCommons.LOCALHOST_SITE + ":" + getClusterName(); return getIp() + ":" + getPort() + ":" + UtilsAndCommons.LOCALHOST_SITE + ":" + getClusterName();
@ -233,7 +241,7 @@ public class Instance extends com.alibaba.nacos.api.naming.pojo.Instance impleme
} }
} }
@JSONField(serialize = false) @JsonIgnore
public String getDefaultKey() { public String getDefaultKey() {
if (getPort() > 0) { if (getPort() > 0) {
return getIp() + ":" + getPort() + ":" + UtilsAndCommons.UNKNOWN_SITE; return getIp() + ":" + getPort() + ":" + UtilsAndCommons.UNKNOWN_SITE;
@ -255,22 +263,22 @@ public class Instance extends com.alibaba.nacos.api.naming.pojo.Instance impleme
return HealthCheckStatus.get(this).isBeingChecked.compareAndSet(false, true); return HealthCheckStatus.get(this).isBeingChecked.compareAndSet(false, true);
} }
@JSONField(serialize = false) @JsonIgnore
public long getCheckRT() { public long getCheckRT() {
return HealthCheckStatus.get(this).checkRT; return HealthCheckStatus.get(this).checkRT;
} }
@JSONField(serialize = false) @JsonIgnore
public AtomicInteger getOKCount() { public AtomicInteger getOKCount() {
return HealthCheckStatus.get(this).checkOKCount; return HealthCheckStatus.get(this).checkOKCount;
} }
@JSONField(serialize = false) @JsonIgnore
public AtomicInteger getFailCount() { public AtomicInteger getFailCount() {
return HealthCheckStatus.get(this).checkFailCount; return HealthCheckStatus.get(this).checkFailCount;
} }
@JSONField(serialize = false) @JsonIgnore
public void setCheckRT(long checkRT) { public void setCheckRT(long checkRT) {
HealthCheckStatus.get(this).checkRT = checkRT; HealthCheckStatus.get(this).checkRT = checkRT;
} }

View File

@ -15,11 +15,12 @@
*/ */
package com.alibaba.nacos.naming.core; package com.alibaba.nacos.naming.core;
import com.alibaba.fastjson.JSON; import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.nacos.common.utils.MD5Utils; import com.alibaba.nacos.common.utils.MD5Utils;
import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.naming.pojo.Record; import com.alibaba.nacos.naming.pojo.Record;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList; import java.util.ArrayList;
@ -47,11 +48,15 @@ public class Instances implements Record {
@Override @Override
public String toString() { public String toString() {
return JSON.toJSONString(this); try {
return JacksonUtils.toJson(this);
} catch (Exception e) {
throw new RuntimeException("Instances toJSON failed", e);
}
} }
@Override @Override
@JSONField(serialize = false) @JsonIgnore
public String getChecksum() { public String getChecksum() {
return recalculateChecksum(); return recalculateChecksum();

View File

@ -15,8 +15,7 @@
*/ */
package com.alibaba.nacos.naming.core; package com.alibaba.nacos.naming.core;
import com.alibaba.fastjson.JSON; import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.nacos.core.utils.ApplicationUtils; import com.alibaba.nacos.core.utils.ApplicationUtils;
import com.alibaba.nacos.common.utils.MD5Utils; import com.alibaba.nacos.common.utils.MD5Utils;
import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.common.Constants;
@ -32,6 +31,10 @@ import com.alibaba.nacos.naming.pojo.Record;
import com.alibaba.nacos.naming.push.PushService; import com.alibaba.nacos.naming.push.PushService;
import com.alibaba.nacos.naming.selector.NoneSelector; import com.alibaba.nacos.naming.selector.NoneSelector;
import com.alibaba.nacos.naming.selector.Selector; import com.alibaba.nacos.naming.selector.Selector;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.ListUtils; import org.apache.commons.collections.ListUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -48,11 +51,12 @@ import java.util.*;
* *
* @author nkorange * @author nkorange
*/ */
@JsonInclude(Include.NON_NULL)
public class Service extends com.alibaba.nacos.api.naming.pojo.Service implements Record, RecordListener<Instances> { public class Service extends com.alibaba.nacos.api.naming.pojo.Service implements Record, RecordListener<Instances> {
private static final String SERVICE_NAME_SYNTAX = "[0-9a-zA-Z@\\.:_-]+"; private static final String SERVICE_NAME_SYNTAX = "[0-9a-zA-Z@\\.:_-]+";
@JSONField(serialize = false) @JsonIgnore
private ClientBeatCheckTask clientBeatCheckTask = new ClientBeatCheckTask(this); private ClientBeatCheckTask clientBeatCheckTask = new ClientBeatCheckTask(this);
/** /**
@ -90,7 +94,7 @@ public class Service extends com.alibaba.nacos.api.naming.pojo.Service implement
super(name); super(name);
} }
@JSONField(serialize = false) @JsonIgnore
public PushService getPushService() { public PushService getPushService() {
return ApplicationUtils.getBean(PushService.class); return ApplicationUtils.getBean(PushService.class);
} }
@ -322,10 +326,14 @@ public class Service extends com.alibaba.nacos.api.naming.pojo.Service implement
} }
public String toJSON() { public String toJSON() {
return JSON.toJSONString(this); try {
return JacksonUtils.toJson(this);
} catch (Exception e) {
throw new RuntimeException("Service toJson failed", e);
}
} }
@JSONField(serialize = false) @JsonIgnore
public String getServiceString() { public String getServiceString() {
Map<Object, Object> serviceObject = new HashMap<Object, Object>(10); Map<Object, Object> serviceObject = new HashMap<Object, Object>(10);
Service service = this; Service service = this;
@ -369,7 +377,11 @@ public class Service extends com.alibaba.nacos.api.naming.pojo.Service implement
serviceObject.put("clusters", clustersList); serviceObject.put("clusters", clustersList);
return JSON.toJSONString(serviceObject); try {
return JacksonUtils.toJson(serviceObject);
} catch (Exception e) {
throw new RuntimeException("Service toJson failed", e);
}
} }
public String getToken() { public String getToken() {

View File

@ -15,7 +15,7 @@
*/ */
package com.alibaba.nacos.naming.healthcheck; package com.alibaba.nacos.naming.healthcheck;
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker; import com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Http;
import com.alibaba.nacos.naming.core.Cluster; import com.alibaba.nacos.naming.core.Cluster;
import com.alibaba.nacos.naming.core.Instance; import com.alibaba.nacos.naming.core.Instance;
import com.alibaba.nacos.naming.misc.SwitchDomain; import com.alibaba.nacos.naming.misc.SwitchDomain;
@ -115,7 +115,7 @@ public class HttpHealthCheckProcessor implements HealthCheckProcessor {
continue; continue;
} }
AbstractHealthChecker.Http healthChecker = (AbstractHealthChecker.Http) cluster.getHealthChecker(); Http healthChecker = (Http) cluster.getHealthChecker();
int ckPort = cluster.isUseIPPort4Check() ? ip.getPort() : cluster.getDefCkport(); int ckPort = cluster.isUseIPPort4Check() ? ip.getPort() : cluster.getDefCkport();
URL host = new URL("http://" + ip.getIp() + ":" + ckPort); URL host = new URL("http://" + ip.getIp() + ":" + ckPort);

View File

@ -1,78 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.naming.healthcheck;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.alibaba.fastjson.serializer.SerializeWriter;
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker;
import java.io.IOException;
import java.lang.reflect.Type;
/**
* @author nkorange
*/
public class JsonAdapter implements ObjectDeserializer, ObjectSerializer {
private static JsonAdapter INSTANCE = new JsonAdapter();
private JsonAdapter() {
}
public static JsonAdapter getInstance() {
return INSTANCE;
}
@SuppressWarnings("unchecked")
@Override
public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
JSONObject jsonObj = (JSONObject) parser.parse();
String checkType = jsonObj.getString("type");
Class target = HealthCheckType.ofHealthCheckerClass(checkType);
if(target != null){
return (T) JSON.parseObject(jsonObj.toJSONString(), target);
}
return null;
}
@Override
public int getFastMatchToken() {
return 0;
}
@Override
public void write(JSONSerializer jsonSerializer, Object o, Object o1, Type type, int i) throws IOException {
SerializeWriter writer = jsonSerializer.getWriter();
if (o == null) {
writer.writeNull();
return;
}
AbstractHealthChecker config = (AbstractHealthChecker) o;
writer.writeFieldValue(',', "type", config.getType());
config.jsonAdapterCallback(writer);
}
}

View File

@ -15,7 +15,7 @@
*/ */
package com.alibaba.nacos.naming.healthcheck; package com.alibaba.nacos.naming.healthcheck;
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker; import com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Mysql;
import com.alibaba.nacos.naming.core.Cluster; import com.alibaba.nacos.naming.core.Cluster;
import com.alibaba.nacos.naming.core.Instance; import com.alibaba.nacos.naming.core.Instance;
import com.alibaba.nacos.naming.misc.Loggers; import com.alibaba.nacos.naming.misc.Loggers;
@ -146,7 +146,7 @@ public class MysqlHealthCheckProcessor implements HealthCheckProcessor {
Cluster cluster = task.getCluster(); Cluster cluster = task.getCluster();
String key = cluster.getService().getName() + ":" + cluster.getName() + ":" + ip.getIp() + ":" + ip.getPort(); String key = cluster.getService().getName() + ":" + cluster.getName() + ":" + ip.getIp() + ":" + ip.getPort();
Connection connection = CONNECTION_POOL.get(key); Connection connection = CONNECTION_POOL.get(key);
AbstractHealthChecker.Mysql config = (AbstractHealthChecker.Mysql) cluster.getHealthChecker(); Mysql config = (Mysql) cluster.getHealthChecker();
if (connection == null || connection.isClosed()) { if (connection == null || connection.isClosed()) {
MysqlDataSource dataSource = new MysqlDataSource(); MysqlDataSource dataSource = new MysqlDataSource();

View File

@ -15,9 +15,9 @@
*/ */
package com.alibaba.nacos.naming.healthcheck.extend; package com.alibaba.nacos.naming.healthcheck.extend;
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker; import com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;
import com.alibaba.nacos.naming.healthcheck.HealthCheckProcessor; import com.alibaba.nacos.naming.healthcheck.HealthCheckProcessor;
import com.alibaba.nacos.naming.healthcheck.HealthCheckType; import com.alibaba.nacos.api.naming.pojo.healthcheck.HealthCheckType;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@ -17,16 +17,10 @@ package com.alibaba.nacos.naming.misc;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference; import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature; import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker;
import com.alibaba.nacos.common.utils.VersionUtils; import com.alibaba.nacos.common.utils.VersionUtils;
import com.alibaba.nacos.core.utils.ApplicationUtils; import com.alibaba.nacos.core.utils.ApplicationUtils;
import com.alibaba.nacos.naming.healthcheck.JsonAdapter;
import com.alibaba.nacos.naming.selector.Selector;
import com.alibaba.nacos.naming.selector.SelectorJsonAdapter;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.io.File; import java.io.File;
@ -130,17 +124,6 @@ public class UtilsAndCommons {
static { static {
// custom serializer and deserializer for fast-json
SerializeConfig.getGlobalInstance()
.put(AbstractHealthChecker.class, JsonAdapter.getInstance());
ParserConfig.getGlobalInstance()
.putDeserializer(AbstractHealthChecker.class, JsonAdapter.getInstance());
SerializeConfig.getGlobalInstance()
.put(Selector.class, SelectorJsonAdapter.getInstance());
ParserConfig.getGlobalInstance()
.putDeserializer(Selector.class, SelectorJsonAdapter.getInstance());
// write null values, otherwise will cause compatibility issues // write null values, otherwise will cause compatibility issues
JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.WriteNullStringAsEmpty.getMask(); JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.WriteNullStringAsEmpty.getMask();
JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.WriteNullListAsEmpty.getMask(); JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.WriteNullListAsEmpty.getMask();

View File

@ -21,8 +21,12 @@ import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.selector.ExpressionSelector; import com.alibaba.nacos.api.selector.ExpressionSelector;
import com.alibaba.nacos.api.selector.SelectorType; import com.alibaba.nacos.api.selector.SelectorType;
import com.alibaba.nacos.cmdb.service.CmdbReader; import com.alibaba.nacos.cmdb.service.CmdbReader;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.core.utils.ApplicationUtils; import com.alibaba.nacos.core.utils.ApplicationUtils;
import com.alibaba.nacos.naming.core.Instance; import com.alibaba.nacos.naming.core.Instance;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList; import java.util.ArrayList;
@ -55,6 +59,7 @@ import java.util.Set;
* @see CmdbReader * @see CmdbReader
* @since 0.7.0 * @since 0.7.0
*/ */
@JsonTypeInfo(use = Id.NAME, property = "type")
public class LabelSelector extends ExpressionSelector implements Selector { public class LabelSelector extends ExpressionSelector implements Selector {
/** /**
@ -79,6 +84,7 @@ public class LabelSelector extends ExpressionSelector implements Selector {
static { static {
SUPPORTED_INNER_CONNCETORS.add(String.valueOf(CEQUAL)); SUPPORTED_INNER_CONNCETORS.add(String.valueOf(CEQUAL));
SUPPORTED_OUTER_CONNCETORS.add(String.valueOf(CAND)); SUPPORTED_OUTER_CONNCETORS.add(String.valueOf(CAND));
JacksonUtils.registerSubtype(LabelSelector.class, SelectorType.label.name());
} }
public Set<String> getLabels() { public Set<String> getLabels() {
@ -90,7 +96,7 @@ public class LabelSelector extends ExpressionSelector implements Selector {
} }
public LabelSelector() { public LabelSelector() {
setType(SelectorType.label.name()); super();
} }
private CmdbReader getCmdbReader() { private CmdbReader getCmdbReader() {

View File

@ -15,7 +15,11 @@
*/ */
package com.alibaba.nacos.naming.selector; package com.alibaba.nacos.naming.selector;
import com.alibaba.nacos.api.selector.SelectorType;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.naming.core.Instance; import com.alibaba.nacos.naming.core.Instance;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import java.util.List; import java.util.List;
@ -25,8 +29,13 @@ import java.util.List;
* @author nkorange * @author nkorange
* @since 0.7.0 * @since 0.7.0
*/ */
@JsonTypeInfo(use = Id.NAME, property = "type")
public class NoneSelector extends com.alibaba.nacos.api.selector.NoneSelector implements Selector { public class NoneSelector extends com.alibaba.nacos.api.selector.NoneSelector implements Selector {
static {
JacksonUtils.registerSubtype(NoneSelector.class, SelectorType.none.name());
}
@Override @Override
public List<Instance> select(String consumer, List<Instance> providers) { public List<Instance> select(String consumer, List<Instance> providers) {
return providers; return providers;

View File

@ -15,7 +15,10 @@
*/ */
package com.alibaba.nacos.naming.selector; package com.alibaba.nacos.naming.selector;
import com.alibaba.nacos.api.selector.NoneSelector;
import com.alibaba.nacos.naming.core.Instance; import com.alibaba.nacos.naming.core.Instance;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import java.util.List; import java.util.List;
@ -30,12 +33,15 @@ import java.util.List;
* <p> * <p>
* Every extended selector should also register its type to class SelectorType so Nacos * Every extended selector should also register its type to class SelectorType so Nacos
* recognizes it and can correctly create this type of selector. * recognizes it and can correctly create this type of selector.
* <p>
* Sub class should register their type to JacksonUtil.
* *
* @author nkorange * @author nkorange
* @see com.alibaba.nacos.api.selector.SelectorType * @see com.alibaba.nacos.api.selector.SelectorType
* @see SelectorJsonAdapter * @see com.alibaba.nacos.common.utils.JacksonUtils
* @since 0.7.0 * @since 0.7.0
*/ */
@JsonTypeInfo(use = Id.NAME, property = "type", defaultImpl = NoneSelector.class)
public interface Selector { public interface Selector {
/** /**

View File

@ -1,96 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.naming.selector;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.alibaba.fastjson.serializer.SerializeWriter;
import com.alibaba.nacos.api.selector.SelectorType;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.lang.reflect.Type;
/**
* Json adapter for class Selector.
* <p>
* When deserializing object for class Selector, we should consider to convert the selector to
* its runtime child class object. And this adapter helps us to finish it.
*
* @author nkorange
* @since 0.7.0
*/
public class SelectorJsonAdapter implements ObjectDeserializer, ObjectSerializer {
private static SelectorJsonAdapter INSTANCE = new SelectorJsonAdapter();
private SelectorJsonAdapter() {
}
public static SelectorJsonAdapter getInstance() {
return INSTANCE;
}
@Override
public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
JSONObject jsonObj = (JSONObject) parser.parse();
if (jsonObj == null) {
return null;
}
String checkType = jsonObj.getString("type");
if (StringUtils.equals(checkType, SelectorType.label.name())) {
return (T) JSON.parseObject(jsonObj.toJSONString(), LabelSelector.class);
}
if (StringUtils.equals(checkType, SelectorType.none.name())) {
return (T) JSON.parseObject(jsonObj.toJSONString(), NoneSelector.class);
}
return null;
}
@Override
public int getFastMatchToken() {
return 0;
}
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
SerializeWriter writer = serializer.getWriter();
if (object == null) {
writer.writeNull();
return;
}
Selector selector = (Selector) object;
writer.writeFieldValue(',', "type", selector.getType());
if (StringUtils.equals(selector.getType(), SelectorType.label.name())) {
LabelSelector labelSelector = (LabelSelector) selector;
writer.writeFieldValue(',', "labels", JSON.toJSONString(labelSelector.getLabels()));
}
}
}

View File

@ -15,6 +15,7 @@
*/ */
package com.alibaba.nacos.naming; package com.alibaba.nacos.naming;
import com.alibaba.nacos.core.utils.ApplicationUtils;
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftCore; import com.alibaba.nacos.naming.consistency.persistent.raft.RaftCore;
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftPeer; import com.alibaba.nacos.naming.consistency.persistent.raft.RaftPeer;
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftPeerSet; import com.alibaba.nacos.naming.consistency.persistent.raft.RaftPeerSet;
@ -27,19 +28,30 @@ import com.alibaba.nacos.naming.push.PushService;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy; import org.mockito.Spy;
import org.springframework.context.ApplicationContext; import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.mock.env.MockEnvironment;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
/** /**
* @author nkorange * @author nkorange
*/ */
@RunWith(MockitoJUnitRunner.class)
public class BaseTest { public class BaseTest {
protected static final String TEST_CLUSTER_NAME = "test-cluster";
protected static final String TEST_SERVICE_NAME = "test-service";
protected static final String TEST_GROUP_NAME = "test-group-name";
protected static final String TEST_NAMESPACE = "test-namespace";
@Mock @Mock
public ServiceManager serviceManager; public ServiceManager serviceManager;
@ -52,36 +64,52 @@ public class BaseTest {
@Rule @Rule
public ExpectedException expectedException = ExpectedException.none(); public ExpectedException expectedException = ExpectedException.none();
@Spy
protected ConfigurableApplicationContext context;
@Mock
protected DistroMapper distroMapper;
@Spy
protected SwitchDomain switchDomain;
@Mock
protected HealthCheckProcessorDelegate delegate;
@Mock
protected PushService pushService;
@Spy
private MockEnvironment environment;
@Before @Before
public void before() { public void before() {
MockitoAnnotations.initMocks(this); ApplicationUtils.injectEnvironment(environment);
ApplicationUtils.injectContext(context);
}
protected void mockRaft() {
RaftPeer peer = new RaftPeer(); RaftPeer peer = new RaftPeer();
peer.ip = NetUtils.localServer(); peer.ip = NetUtils.localServer();
raftCore.setPeerSet(peerSet); raftCore.setPeerSet(peerSet);
Mockito.when(peerSet.local()).thenReturn(peer); Mockito.when(peerSet.local()).thenReturn(peer);
Mockito.when(peerSet.getLeader()).thenReturn(peer); Mockito.when(peerSet.getLeader()).thenReturn(peer);
Mockito.when(peerSet.isLeader(NetUtils.localServer())).thenReturn(true); Mockito.when(peerSet.isLeader(NetUtils.localServer())).thenReturn(true);
}
doReturn(distroMapper).when(context).getBean(DistroMapper.class); protected void mockInjectPushServer() {
doReturn(switchDomain).when(context).getBean(SwitchDomain.class);
doReturn(delegate).when(context).getBean(HealthCheckProcessorDelegate.class);
doReturn(pushService).when(context).getBean(PushService.class); doReturn(pushService).when(context).getBean(PushService.class);
} }
protected static final String TEST_CLUSTER_NAME = "test-cluster"; protected void mockInjectHealthCheckProcessor() {
protected static final String TEST_SERVICE_NAME = "test-service"; doReturn(delegate).when(context).getBean(HealthCheckProcessorDelegate.class);
protected static final String TEST_GROUP_NAME = "test-group-name"; }
protected static final String TEST_NAMESPACE = "test-namespace";
@Spy protected void mockInjectSwitchDomain() {
protected ApplicationContext context; doReturn(switchDomain).when(context).getBean(SwitchDomain.class);
@Mock }
protected DistroMapper distroMapper;
@Spy protected void mockInjectDistroMapper() {
protected SwitchDomain switchDomain; doReturn(distroMapper).when(context).getBean(DistroMapper.class);
@Mock }
protected HealthCheckProcessorDelegate delegate;
@Mock
protected PushService pushService;
} }

View File

@ -15,14 +15,21 @@
*/ */
package com.alibaba.nacos.naming.core; package com.alibaba.nacos.naming.core;
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker; import com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Http;
import org.junit.Assert; import com.alibaba.nacos.common.utils.JacksonUtils;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/** /**
* @author nkorange * @author nkorange
*/ */
@ -50,7 +57,7 @@ public class ClusterTest {
Cluster newCluster = new Cluster("nacos-cluster-1", service); Cluster newCluster = new Cluster("nacos-cluster-1", service);
newCluster.setDefCkport(8888); newCluster.setDefCkport(8888);
newCluster.setDefIPPort(9999); newCluster.setDefIPPort(9999);
AbstractHealthChecker.Http healthCheckConfig = new AbstractHealthChecker.Http(); Http healthCheckConfig = new Http();
healthCheckConfig.setPath("/nacos-path-1"); healthCheckConfig.setPath("/nacos-path-1");
healthCheckConfig.setExpectedResponseCode(500); healthCheckConfig.setExpectedResponseCode(500);
healthCheckConfig.setHeaders("Client-Version:nacos-test-1"); healthCheckConfig.setHeaders("Client-Version:nacos-test-1");
@ -58,13 +65,13 @@ public class ClusterTest {
cluster.update(newCluster); cluster.update(newCluster);
Assert.assertEquals(8888, cluster.getDefCkport()); assertEquals(8888, cluster.getDefCkport());
Assert.assertEquals(9999, cluster.getDefIPPort()); assertEquals(9999, cluster.getDefIPPort());
Assert.assertTrue(cluster.getHealthChecker() instanceof AbstractHealthChecker.Http); assertTrue(cluster.getHealthChecker() instanceof Http);
AbstractHealthChecker.Http httpHealthCheck = (AbstractHealthChecker.Http) (cluster.getHealthChecker()); Http httpHealthCheck = (Http) (cluster.getHealthChecker());
Assert.assertEquals("/nacos-path-1", httpHealthCheck.getPath()); assertEquals("/nacos-path-1", httpHealthCheck.getPath());
Assert.assertEquals(500, httpHealthCheck.getExpectedResponseCode()); assertEquals(500, httpHealthCheck.getExpectedResponseCode());
Assert.assertEquals("Client-Version:nacos-test-1", httpHealthCheck.getHeaders()); assertEquals("Client-Version:nacos-test-1", httpHealthCheck.getHeaders());
} }
@Test @Test
@ -85,12 +92,12 @@ public class ClusterTest {
cluster.updateIPs(list, false); cluster.updateIPs(list, false);
List<Instance> ips = cluster.allIPs(); List<Instance> ips = cluster.allIPs();
Assert.assertNotNull(ips); assertNotNull(ips);
Assert.assertEquals(2, ips.size()); assertEquals(2, ips.size());
Assert.assertEquals("1.1.1.1", ips.get(0).getIp()); assertEquals("1.1.1.1", ips.get(0).getIp());
Assert.assertEquals(1234, ips.get(0).getPort()); assertEquals(1234, ips.get(0).getPort());
Assert.assertEquals("1.1.1.1", ips.get(1).getIp()); assertEquals("1.1.1.1", ips.get(1).getIp());
Assert.assertEquals(2345, ips.get(1).getPort()); assertEquals(2345, ips.get(1).getPort());
} }
@Test @Test
@ -113,4 +120,39 @@ public class ClusterTest {
cluster.validate(); cluster.validate();
} }
@Test
public void testSerialize() throws Exception {
String actual = JacksonUtils.toJson(cluster);
System.out.println(actual);
assertTrue(actual.contains("\"defaultPort\":80"));
assertTrue(actual.contains("\"defIPPort\":8080"));
assertTrue(actual.contains("\"healthChecker\":{\"type\":\"TCP\"}"));
assertTrue(actual.contains("\"metadata\":{}"));
assertTrue(actual.contains("\"defCkport\":80"));
assertTrue(actual.contains("\"name\":\"nacos-cluster-1\""));
assertTrue(actual.contains("\"defaultCheckPort\":80"));
assertTrue(actual.contains("\"serviceName\":\"nacos.service.1\""));
assertTrue(actual.contains("\"useIPPort4Check\":true"));
assertTrue(actual.contains("\"sitegroup\":\"\""));
assertTrue(actual.contains("\"empty\":true"));
assertFalse(actual.contains("\"service\""));
}
@Test
public void testDeserialize() throws Exception {
String example = "{\"defCkport\":80,\"defIPPort\":8080,\"defaultCheckPort\":80,\"defaultPort\":80,\"empty\":true,\"healthChecker\":{\"type\":\"TCP\"},\"metadata\":{},\"name\":\"nacos-cluster-1\",\"serviceName\":\"nacos.service.1\",\"sitegroup\":\"\",\"useIPPort4Check\":true}";
Cluster actual = JacksonUtils.toObj(example, Cluster.class);
assertEquals(80, actual.getDefCkport());
assertEquals(8080, actual.getDefIPPort());
assertEquals(80, actual.getDefaultCheckPort());
assertEquals(80, actual.getDefaultPort());
assertTrue(actual.isEmpty());
assertTrue(actual.getMetadata().isEmpty());
assertTrue(actual.isUseIPPort4Check());
assertEquals("nacos-cluster-1", actual.getName());
assertEquals("nacos.service.1", actual.getServiceName());
assertEquals("", actual.getSitegroup());
assertNull(actual.getHealthCheckTask());
}
} }

View File

@ -15,41 +15,31 @@
*/ */
package com.alibaba.nacos.naming.core; package com.alibaba.nacos.naming.core;
import com.alibaba.nacos.naming.BaseTest;
import com.alibaba.nacos.naming.misc.UtilsAndCommons; import com.alibaba.nacos.naming.misc.UtilsAndCommons;
import com.alibaba.nacos.naming.push.PushService;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.springframework.context.ApplicationContext;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static org.mockito.Mockito.doReturn;
/** /**
* @author nkorange * @author nkorange
*/ */
public class DomainTest { public class DomainTest extends BaseTest {
private Service service; private Service service;
@Spy
protected ApplicationContext context;
@Mock
protected PushService pushService;
@Before @Before
public void before() { public void before() {
MockitoAnnotations.initMocks(this); super.before();
service = new Service(); service = new Service();
service.setName("nacos.service.1"); service.setName("nacos.service.1");
Cluster cluster = new Cluster(UtilsAndCommons.DEFAULT_CLUSTER_NAME, service); Cluster cluster = new Cluster(UtilsAndCommons.DEFAULT_CLUSTER_NAME, service);
service.addCluster(cluster); service.addCluster(cluster);
doReturn(pushService).when(context).getBean(PushService.class); mockInjectPushServer();
} }
@Test @Test

View File

@ -15,14 +15,18 @@
*/ */
package com.alibaba.nacos.naming.core; package com.alibaba.nacos.naming.core;
import com.alibaba.fastjson.JSON; import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.naming.healthcheck.RsInfo; import com.alibaba.nacos.naming.healthcheck.RsInfo;
import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.HashMap;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/** /**
* @author nkorange * @author nkorange
@ -42,31 +46,90 @@ public class InstanceTest {
instance.setPort(1234); instance.setPort(1234);
instance.setWeight(5); instance.setWeight(5);
Assert.assertEquals("1.1.1.1", instance.getIp()); assertEquals("1.1.1.1", instance.getIp());
Assert.assertEquals(1234, instance.getPort()); assertEquals(1234, instance.getPort());
Assert.assertEquals(5, instance.getWeight(), 0.001); assertEquals(5, instance.getWeight(), 0.001);
} }
@Test @Test
public void fromJson() { public void testToJsonWithAllParam() {
instance = new Instance("1.1.1.1", 1234, "TEST", "TENANT", "APP");
String actual = instance.toJSON();
assertTrue(actual.contains("\"app\":\"APP\""));
assertTrue(actual.contains("\"clusterName\":\"TEST\""));
assertTrue(actual.contains("\"enabled\":true"));
assertTrue(actual.contains("\"ephemeral\":true"));
assertTrue(actual.contains("\"healthy\":true"));
assertTrue(actual.contains("\"instanceHeartBeatInterval\":5000"));
assertTrue(actual.contains("\"instanceHeartBeatTimeOut\":15000"));
assertTrue(actual.contains("\"instanceIdGenerator\":\"simple\""));
assertTrue(actual.contains("\"ip\":\"1.1.1.1\""));
assertTrue(actual.contains("\"ipDeleteTimeout\":30000"));
assertTrue(actual.contains("\"lastBeat\":" + instance.getLastBeat()));
assertTrue(actual.contains("\"marked\":false"));
assertTrue(actual.contains("\"metadata\":{}"));
assertTrue(actual.contains("\"port\":1234"));
assertTrue(actual.contains("\"tenant\":\"TENANT\""));
assertTrue(actual.contains("\"weight\":1.0"));
assertFalse(actual.contains("\"mockValid\""));
assertFalse(actual.contains("\"failCount\""));
}
@Test
public void testToJsonWithoutTenantAndApp() {
instance = new Instance("1.1.1.1", 1234, "TEST");
String actual = instance.toJSON();
System.out.println(actual);
assertTrue(actual.contains("\"clusterName\":\"TEST\""));
assertTrue(actual.contains("\"enabled\":true"));
assertTrue(actual.contains("\"ephemeral\":true"));
assertTrue(actual.contains("\"healthy\":true"));
assertTrue(actual.contains("\"instanceHeartBeatInterval\":5000"));
assertTrue(actual.contains("\"instanceHeartBeatTimeOut\":15000"));
assertTrue(actual.contains("\"instanceIdGenerator\":\"simple\""));
assertTrue(actual.contains("\"ip\":\"1.1.1.1\""));
assertTrue(actual.contains("\"ipDeleteTimeout\":30000"));
assertTrue(actual.contains("\"lastBeat\":" + instance.getLastBeat()));
assertTrue(actual.contains("\"marked\":false"));
assertTrue(actual.contains("\"metadata\":{}"));
assertTrue(actual.contains("\"port\":1234"));
assertTrue(actual.contains("\"weight\":1.0"));
assertFalse(actual.contains("\"app\""));
assertFalse(actual.contains("\"tenant\":"));
assertFalse(actual.contains("\"mockValid\""));
assertFalse(actual.contains("\"failCount\""));
}
@Test
public void testFromJsonByJson() {
instance = Instance.fromJSON("{\"clusterName\":\"TEST\",\"enabled\":true,\"ephemeral\":true,\"healthy\":true,\"instanceHeartBeatInterval\":5000,\"instanceHeartBeatTimeOut\":15000,\"instanceIdGenerator\":\"simple\",\"ip\":\"1.1.1.1\",\"ipDeleteTimeout\":30000,\"lastBeat\":1590043805463,\"marked\":false,\"metadata\":{},\"port\":1234,\"weight\":1.0}\n");
assertEquals("1.1.1.1", instance.getIp());
assertEquals(1234, instance.getPort());
assertEquals("TEST", instance.getClusterName());
assertNull(instance.getApp());
assertNull(instance.getTenant());
}
@Test
public void testFromJsonByNoJson() {
instance = Instance.fromJSON("2.2.2.2:8888_2_TEST1"); instance = Instance.fromJSON("2.2.2.2:8888_2_TEST1");
Assert.assertEquals("2.2.2.2", instance.getIp()); assertEquals("2.2.2.2", instance.getIp());
Assert.assertEquals(8888, instance.getPort()); assertEquals(8888, instance.getPort());
Assert.assertEquals(2, instance.getWeight(), 0.001); assertEquals(2, instance.getWeight(), 0.001);
Assert.assertEquals("TEST1", instance.getClusterName()); assertEquals("TEST1", instance.getClusterName());
} }
@Test @Test
public void rsInfo() { public void rsInfo() throws Exception {
RsInfo info = new RsInfo(); RsInfo info = new RsInfo();
Map<String, String> metadata = new HashMap<>(); Map<String, String> metadata = new HashMap<>();
metadata.put("version", "2222"); metadata.put("version", "2222");
info.setMetadata(metadata); info.setMetadata(metadata);
System.out.println(JSON.toJSONString(info)); System.out.println(JacksonUtils.toJson(info));
String json = JSON.toJSONString(info); String json = JacksonUtils.toJson(info);
RsInfo info1 = JSON.parseObject(json, RsInfo.class); RsInfo info1 = JacksonUtils.toObj(json, RsInfo.class);
System.out.println(info1); System.out.println(info1);
} }
} }

View File

@ -16,13 +16,19 @@
package com.alibaba.nacos.naming.core; package com.alibaba.nacos.naming.core;
import org.junit.Test; import org.junit.Test;
import java.math.BigInteger; import java.math.BigInteger;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import static org.junit.Assert.assertEquals;
/** /**
* @author lkxiaolou * @author lkxiaolou
@ -81,6 +87,34 @@ public class InstancesTest {
assert catchException.get(); assert catchException.get();
} }
@Test
public void testToString() {
Instances actual = new Instances();
Collection<Instance> instancesCase = createInstancesCase();
actual.getInstanceList().addAll(instancesCase);
String expected = "{\"instanceList\":[" + StringUtils.join(instancesCase.stream().map(Instance::toJSON).collect(Collectors.toList()), ",") + "]}";
assertEquals(expected, actual.toString());
}
@Test
public void testDeserializeFromJson() throws Exception {
Collection<Instance> expected = createInstancesCase();
String instancesJson = "{\"instanceList\":[" + StringUtils.join(expected.stream().map(Instance::toJSON).collect(Collectors.toList()), ",") + "]}";
Instances actual = JacksonUtils.toObj(instancesJson, Instances.class);
assertEquals(expected, actual.getInstanceList());
}
private Collection<Instance> createInstancesCase() {
Collection<Instance> result = new ArrayList<>();
Instance instanceWithBasicParam = new Instance("1.1.1.1", 1111);
Instance instanceWithCluster = new Instance("1.1.1.1", 1112, "TEST");
Instance instanceWithAllParam = new Instance("1.1.1.1", 1112, "TEST", "TENANT", "APP");
result.add(instanceWithBasicParam);
result.add(instanceWithCluster);
result.add(instanceWithAllParam);
return result;
}
//@Test //@Test
// 跑起来比较久所以注释掉 // 跑起来比较久所以注释掉
public void checkSumThreadSafe() throws Exception { public void checkSumThreadSafe() throws Exception {

View File

@ -49,6 +49,9 @@ public class ServiceManagerTest extends BaseTest {
@Before @Before
public void before() { public void before() {
super.before(); super.before();
mockInjectHealthCheckProcessor();
mockInjectDistroMapper();
mockInjectSwitchDomain();
} }
@Test @Test

View File

@ -15,30 +15,44 @@
*/ */
package com.alibaba.nacos.naming.core; package com.alibaba.nacos.naming.core;
import com.alibaba.nacos.api.selector.SelectorType;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.naming.BaseTest; import com.alibaba.nacos.naming.BaseTest;
import com.alibaba.nacos.naming.selector.NoneSelector;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.Spy;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/** /**
* @author jifengnan 2019-04-28 * @author jifengnan 2019-04-28
*/ */
public class ServiceTest extends BaseTest { public class ServiceTest extends BaseTest {
@Spy
private Service service; private Service service;
@Before @Before
public void before() { public void before() {
super.before(); super.before();
service = new Service("test-service");
mockInjectPushServer();
mockInjectHealthCheckProcessor();
mockInjectDistroMapper();
mockInjectSwitchDomain();
JacksonUtils.registerSubtype(NoneSelector.class, SelectorType.none.name());
} }
@Test @Test
public void testUpdateIPs() { public void testUpdateIPs() {
service.setName("test-service");
List<Instance> instances = new ArrayList<>(); List<Instance> instances = new ArrayList<>();
Instance instance = new Instance("1.1.1.1", 1, "test-instance1"); Instance instance = new Instance("1.1.1.1", 1, "test-instance1");
instances.add(instance); instances.add(instance);
@ -55,4 +69,56 @@ public class ServiceTest extends BaseTest {
instances.remove(null); instances.remove(null);
Assert.assertEquals(instances, service.allIPs(true)); Assert.assertEquals(instances, service.allIPs(true));
} }
@Test
public void testSerialize() throws Exception {
String actual = new Service("test-service").toJSON();
assertTrue(actual.contains("\"checksum\":\"cb129dc536a387e791ee6f63251c816b\""));
assertTrue(actual.contains("\"clusterMap\":{}"));
assertTrue(actual.contains("\"empty\":true"));
assertTrue(actual.contains("\"enabled\":true"));
assertTrue(actual.contains("\"finalizeCount\":0"));
assertTrue(actual.contains("\"ipDeleteTimeout\":30000"));
assertTrue(actual.contains("\"lastModifiedMillis\":0"));
assertTrue(actual.contains("\"metadata\":{}"));
assertTrue(actual.contains("\"name\":\"test-service\""));
assertTrue(actual.contains("\"owners\":[]"));
assertTrue(actual.contains("\"protectThreshold\":0.0"));
assertTrue(actual.contains("\"resetWeight\":false"));
assertTrue(actual.contains("\"selector\":{\"type\":\"none\"}"));
assertFalse(actual.contains("clientBeatCheckTask"));
assertFalse(actual.contains("serviceString"));
assertFalse(actual.contains("pushService"));
}
@Test
public void testDeserialize() throws Exception {
String example = "{\"checksum\":\"cb129dc536a387e791ee6f63251c816b\",\"clusterMap\":{},\"empty\":true,\"enabled\":true,\"finalizeCount\":0,\"ipDeleteTimeout\":30000,\"lastModifiedMillis\":0,\"metadata\":{},\"name\":\"test-service\",\"owners\":[],\"protectThreshold\":0.0,\"resetWeight\":false,\"selector\":{\"type\":\"none\"}}";
Service actual = JacksonUtils.toObj(example, Service.class);
assertEquals("cb129dc536a387e791ee6f63251c816b", actual.getChecksum());
assertEquals("test-service", actual.getName());
assertTrue(actual.getClusterMap().isEmpty());
assertTrue(actual.isEmpty());
assertTrue(actual.getEnabled());
assertTrue(actual.getMetadata().isEmpty());
assertTrue(actual.getOwners().isEmpty());
assertEquals(0, actual.getFinalizeCount());
assertEquals(30000, actual.getIpDeleteTimeout());
assertEquals(0, actual.getLastModifiedMillis());
assertEquals(0, actual.getLastModifiedMillis());
assertEquals(0.0, actual.getProtectThreshold(), 0);
assertFalse(actual.getResetWeight());
assertThat(actual.getSelector(), instanceOf(NoneSelector.class));
}
@Test
public void testGetServiceString() {
String actual = service.getServiceString();
assertTrue(actual.contains("\"invalidIPCount\":0"));
assertTrue(actual.contains("\"name\":\"test-service\""));
assertTrue(actual.contains("\"ipCount\":0"));
assertTrue(actual.contains("\"owners\":[]"));
assertTrue(actual.contains("\"protectThreshold\":0.0"));
assertTrue(actual.contains("\"clusters\":[]"));
}
} }

View File

@ -14,7 +14,9 @@ import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.mock.web.MockServletContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -23,7 +25,8 @@ import java.util.List;
* @author Nicholas * @author Nicholas
*/ */
@SpringBootTest @SpringBootTest
@RunWith(SpringRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MockServletContext.class)
public class SubscribeManagerTest extends BaseTest { public class SubscribeManagerTest extends BaseTest {
@Mock @Mock