Skip to content

Commit

Permalink
Merge pull request #1126 from XCXCXCXCX/ISSUE_#359
Browse files Browse the repository at this point in the history
[#359] provide a way for user to implement their health checkers.
  • Loading branch information
Fury Zhu authored May 12, 2019
2 parents a3da313 + 23454ff commit 1f1b047
Show file tree
Hide file tree
Showing 11 changed files with 246 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
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;

Expand Down Expand Up @@ -45,8 +46,16 @@ public void setType(String type) {
* @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";
Expand Down Expand Up @@ -116,6 +125,17 @@ public Map<String, String> getCustomHeaders() {
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.hash(path, headers, expectedResponseCode);
Expand Down Expand Up @@ -215,6 +235,18 @@ 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.hash(user, pwd, cmd);
Expand Down
1 change: 1 addition & 0 deletions console/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
<version>2.1.1.RELEASE</version>
<configuration>
<mainClass>com.alibaba.nacos.Nacos</mainClass>
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
Expand Down
3 changes: 1 addition & 2 deletions distribution/bin/startup.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,8 @@ if not "%2" == "cluster" (
set "JAVA_OPT=%JAVA_OPT% -XX:-UseLargePages"
)

set "JAVA_OPT=%JAVA_OPT% -Xbootclasspath/a:%BASE_DIR%\plugins\cmdb"
set "JAVA_OPT=%JAVA_OPT% -Dnacos.home=%BASE_DIR%"
set "JAVA_OPT=%JAVA_OPT% -jar %BASE_DIR%\target\nacos-server.jar"
set "JAVA_OPT=%JAVA_OPT% -Dloader.path=%BASE_DIR%/plugins/health -jar %BASE_DIR%\target\nacos-server.jar"
set "JAVA_OPT=%JAVA_OPT% --spring.config.location=%CUSTOM_SEARCH_LOCATIONS%"
set "JAVA_OPT=%JAVA_OPT% --logging.config=%BASE_DIR%/conf/nacos-logback.xml"

Expand Down
2 changes: 1 addition & 1 deletion distribution/bin/startup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ else
fi

JAVA_OPT="${JAVA_OPT} -Dnacos.home=${BASE_DIR}"
JAVA_OPT="${JAVA_OPT} -jar ${BASE_DIR}/target/nacos-server.jar"
JAVA_OPT="${JAVA_OPT} -Dloader.path=${BASE_DIR}/plugins/health -jar ${BASE_DIR}/target/nacos-server.jar"
JAVA_OPT="${JAVA_OPT} ${JAVA_OPT_EXT}"
JAVA_OPT="${JAVA_OPT} --spring.config.location=${CUSTOM_SEARCH_LOCATIONS}"
JAVA_OPT="${JAVA_OPT} --logging.config=${BASE_DIR}/conf/nacos-logback.xml"
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.alibaba.nacos.naming.core.Service;
import com.alibaba.nacos.naming.core.ServiceManager;
import com.alibaba.nacos.naming.exception.NacosException;
import com.alibaba.nacos.naming.healthcheck.HealthCheckType;
import com.alibaba.nacos.naming.misc.Loggers;
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
import org.apache.commons.lang3.BooleanUtils;
Expand Down Expand Up @@ -75,23 +76,12 @@ public String update(HttpServletRequest request) throws Exception {

JSONObject healthCheckObj = JSON.parseObject(healthChecker);
AbstractHealthChecker abstractHealthChecker;

switch (healthCheckObj.getString("type")) {
case AbstractHealthChecker.Tcp.TYPE:
abstractHealthChecker = JSON.parseObject(healthChecker, AbstractHealthChecker.Tcp.class);
break;
case AbstractHealthChecker.Http.TYPE:
abstractHealthChecker = JSON.parseObject(healthChecker, AbstractHealthChecker.Http.class);
break;
case AbstractHealthChecker.Mysql.TYPE:
abstractHealthChecker = JSON.parseObject(healthChecker, AbstractHealthChecker.Mysql.class);
break;
case AbstractHealthChecker.None.TYPE:
abstractHealthChecker = JSON.parseObject(healthChecker, AbstractHealthChecker.None.class);
break;
default:
throw new NacosException(NacosException.INVALID_PARAM, "unknown health check type:" + healthChecker);
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.setMetadata(UtilsAndCommons.parseMetadata(metadata));
Expand All @@ -105,4 +95,5 @@ public String update(HttpServletRequest request) throws Exception {

return "ok";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.naming.CommonParams;
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker;
import com.alibaba.nacos.core.utils.WebUtils;
import com.alibaba.nacos.naming.boot.RunningConfig;
import com.alibaba.nacos.naming.core.DistroMapper;
Expand All @@ -32,11 +33,16 @@
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Health status related operation controller
Expand Down Expand Up @@ -110,4 +116,20 @@ public String update(HttpServletRequest request) throws Exception {

return "ok";
}

@ResponseBody
@RequestMapping(value = "checkers", method = RequestMethod.GET)
public ResponseEntity checkers() {
List<Class> classes = HealthCheckType.getLoadedHealthCheckerClasses();
Map<String, AbstractHealthChecker> checkerMap = new HashMap<>(8);
for (Class clazz : classes) {
try {
AbstractHealthChecker checker = (AbstractHealthChecker) clazz.newInstance();
checkerMap.put(checker.getType(), checker);
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
return ResponseEntity.ok(checkerMap);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,48 +15,45 @@
*/
package com.alibaba.nacos.naming.healthcheck;

import com.alibaba.nacos.naming.healthcheck.extend.HealthCheckExtendProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @author nacos
*/
@Component("healthCheckDelegate")
public class HealthCheckProcessorDelegate implements HealthCheckProcessor {

@Autowired
private HttpHealthCheckProcessor httpProcessor;

@Autowired
private TcpSuperSenseProcessor tcpProcessor;
private Map<String, HealthCheckProcessor> healthCheckProcessorMap
= new HashMap<>();

@Autowired
private MysqlHealthCheckProcessor mysqlProcessor;
public HealthCheckProcessorDelegate(HealthCheckExtendProvider provider) {
provider.init();
}

@Autowired
private NoneHealthCheckProcessor noneProcessor;
public void addProcessor(Collection<HealthCheckProcessor> processors){
healthCheckProcessorMap.putAll(processors.stream()
.filter(processor -> processor.getType() != null)
.collect(Collectors.toMap(HealthCheckProcessor::getType, processor -> processor)));
}

@Override
public void process(HealthCheckTask task) {

String type = task.getCluster().getHealthChecker().getType();

if (type.equals(httpProcessor.getType())) {
httpProcessor.process(task);
return;
}

if (type.equals(tcpProcessor.getType())) {
tcpProcessor.process(task);
return;
}

if (type.equals(mysqlProcessor.getType())) {
mysqlProcessor.process(task);
return;
HealthCheckProcessor processor = healthCheckProcessorMap.get(type);
if(processor == null){
processor = healthCheckProcessorMap.get("none");
}

noneProcessor.process(task);
processor.process(task);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,68 @@
*/
package com.alibaba.nacos.naming.healthcheck;

import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* @author nkorange
*/
public enum HealthCheckType {
/**
* TCP type
*/
TCP,
TCP("tcp", AbstractHealthChecker.Tcp.class),
/**
* HTTP type
*/
HTTP,
HTTP("http", AbstractHealthChecker.Http.class),
/**
* MySQL type
*/
MYSQL,
MYSQL("mysql", AbstractHealthChecker.Mysql.class),
/**
* No check
*/
NONE
NONE("none", AbstractHealthChecker.None.class);

private String name;

private Class healthCheckerClass;

private static Map<String, Class> EXTEND =
new ConcurrentHashMap<>();

HealthCheckType(String name, Class healthCheckerClass) {
this.name = name;
this.healthCheckerClass = healthCheckerClass;
}

public static void registerHealthChecker(String type, Class healthCheckerClass){
EXTEND.putIfAbsent(type, healthCheckerClass);
}

public static Class ofHealthCheckerClass(String type){
HealthCheckType enumType;
try {
enumType = valueOf(type);
}catch (Exception e){
return EXTEND.get(type);
}
return enumType.healthCheckerClass;
}

public static List<Class> getLoadedHealthCheckerClasses(){
List<Class> all = new ArrayList<>();
for(HealthCheckType type : values()){
all.add(type.healthCheckerClass);
}
for(Map.Entry<String, Class> entry : EXTEND.entrySet()){
all.add(entry.getValue());
}
return all;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,16 @@ 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");

if (StringUtils.equals(checkType, AbstractHealthChecker.Http.TYPE)) {
return (T) JSON.parseObject(jsonObj.toJSONString(), AbstractHealthChecker.Http.class);
}

if (StringUtils.equals(checkType, AbstractHealthChecker.Tcp.TYPE)) {
return (T) JSON.parseObject(jsonObj.toJSONString(), AbstractHealthChecker.Tcp.class);
}

if (StringUtils.equals(checkType, AbstractHealthChecker.None.TYPE)) {
return (T) JSON.parseObject(jsonObj.toJSONString(), AbstractHealthChecker.None.class);
}
Class target = HealthCheckType.ofHealthCheckerClass(checkType);

if (StringUtils.equals(checkType, AbstractHealthChecker.Mysql.TYPE)) {
return (T) JSON.parseObject(jsonObj.toJSONString(), AbstractHealthChecker.Mysql.class);
if(target != null){
return (T) JSON.parseObject(jsonObj.toJSONString(), target);
}

return null;
Expand All @@ -83,21 +74,6 @@ public void write(JSONSerializer jsonSerializer, Object o, Object o1, Type type,

writer.writeFieldValue(',', "type", config.getType());

if (StringUtils.equals(config.getType(), HealthCheckType.HTTP.name())) {
AbstractHealthChecker.Http httpCheckConfig = (AbstractHealthChecker.Http) config;
writer.writeFieldValue(',', "path", httpCheckConfig.getPath());
writer.writeFieldValue(',', "headers", httpCheckConfig.getHeaders());
}

if (StringUtils.equals(config.getType(), HealthCheckType.TCP.name())) {
// nothing sepcial to handle
}

if (StringUtils.equals(config.getType(), HealthCheckType.MYSQL.name())) {
AbstractHealthChecker.Mysql mysqlCheckConfig = (AbstractHealthChecker.Mysql) config;
writer.writeFieldValue(',', "user", mysqlCheckConfig.getUser());
writer.writeFieldValue(',', "pwd", mysqlCheckConfig.getPwd());
writer.writeFieldValue(',', "cmd", mysqlCheckConfig.getCmd());
}
config.jsonAdapterCallback(writer);
}
}
Loading

0 comments on commit 1f1b047

Please sign in to comment.