1

1、告警模块整体架构模型

告警模块梳理 (1).png

2、告警服务的三种告警服务模块

2.1、容错和监听事件

其实就是Master会监听Master、Worker中的Zookeeper中的临时顺序节点,一旦有Master或者Worker服务掉了,Master都会感知到,并向 t_ds_alert 表中插入对应的数据

org.apache.dolphinscheduler.server.master.registry.ServerNodeManager.MasterDataListener

class MasterDataListener implements SubscribeListener {
        @Override
        public void notify(Event event) {
            final String path = event.path();
            final Type type = event.type();
            if (registryClient.isMasterPath(path)) {
                try {
                    if (type.equals(Type.ADD)) {
                        log.info("master node : {} added.", path);
                    } else if (type.equals(Type.REMOVE)) {
                        log.info("master node : {} down.", path);
                        // 这里其实就是向 t_ds_alert 表中插入数据
                        alertDao.sendServerStoppedAlert(1, path, "MASTER");
                       // 这里其实就是向 t_ds_listener_event 表中插入数据
                       listenerEventAlertManager.publishServerDownListenerEvent(path, "MASTER");
                    }
                } catch (Exception ex) {
                    log.error("MasterNodeListener capture data change and get data failed.", ex);
                }
            }
        }
    }

org.apache.dolphinscheduler.server.master.registry.ServerNodeManager.WorkerDataListener

 class WorkerDataListener implements SubscribeListener {

        @Override
        public void notify(Event event) {
            final String path = event.path();
            final Type type = event.type();
            final String data = event.data();
            if (registryClient.isWorkerPath(path)) {
                try {
                    String[] parts = path.split("/");
                    final String workerAddress = parts[parts.length - 1];

                    // todo: update workerNodeInfo
                    log.debug("received subscribe event : {}", event);
                    if (type == Type.ADD) {
                        log.info("Worker: {} added, currentNode : {}", path, workerAddress);
                    } else if (type == Type.REMOVE) {
                        log.info("Worker node : {} down.", path);
                        removeSingleWorkerNode(workerAddress);
                        // 这里其实就是向 t_ds_alert 表中插入数据
                        alertDao.sendServerStoppedAlert(1, path, "WORKER");
                        // 这里其实就是向 t_ds_listener_event 表中插入数据 
                        listenerEventAlertManager.publishServerDownListenerEvent(path, "WORKER");
                    } else if (type == Type.UPDATE) {
                        syncSingleWorkerNodeInfo(workerAddress, JSONUtils.parseObject(data, WorkerHeartBeat.class));
                    }
                } catch (Exception ex) {
                    log.error("WorkerGroupListener capture data change and get data failed", ex);
                }
            }
        }
}

注意 : 监听事件表存在不单单就是上面master或worker节点掉了的事件监听而已,还有比如说流程定义删除、流程实例启动、流程实例结束等等,详细参考 : org.apache.dolphinscheduler.service.alert.ListenerEventAlertManager

2.2、RPC服务

org.apache.dolphinscheduler.alert.rpc.AlertRpcServer
AlertRpcServer是一个Netty服务,可接收RPC请求

同时AlertRpcServer继承了SpringServerMethodInvokerDiscovery,SpringServerMethodInvokerDiscovery实现了BeanPostProcessor。简单说 : BeanPostProcessor也称为Bean后置处理器,它是Spring中定义的接口,在Spring容器的创建过程中(具体为Bean初始化前后)会回调BeanPostProcessor中定义的两个方。

org.apache.dolphinscheduler.extract.base.server.SpringServerMethodInvokerDiscovery

@Slf4j
public class SpringServerMethodInvokerDiscovery implements BeanPostProcessor {

    protected final NettyRemotingServer nettyRemotingServer;

    public SpringServerMethodInvokerDiscovery(NettyRemotingServer nettyRemotingServer) {
        this.nettyRemotingServer = nettyRemotingServer;
    }

    @Nullable
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Class<?>[] interfaces = bean.getClass().getInterfaces();
        for (Class<?> anInterface : interfaces) {
            if (anInterface.getAnnotation(RpcService.class) == null) {
                continue;
            }
            // anInterface 是接口,bean是实例,beanName是全类名
            registerRpcMethodInvoker(anInterface, bean, beanName);
        }
        return bean;
    }

    private void registerRpcMethodInvoker(Class<?> anInterface, Object bean, String beanName) {
        Method[] declaredMethods = anInterface.getDeclaredMethods();
        for (Method method : declaredMethods) {
            RpcMethod rpcMethod = method.getAnnotation(RpcMethod.class);
            if (rpcMethod == null) {
                continue;
            }
            ServerMethodInvoker methodInvoker = new ServerMethodInvokerImpl(bean, method);
            // 其实这里就是向alert rpc netty中注册对应的handler
            nettyRemotingServer.registerMethodInvoker(methodInvoker);
            log.debug("Register ServerMethodInvoker: {} to bean: {}", methodInvoker.getMethodIdentify(), beanName);
        }
    }
}

3、实例

image.png
可以看到创建了两个实例,一个是全局告警,一个不是全局告警。两个的区别在于 : 全局告警相当于是管理员,需要知道所有的告警。普通告警是针对个人的告警组。
全局告警订阅的是其实就是监听事件表,只要往监听事件表发送消息,就会使用全局告警组对外进行告警
普通告警那就是比如说针对流程、任务、超时和任务结果的告警。当然还有节点的容错

以Email插件,126邮箱为例 :

3.1、首先126中设置开通

image.png
注意 : 记住授权密码

3.2、创建告警实例

告警实例配置.png
点击 测试发送 ,看结果如下 :
image.png

4、BUG说明

4.1、后端(3.2.2分支已解决)

因为我使用的是 3.2.1 版本,我解决了之后,突然发现 3.2.2 tag上面也解决,无所谓了。
org.apache.dolphinscheduler.api.service.impl.AlertPluginInstanceServiceImpl#testSend
image.png

4.2、前端(官网暂未解决)

什么问题呢?你发现default admin warning group默认管理员告警组是不能进行编辑的,所以有以下修改
image.png

4.3、后端(t_ds_listener_event)(官网暂未解决)

image.png


journey
32 声望23 粉丝