com.alibaba.csp.ahas.sentinel.DefaultSentinelSdkService Maven / Gradle / Ivy
package com.alibaba.csp.ahas.sentinel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import com.alibaba.csp.ahas.sentinel.acm.SentinelSdkInitService;
import com.alibaba.csp.ahas.sentinel.acm.SentinelSdkInitServiceManager;
import com.alibaba.csp.sentinel.Constants;
import com.alibaba.csp.sentinel.adapter.agent.AgentCompatibilityUtils;
import com.alibaba.csp.sentinel.command.handler.*;
import com.alibaba.csp.sentinel.command.handler.cluster.FetchClusterModeCommandHandler;
import com.alibaba.csp.sentinel.command.handler.cluster.ModifyClusterModeCommandHandler;
import com.alibaba.csp.sentinel.concurrent.NamedThreadFactory;
import com.alibaba.csp.sentinel.init.InitFunc;
import com.alibaba.csp.sentinel.init.InitOrder;
import com.alibaba.csp.sentinel.log.RecordLog;
import com.alibaba.csp.sentinel.setting.handler.FallbackBehaviorCheckCommandHandler;
import com.alibaba.csp.sentinel.spi.SpiOrder;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.taobao.csp.ahas.service.api.constant.AppConstants;
import com.taobao.csp.ahas.service.api.transport.TransportService;
import com.taobao.csp.ahas.service.component.AgwComponent;
import com.taobao.csp.ahas.service.component.AgwComponentManager;
import com.taobao.csp.ahas.service.component.AgwComponentType;
import com.taobao.csp.ahas.service.component.AgwProductCode;
import com.taobao.csp.ahas.service.exception.SentinelDisabledException;
import com.taobao.csp.ahas.service.init.AhasInitFunc;
import com.taobao.csp.ahas.transport.api.Response;
import com.taobao.csp.ahas.transport.api.ServiceConstants.Sentinel;
import static com.alibaba.csp.sentinel.init.InitOrder.HIGHEST_PRECEDENCE;
/**
* @author changjun.xcj
* @author leyou
*/
@SpiOrder(-10000)
@InitOrder(HIGHEST_PRECEDENCE)
public class DefaultSentinelSdkService implements InitFunc {
private static final AgwComponent agwComponent = AgwComponentManager.getAgwComponent();
private static final AtomicBoolean isAhasInit = new AtomicBoolean(false);
private static final AtomicBoolean ahasInitSuccess = new AtomicBoolean(false);
private static final ExecutorService INIT_EXECUTOR =
Executors.newSingleThreadExecutor(new NamedThreadFactory("AhasSentinelSdkService-init-thread", true));
private static ScheduledExecutorService hbScheduler = new ScheduledThreadPoolExecutor(2,
new NamedThreadFactory("ahas-sentinel-heartbeat-send-task", true), new DiscardOldestPolicy());
private static DefaultSentinelSdkService defaultSentinelSdkService;
private static String ahasSdkVersion;
public static synchronized DefaultSentinelSdkService getInstance() {
if (defaultSentinelSdkService == null) {
defaultSentinelSdkService = new DefaultSentinelSdkService();
}
return defaultSentinelSdkService;
}
public DefaultSentinelSdkService() {
// Agent存在,SDK中不再重复初始化
// 注意:HeartBeatSender 不在此处初始化,而是由 Sentinel SPI 机制加载
if (AgentCompatibilityUtils.isAgentPresent()) {
return;
}
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
initAhasTransport();
} catch (Throwable e) {
RecordLog.warn("[DefaultSentinelSdkService] Failed to initialize AHAS transport", e);
System.err.println("ERROR: AHAS init fail");
}
}
};
INIT_EXECUTOR.submit(runnable);
}
@Override
public void init() throws Exception {
// Agent存在,SDK中不再重复初始化
if (AgentCompatibilityUtils.isAgentPresent()) {
return;
}
Runnable runnable = new Runnable() {
@Override
public void run() {
if (!ahasInitSuccess.get()) {
return;
}
try {
SentinelSdkInitService sentinelSdkInitService = SentinelSdkInitServiceManager
.getInitService(agwComponent.getClientInfoService());
sentinelSdkInitService.init(ahasSdkVersion);
} catch (Throwable throwable) {
RecordLog.warn("[DefaultSentinelSdkService] Init AHAS Sentinel or ACM error", throwable);
}
}
};
INIT_EXECUTOR.submit(runnable);
}
private void initAhasTransport() throws Exception {
if (!isAhasInit.compareAndSet(false, true)) {
return;
}
// Register command handler in advance.
registerCommandHandler();
// Set client version manually.
// TODO always remember keep the version same as in pom!!!
// 为了防止 ahas-sentinel-client 被用户 shade 后取得版本不对,这里先 hard code. 切记记得版本更新的时候同步改掉!!!
ahasSdkVersion = "1.10.10_1.10.10";
System.setProperty(AppConstants.AHAS_VERSION, ahasSdkVersion);
// skip init AHAS proxy if ahas.inner.agw.disable has been set.
if (AgwComponentManager.isInner() && System.getProperty(AppConstants.AHAS_INNER_AGW_DISABLE) != null) {
RecordLog.info("ahas.inner.agw.disable detected (inner env), so AHAS agw module will not be initialized");
ahasInitSuccess.set(true);
return;
}
int times = 0;
while (true) {
try {
((AhasInitFunc) agwComponent.getClientInfoService()).init("JAVA_SDK", null);
agwComponent.getTransportService().init(agwComponent.getClientInfoService(),AgwProductCode.SENTINEL);
agwComponent.getHeartbeatService().init(agwComponent);
break;
} catch (Throwable throwable) {
if (throwable instanceof SentinelDisabledException) {
RecordLog.warn("[DefaultSentinelSdkService] AHAS Sentinel disabled, stop connect to server.");
throw new SentinelDisabledException("AHAS Sentinel disabled");
} else {
RecordLog.error("[DefaultSentinelSdkService] Failed to init AHAS transport, region={}, "
+ "will retry (current {}) ", agwComponent.getClientInfoService().getRegionId(), times,
throwable);
times++;
if (AgwComponentManager.isInner() && times > 3) {
// Proxy transport is not mandatory in inner mode.
AhasGlobalContext.setClientInfoService(agwComponent.getClientInfoService());
ahasInitSuccess.set(true);
RecordLog.warn("AHAS transport module will be skipped during Sentinel initialization");
return;
}
try {
Thread.sleep(1000 * 10);
} catch (Exception ignore) {
}
}
}
}
RecordLog.info("[DefaultSentinelSdkService] AHAS gateway host: " +
agwComponent.getClientInfoService().getGatewayHost() +
", port:" + agwComponent.getClientInfoService().getGatewayPort());
AhasGlobalContext.setClientInfoService(agwComponent.getClientInfoService());
// Since 1.9.2,AHAS SDK 心跳机制不再依赖 Sentinel 本身的 HeartbeatSender SPI,以避免初始化顺序导致读不到配置的问题.
initHeartbeatTask();
ahasInitSuccess.set(true);
RecordLog.info("AHAS transport has been initialized successfully");
}
private String getAhasVersion(String defaultVersion) {
String gwVersion = defaultVersion;
try {
String version = DefaultSentinelSdkService.class.getPackage().getImplementationVersion();
if (StringUtil.isNotBlank(version)) {
gwVersion = version;
}
} catch (Throwable e) {
RecordLog.warn("[DefaultSentinelSdkService] Using default AHAS version, ignore exception", e);
}
return gwVersion;
}
/**
* Get whole version of the SDK.
*
* @param ahasVersion AHAS SDK version
* @return sentinel-core version + AHAS SDK version
*/
private String getWholeVersion(/*@Valid*/ String ahasVersion) {
String coreVersion = Constants.SENTINEL_VERSION;
String wholeVersion = coreVersion + "_" + ahasVersion;
RecordLog.info("[DefaultSentinelSdkService] wholeVersion: " + wholeVersion);
return wholeVersion;
}
/**
* Register Sentinel handler to {@link TransportService}
*/
private void registerCommandHandler() {
agwComponent.getTransportService().registerHandler(Sentinel.CLUSTER_NODE.getHandlerName(),
new SentinelRequestHandler(new FetchSimpleClusterNodeCommandHandler()));
agwComponent.getTransportService().registerHandler(Sentinel.JSON_TREE.getHandlerName(),
new SentinelRequestHandler(new FetchJsonTreeCommandHandler()));
agwComponent.getTransportService().registerHandler(Sentinel.METRIC.getHandlerName(),
new SentinelRequestHandler(new SendMetricCommandHandler()));
agwComponent.getTransportService().registerHandler(Sentinel.GET_RULES.getHandlerName(),
new SentinelRequestHandler(new FetchActiveRuleCommandHandler()));
agwComponent.getTransportService().registerHandler(Sentinel.VERSION.getHandlerName(),
new SentinelRequestHandler(new VersionCommandHandler()));
agwComponent.getTransportService().registerHandler(Sentinel.GET_SWITCH.getHandlerName(),
new SentinelRequestHandler(new OnOffGetCommandHandler()));
agwComponent.getTransportService().registerHandler(Sentinel.SET_SWITCH.getHandlerName(),
new SentinelRequestHandler(new OnOffSetCommandHandler()));
// Cluster handlers.
agwComponent.getTransportService().registerHandler(Sentinel.SET_CLUSTER_MODE.getHandlerName(),
new SentinelRequestHandler(new ModifyClusterModeCommandHandler()));
agwComponent.getTransportService().registerHandler(Sentinel.GET_CLUSTER_MODE.getHandlerName(),
new SentinelRequestHandler(new FetchClusterModeCommandHandler()));
// (since 1.9.5)
agwComponent.getTransportService().registerHandler(Sentinel.CHECK_FALLBACK_BEHAVIOR.getHandlerName(),
new SentinelRequestHandler(new FallbackBehaviorCheckCommandHandler()));
// Add customized command handlers for PRIVATE_CLOUD mode.
if (AgwComponentType.PRIVATE_CLOUD.getType() == SentinelSdkInitServiceManager.getMode()) {
agwComponent.getTransportService().registerHandler(Sentinel.EXECUTE_SHELL_COMMAND.getHandlerName(),
new SentinelRequestHandler(new ExecuteShellCommandHandler()));
}
}
private void initHeartbeatTask() {
int ahasHbIntervalMs = agwComponent.getClientInfoService().getHeartbeatRate() * 1000;
int intervalMs = ahasHbIntervalMs > 0 ? ahasHbIntervalMs : 8000;
if (AgwComponentManager.isInner() && agwComponent.getClientInfoService().getUserId() == null) {
// This indicates that the transport module was not initialized successfully.
return;
}
// 这里不再依赖 Sentinel 本身的 HeartbeatSender 模块.
hbScheduler.scheduleAtFixedRate(new Runnable() {
public void run() {
try {
sendHeartbeat();
} catch (Throwable var2) {
RecordLog.warn("[HeartbeatSender] Send heartbeat error", var2);
}
}
}, 3000L, intervalMs, TimeUnit.MILLISECONDS);
RecordLog.info("AHAS Sentinel heartbeat task started, interval={}ms", intervalMs);
}
public boolean sendHeartbeat() throws Exception {
if (!ahasInitSuccess.get() || agwComponent.getClientInfoService().getSentinalDisable() == 1) {
return false;
}
if (AgwComponentManager.isInner() && agwComponent.getClientInfoService().getUserId() == null) {
// This indicates that the transport module was not initialized successfully.
return false;
}
Response> mapResponse = agwComponent.getHeartbeatService().sendHeartbeat(AgwProductCode.SENTINEL);
if (!mapResponse.isSuccess()) {
throw new RuntimeException(mapResponse.toString());
}
return mapResponse.isSuccess();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy