All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.alibaba.schedulerx.worker.discovery.DefaultServerDiscovery Maven / Gradle / Ivy
package com.alibaba.schedulerx.worker.discovery;
import java.net.URLEncoder;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.lang.StringUtils;
import com.alibaba.schedulerx.common.constants.CommonConstants;
import com.alibaba.schedulerx.common.domain.Constants;
import com.alibaba.schedulerx.common.domain.JSONResult;
import com.alibaba.schedulerx.common.domain.ResponseCode;
import com.alibaba.schedulerx.common.domain.ScaleGroupResult;
import com.alibaba.schedulerx.common.util.ConfigUtil;
import com.alibaba.schedulerx.common.util.JsonUtil;
import com.alibaba.schedulerx.worker.SchedulerxWorker;
import com.alibaba.schedulerx.worker.domain.WorkerConstants;
import com.alibaba.schedulerx.worker.log.LogFactory;
import com.alibaba.schedulerx.worker.log.Logger;
import com.alibaba.schedulerx.worker.util.ConsoleUtil;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.Unirest;
import akka.actor.ActorSelection;
import akka.actor.ActorSystem;
/**
* heart beat get active leader of specific group through console.
*
* @author @yanxun
* @date 2018/5/22
*/
public class DefaultServerDiscovery implements ServerDiscovery {
public DefaultServerDiscovery() {}
private static final Logger LOGGER = LogFactory.getLogger(DefaultServerDiscovery.class);
private static final String ACTIVE_SERVER_QUERY_PATH = "/worker/v1/appgroup/getLeaderAddr";
private static final String SERVER_DISCOVERY_THREAD_NAME = "activeServerDiscoveryThread-";
private ScheduledExecutorService scheduledExecutorService;
private volatile String activeServerAddr;
private volatile ActorSelection instanceStatusRouter;
private volatile ActorSelection mapMasterRouter;
private volatile ActorSelection taskStatusRouter;
private volatile ActorSelection heartbeatActor;
private volatile ActorSelection logActor;
private volatile ActorSystem actorSystem = SchedulerxWorker.actorSystem;
private GroupManager groupManager = GroupManager.INSTANCE;
private Configuration conf = ConfigUtil.getWorkerConfig();
private long exceptionCount = 0;
@Override
public void start(final String namespace, final String namespaceSource, final String groupId, final String appKey) throws Exception {
final String consoleDomain = conf.getString(WorkerConstants.WORKER_DOMAIN_NAME);
scheduledExecutorService = new ScheduledThreadPoolExecutor(1,
new ThreadFactoryBuilder().setNameFormat(SERVER_DISCOVERY_THREAD_NAME + groupId).build(),
new ThreadPoolExecutor.DiscardPolicy());
//如果开启了consolelist服务发现,通过console的ip轮询
final boolean enableConsoleList = ConfigUtil.getWorkerConfig().getBoolean(CommonConstants.SCHEDULERX_CONSOLELIST_ENABLE, false);
if (enableConsoleList) {
String consoleIp = ConsoleUtil.getRandomConsoleIp(consoleDomain);
if (consoleIp != null) {
conf.setProperty(WorkerConstants.WORKER_DOMAIN_NAME, consoleIp);
LOGGER.info("enable consoleList domain={}", consoleIp);
}
}
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
String domain = ConfigUtil.getWorkerConfig().getString(WorkerConstants.WORKER_DOMAIN_NAME);
String activeServer = queryActiveServer(domain, groupId, appKey, namespace, namespaceSource);
if (!StringUtils.isEmpty(activeServer) && !activeServer.equalsIgnoreCase(activeServerAddr)) {
LOGGER.info("activeServerAddr={} change to {}, actorSystem={}", activeServerAddr, activeServer,
actorSystem.provider().getDefaultAddress());
activeServerAddr = activeServer;
heartbeatActor = actorSystem.actorSelection(getServerHeartbeatAkkaPath(activeServerAddr));
instanceStatusRouter = actorSystem.actorSelection(getServerInstanceStatusRouterAkkaPath(activeServerAddr));
mapMasterRouter = actorSystem.actorSelection(getServerMapMasterRouterAkkaPath(activeServerAddr));
taskStatusRouter = actorSystem.actorSelection(getServerTaskStatusRouterAkkaPath(activeServerAddr));
logActor = actorSystem.actorSelection(getServerLogAkkaPath(activeServerAddr));
} else if (StringUtils.isEmpty(activeServer)) {
//console的ip可能会变,如果当前domain接口获取失败,重新获取新的consolelist
if (enableConsoleList) {
String consoleIp = ConsoleUtil.getRandomConsoleIp(consoleDomain);
if (consoleIp != null) {
conf.setProperty(WorkerConstants.WORKER_DOMAIN_NAME, consoleIp);
LOGGER.info("domain change from {} to {}", domain, consoleIp);
}
}
}
} catch (Throwable t) {
//console的ip可能会变,果然当前domain接口获取失败,重新获取新的consolelist
if (enableConsoleList) {
LOGGER.warn("scheduled query active server lost, you can ignore this message if not often.");
String consoleIp = ConsoleUtil.getRandomConsoleIp(consoleDomain);
if (consoleIp != null) {
conf.setProperty(WorkerConstants.WORKER_DOMAIN_NAME, consoleIp);
LOGGER.info("domain change to {}", consoleIp);
}
} else {
LOGGER.warn("scheduled query active server lost, you can ignore this message if not often.");
}
}
}
}, 0L, 10L, TimeUnit.SECONDS);
}
@Override
public String getActiveServerAddr() {
return activeServerAddr;
}
private String getServerInstanceStatusRouterAkkaPath(String serverAddr) {
return Constants.SERVER_AKKA_PATH_PREFIX + serverAddr + Constants.SERVER_AKKA_INSTANCE_STATUS_ROUTER_PATH;
}
private String getServerMapMasterRouterAkkaPath(String serverAddr) {
return Constants.SERVER_AKKA_PATH_PREFIX + serverAddr + Constants.SERVER_AKKA_MAP_MASTER_ROUTER_PATH;
}
private String getServerTaskStatusRouterAkkaPath(String serverAddr) {
return Constants.SERVER_AKKA_PATH_PREFIX + serverAddr + Constants.SERVER_AKKA_TASK_STATUS_ROUTER_PATH;
}
private String getServerHeartbeatAkkaPath(String serverAddr) {
return Constants.SERVER_AKKA_PATH_PREFIX + serverAddr + Constants.SERVER_AKKA_HEARTBEAT_PATH;
}
private String getServerLogAkkaPath(String serverAddr) {
return Constants.SERVER_AKKA_PATH_PREFIX + serverAddr + "/user/log";
}
@Override
public ActorSelection getActiveHeartBeatActor() {
return heartbeatActor;
}
@Override
public void stop() throws Exception {
scheduledExecutorService.shutdown();
}
private String queryActiveServer(String domain, String groupId, String appKey, String namespace, String namespaceSource) {
String activeServer = null;
String activeServerQueryUrl;
if (namespace != null) {
activeServerQueryUrl = "http://" + domain + ACTIVE_SERVER_QUERY_PATH
+ "?groupId=" + groupId + "&namespace=" + namespace;
if (StringUtils.isNotBlank(namespaceSource)) {
activeServerQueryUrl += "&namespaceSource="+namespaceSource;
}
} else {
activeServerQueryUrl = "http://" + domain + ACTIVE_SERVER_QUERY_PATH + "?groupId=" + groupId;
}
activeServerQueryUrl += "&enableScale=true";
try {
activeServerQueryUrl += "&appKey=" + URLEncoder.encode((appKey == null) ? "" : appKey, "UTF-8");
HttpResponse jsonResponse = Unirest.get(activeServerQueryUrl).asJson();
JSONResult jsonResult = JsonUtil.fromJson(jsonResponse.getBody().toString(), JSONResult.class);
LOGGER.debug("queryActiveServer url={}, response={}", activeServerQueryUrl, jsonResponse.getBody().toString());
if (jsonResult != null && jsonResult.isSuccess()) {
if (jsonResult.getCode() == ResponseCode.GROUP_HAS_CHILD) {
//该应用分组开启了自动扩容并且分裂过孩子,需要解析出所有的groupIds,并注册serverDiscovery
ScaleGroupResult groupResult = JsonUtil.fromJson(jsonResult.getData().toString(), ScaleGroupResult.class);
activeServer = groupResult.getCurrentLeaderAddr();
//返回的分组数大于缓存,说明有新的分裂,需要新注册
if (CollectionUtils.isNotEmpty(groupResult.getGroupIds())) {
for (String childGroup : groupResult.getGroupIds()) {
if (!groupManager.contains(childGroup)) {
if (groupResult.getGroupIdMap() != null) {
groupManager.putGroupId2AppKeyMap(childGroup, groupResult.getGroupIdMap().get(childGroup));
}
groupManager.startServerDiscovery(childGroup);
groupManager.appendGroupId(childGroup, groupId);
}
}
}
} else {
activeServer = (String)jsonResult.getData();
}
}
exceptionCount = 0;
} catch (Throwable e) {
if (exceptionCount++ < 10) {
LOGGER.warn("Query active server lost, you can ignore this message if not often, url=" + activeServerQueryUrl);
} else {
LOGGER.error("Query active server lost, please check you config, message:{}, url={}", e.getMessage(), activeServerQueryUrl, e);
}
}
return activeServer;
}
@Override
public ActorSelection getInstanceStatusRouter() {
return instanceStatusRouter;
}
@Override
public ActorSelection getMapMasterRouter() {
return mapMasterRouter;
}
@Override
public ActorSelection getTaskStatusRouter() {
return taskStatusRouter;
}
@Override
public ActorSelection getLogRouter() {
return logActor;
}
@Override
public void reset(ActorSystem actorSystem) {
activeServerAddr = null;
heartbeatActor = null;
instanceStatusRouter = null;
mapMasterRouter = null;
taskStatusRouter = null;
logActor = null;
this.actorSystem = actorSystem;
}
}