Skip to content

Commit

Permalink
【enhancement】新增springboot注册插件事件上报&支持stop方法中上报事件
Browse files Browse the repository at this point in the history
  • Loading branch information
lilai23 committed Jun 7, 2023
1 parent a291527 commit 3b6316b
Show file tree
Hide file tree
Showing 13 changed files with 294 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
package com.huaweicloud.sermant.core.plugin.service;

import com.huaweicloud.sermant.core.common.LoggerFactory;
import com.huaweicloud.sermant.core.event.collector.FrameworkEventCollector;
import com.huaweicloud.sermant.core.service.ServiceManager;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.ServiceLoader;
import java.util.logging.Level;
Expand All @@ -44,23 +47,27 @@ private PluginServiceManager() {
* @param classLoader 插件服务包的ClassLoader
*/
public static void initPluginService(ClassLoader classLoader) {
List<String> startServiceList = new ArrayList<>();
for (PluginService service : ServiceLoader.load(PluginService.class, classLoader)) {
if (loadService(service, service.getClass(), PluginService.class)) {
try {
service.start();
startServiceList.add(service.getClass().getName());
} catch (Exception ex) {
LOGGER.log(Level.SEVERE, String.format(Locale.ENGLISH, "Error occurs while starting plugin service: %s",
LOGGER.log(Level.SEVERE, String.format(Locale.ENGLISH,
"Error occurs while starting plugin service: %s",
service.getClass()), ex);
}
}
}
FrameworkEventCollector.getInstance().collectServiceStartEvent(startServiceList.toString());
}

/**
* 获取插件服务
*
* @param serviceClass 插件服务类
* @param <T> 插件服务类型
* @param <T> 插件服务类型
* @return 插件服务实例
*/
public static <T extends PluginService> T getPluginService(Class<T> serviceClass) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,26 +112,25 @@ public void setDynamicConfigEnable(boolean dynamicConfigEnable) {
* @return 是否开启了该服务
*/
public boolean checkServiceEnable(String serviceName) {
if ("com.huaweicloud.sermant.implement.service.heartbeat.HeartbeatServiceImpl".equals(serviceName)) {
if (ServiceManager.HEARTBEAT_SERVICE_IMPL.equals(serviceName)) {
return isHeartBeatEnable();
}
if ("com.huaweicloud.sermant.implement.service.send.netty.NettyGatewayClient".equals(serviceName)) {
if (ServiceManager.NETTY_GATEWAY_CLIENT.equals(serviceName)) {
return isGatewayEnable();
}
if ("com.huaweicloud.sermant.implement.service.dynamicconfig.BufferedDynamicConfigService".equals(
serviceName)) {
if (ServiceManager.BUFFERED_DYNAMIC_CONFIG_SERVICE.equals(serviceName)) {
return isDynamicConfigEnable();
}
if ("com.huaweicloud.sermant.implement.service.tracing.TracingServiceImpl".equals(serviceName)) {
if (ServiceManager.TRACING_SERVICE_IMPL.equals(serviceName)) {
return isTracingEnable();
}
if ("com.huaweicloud.sermant.implement.service.visibility.VisibilityServiceImpl".equals(serviceName)) {
if (ServiceManager.VISIBILITY_SERVICE_IMPL.equals(serviceName)) {
return isVisibilityEnable();
}
if ("com.huaweicloud.sermant.implement.service.inject.InjectServiceImpl".equals(serviceName)) {
if (ServiceManager.INJECT_SERVICE_IMPL.equals(serviceName)) {
return isInjectEnable();
}
if ("com.huaweicloud.sermant.implement.service.monitor.RegistryServiceImpl".equals(serviceName)) {
if (ServiceManager.REGISTRY_SERVICE_IMPL.equals(serviceName)) {
return isMonitorEnable();
}
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.huaweicloud.sermant.core.event.EventManager;
import com.huaweicloud.sermant.core.event.collector.FrameworkEventCollector;
import com.huaweicloud.sermant.core.exception.DupServiceException;
import com.huaweicloud.sermant.core.service.send.api.GatewayClient;
import com.huaweicloud.sermant.core.utils.SpiLoadUtils;

import java.util.ArrayList;
Expand All @@ -47,6 +48,48 @@
* @since 2021-10-26
*/
public class ServiceManager {
/**
* 动态配置服务类名
*/
public static final String BUFFERED_DYNAMIC_CONFIG_SERVICE = "com.huaweicloud.sermant"
+ ".implement.service.dynamicconfig.BufferedDynamicConfigService";

/**
* 心跳服务类名
*/
public static final String HEARTBEAT_SERVICE_IMPL = "com.huaweicloud.sermant.implement.service.heartbeat"
+ ".HeartbeatServiceImpl";

/**
* 注入服务类名
*/
public static final String INJECT_SERVICE_IMPL = "com.huaweicloud.sermant.implement.service.inject"
+ ".InjectServiceImpl";

/**
* netty网关服务类名
*/
public static final String NETTY_GATEWAY_CLIENT = "com.huaweicloud.sermant.implement.service.send.netty"
+ ".NettyGatewayClient";

/**
* 注册信息服务类名
*/
public static final String REGISTRY_SERVICE_IMPL = "com.huaweicloud.sermant.implement.service.monitor"
+ ".RegistryServiceImpl";

/**
* 链路追踪服务类名
*/
public static final String TRACING_SERVICE_IMPL = "com.huaweicloud.sermant.implement.service.tracing"
+ ".TracingServiceImpl";

/**
* 服务可见性服务类名
*/
public static final String VISIBILITY_SERVICE_IMPL = "com.huaweicloud.sermant.implement.service.visibility"
+ ".VisibilityServiceImpl";

/**
* 日志
*/
Expand Down Expand Up @@ -141,27 +184,38 @@ public BaseService handle(BaseService source, BaseService target) {
* 添加关闭服务的钩子
*/
private static void addStopHook() {
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
offerEvent();
for (BaseService baseService : new HashSet<>(SERVICES.values())) {
try {
baseService.stop();
} catch (Exception ex) {
LOGGER.log(Level.SEVERE, String.format(Locale.ENGLISH,
"Error occurs while stopping service: %s", baseService.getClass().toString()), ex);
}
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
BaseService nettyGateWayClient = SERVICES.get(NETTY_GATEWAY_CLIENT);
SERVICES.remove(NETTY_GATEWAY_CLIENT);
SERVICES.remove(GatewayClient.class.getCanonicalName());
for (BaseService baseService : new HashSet<>(SERVICES.values())) {
try {
baseService.stop();
} catch (Exception ex) {
LOGGER.log(Level.SEVERE, String.format(Locale.ENGLISH,
"Error occurs while stopping service: %s", baseService.getClass().toString()), ex);
}
}
offerEvent();
if (nettyGateWayClient != null) {
try {
nettyGateWayClient.stop();
} catch (Exception ex) {
LOGGER.log(Level.SEVERE, String.format(Locale.ENGLISH,
"Error occurs while stopping service: %s",
nettyGateWayClient.getClass().toString()), ex);
}
}
}));
}

private static void offerEvent() {
// 上报服务关闭事件
ArrayList<String> stopServiceArray = new ArrayList<>();
for (BaseService baseService : new HashSet<>(SERVICES.values())) {
FrameworkEventCollector.getInstance().collectServiceStopEvent(baseService.getClass().getName());
stopServiceArray.add(baseService.getClass().getName());
}
FrameworkEventCollector.getInstance().collectServiceStopEvent(stopServiceArray.toString());

// 上报Sermant关闭的事件
FrameworkEventCollector.getInstance().collectAgentStopEvent();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -514,11 +514,14 @@ const eventName = reactive({
GRACEFUL_OFFLINE_BEGIN: "无损下线开始",
GRACEFUL_OFFLINE_END: "无损下线结束",
// 路由插件事件
ROUTER_RULE_TAKE_EFFECT: "路由插件规则生效",
ROUTER_RULE_REFRESH: "路由插件规则刷新",
SAME_TAG_RULE_MATCH: "同标签优先规则匹配成功",
SAME_TAG_RULE_MISMATCH: "同标签优先规则匹配失败",
INSTANCE_REMOVAL: "实例摘除",
INSTANCE_RECOVERY: "实例恢复"
INSTANCE_RECOVERY: "实例恢复",
SPRINGBOOT_REGISTRY: "SpringBoot服务注册",
SPRINGBOOT_UNREGISTRY: "SpringBoot服务移除注册",
SPRINGBOOT_GRAY_CONFIG_REFRESH: "SpringBoot注册插件灰度规则刷新"
});
const displayState = reactive({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ public void collectServiceRouteRuleEvent(String rule) {
return;
}
String eventDescription = "Service router rule refresh:" + System.lineSeparator() + rule;
offerEvent(new Event(RouterEventDefinition.ROUTER_RULE_TAKE_EFFECT.getScope(),
RouterEventDefinition.ROUTER_RULE_TAKE_EFFECT.getEventLevel(),
RouterEventDefinition.ROUTER_RULE_TAKE_EFFECT.getEventType(),
new EventInfo(RouterEventDefinition.ROUTER_RULE_TAKE_EFFECT.getName(), eventDescription)));
offerEvent(new Event(RouterEventDefinition.ROUTER_RULE_REFRESH.getScope(),
RouterEventDefinition.ROUTER_RULE_REFRESH.getEventLevel(),
RouterEventDefinition.ROUTER_RULE_REFRESH.getEventType(),
new EventInfo(RouterEventDefinition.ROUTER_RULE_REFRESH.getName(), eventDescription)));
}

/**
Expand All @@ -80,10 +80,10 @@ public void collectGlobalRouteRuleEvent(String rule) {
return;
}
String eventDescription = "Global router rule refresh:" + System.lineSeparator() + rule;
offerEvent(new Event(RouterEventDefinition.ROUTER_RULE_TAKE_EFFECT.getScope(),
RouterEventDefinition.ROUTER_RULE_TAKE_EFFECT.getEventLevel(),
RouterEventDefinition.ROUTER_RULE_TAKE_EFFECT.getEventType(),
new EventInfo(RouterEventDefinition.ROUTER_RULE_TAKE_EFFECT.getName(), eventDescription)));
offerEvent(new Event(RouterEventDefinition.ROUTER_RULE_REFRESH.getScope(),
RouterEventDefinition.ROUTER_RULE_REFRESH.getEventLevel(),
RouterEventDefinition.ROUTER_RULE_REFRESH.getEventType(),
new EventInfo(RouterEventDefinition.ROUTER_RULE_REFRESH.getName(), eventDescription)));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@
*/
public enum RouterEventDefinition {
/**
* 路由插件规则生效事件
* 路由插件规则刷新事件
*/

ROUTER_RULE_TAKE_EFFECT("ROUTER_RULE_TAKE_EFFECT", EventType.GOVERNANCE, EventLevel.NORMAL),
ROUTER_RULE_REFRESH("ROUTER_RULE_REFRESH", EventType.OPERATION, EventLevel.NORMAL),

/**
* 同TAG优先规则匹配生效
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.huawei.discovery.config;

import com.huawei.discovery.entity.PlugEffectStrategyCache;
import com.huawei.discovery.event.SpringBootRegistryEventCollector;

import com.huaweicloud.sermant.core.common.LoggerFactory;
import com.huaweicloud.sermant.core.service.dynamicconfig.common.DynamicConfigEvent;
Expand All @@ -43,6 +44,7 @@ public void process(DynamicConfigEvent event) {
+ "[%s], " + "content [%s] ",event.getKey(), event.getEventType(), event.getContent()));
if (StringUtils.equalsIgnoreCase(PlugEffectWhiteBlackConstants.DYNAMIC_CONFIG_LISTENER_KEY, event.getKey())) {
PlugEffectStrategyCache.INSTANCE.resolve(event.getEventType(), event.getContent());
SpringBootRegistryEventCollector.getInstance().collectGrayConfigTakeEffectEvent(event.getContent());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved.
*
* 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.huawei.discovery.event;

import com.huawei.discovery.entity.DefaultServiceInstance;

import com.huaweicloud.sermant.core.config.ConfigManager;
import com.huaweicloud.sermant.core.event.Event;
import com.huaweicloud.sermant.core.event.EventCollector;
import com.huaweicloud.sermant.core.event.EventInfo;
import com.huaweicloud.sermant.core.event.EventManager;
import com.huaweicloud.sermant.core.event.config.EventConfig;

/**
* springboot注册插件事件采集器
*
* @author lilai
* @since 2023-04-14
*/
public class SpringBootRegistryEventCollector extends EventCollector {
private static volatile SpringBootRegistryEventCollector collector;

private final EventConfig eventConfig = ConfigManager.getConfig(EventConfig.class);

private SpringBootRegistryEventCollector() {
}

/**
* 获取springboot注册插件事件采集器单例
*
* @return springboot注册插件事件采集器单例
*/
public static SpringBootRegistryEventCollector getInstance() {
if (collector == null) {
synchronized (SpringBootRegistryEventCollector.class) {
if (collector == null) {
collector = new SpringBootRegistryEventCollector();
EventManager.registerCollector(SpringBootRegistryEventCollector.getInstance());
}
}
}
return collector;
}

/**
* 采集服务注册事件
*
* @param instance 微服务实例
*/
public void collectRegistryEvent(DefaultServiceInstance instance) {
if (!eventConfig.isEnable()) {
return;
}
String eventDescription = "Service instance register:" + instance.toString();
offerEvent(new Event(SpringBootRegistryEventDefinition.SPRINGBOOT_REGISTRY.getScope(),
SpringBootRegistryEventDefinition.SPRINGBOOT_REGISTRY.getEventLevel(),
SpringBootRegistryEventDefinition.SPRINGBOOT_REGISTRY.getEventType(),
new EventInfo(SpringBootRegistryEventDefinition.SPRINGBOOT_REGISTRY.getName(), eventDescription)));
}

/**
* 采集服务移除注册事件
*
* @param instance 微服务实例
*/
public void collectUnRegistryEvent(DefaultServiceInstance instance) {
if (!eventConfig.isEnable()) {
return;
}
String eventDescription = "Service instance unregister:" + instance.toString();
offerEvent(new Event(SpringBootRegistryEventDefinition.SPRINGBOOT_UNREGISTRY.getScope(),
SpringBootRegistryEventDefinition.SPRINGBOOT_UNREGISTRY.getEventLevel(),
SpringBootRegistryEventDefinition.SPRINGBOOT_UNREGISTRY.getEventType(),
new EventInfo(SpringBootRegistryEventDefinition.SPRINGBOOT_UNREGISTRY.getName(), eventDescription)));
}

/**
* 采集灰度配置生效事件
*
* @param config 灰度配置
*/
public void collectGrayConfigTakeEffectEvent(String config) {
if (!eventConfig.isEnable()) {
return;
}
String eventDescription = "Gray config refresh:" + config;
offerEvent(new Event(SpringBootRegistryEventDefinition.SPRINGBOOT_GRAY_CONFIG_REFRESH.getScope(),
SpringBootRegistryEventDefinition.SPRINGBOOT_GRAY_CONFIG_REFRESH.getEventLevel(),
SpringBootRegistryEventDefinition.SPRINGBOOT_GRAY_CONFIG_REFRESH.getEventType(),
new EventInfo(SpringBootRegistryEventDefinition.SPRINGBOOT_GRAY_CONFIG_REFRESH.getName(),
eventDescription)));
}
}
Loading

0 comments on commit 3b6316b

Please sign in to comment.