前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Sermant学习二

Sermant学习二

作者头像
路行的亚洲
发布2024-01-30 16:16:41
760
发布2024-01-30 16:16:41
举报
文章被收录于专栏:后端技术学习后端技术学习

一、AgentCoreEntrance

前面我们已经知道,AgentCoreEntrance主要做了这些事情

我们来看主要的这些步骤的套路,其一个核心,将相关信息进行上报

代码语言:javascript
复制
EventSender.sendEvent(new EventMessage(BootArgsIndexer.getInstanceId(), events))

上报的过程是通过事件完成的。最终通过netty来完成,发送即时数据到服务端:

代码语言:javascript
复制
nettyClient.sendInstantData(
        JSON.toJSONString(object, SerializerFeature.WriteMapNullValue).getBytes(StandardCharsets.UTF_8),
        type))

在发送的过程中,首先会将消息进行压缩,然后构建服务的数据,然后进行发送。主要分为两种,一种是即时发送,一种是放入队列中。

代码语言:javascript
复制
public boolean sendInstantData(byte[] msg, Message.ServiceData.DataType dataType) {
    if (!this.connectionAvailable) {
        LOGGER.warning("Netty connection is not available.");
        return false;
    }
    byte[] compressMsg = GzipUtils.compress(msg);
    Message.ServiceData serviceData =
            Message.ServiceData.newBuilder().setDataType(dataType).setData(ByteString.copyFrom(compressMsg))
                    .build();
    // 设置消息信息,然后进行发送,可以理解为就是写入和刷新
    Message.NettyMessage message = Message.NettyMessage.newBuilder()
            .setMessageType(Message.NettyMessage.MessageType.SERVICE_DATA).addServiceData(serviceData).build();
    if (channel == null) {
        LOGGER.warning("Netty channel is null, send instant data failure.");
        return false;
    } else {
        channel.writeAndFlush(message);
        LOGGER.info("Sent instant data successfully by netty.");
        return true;
    }
}

NettyServer会对压缩的业务数据进行解压,然后对数据类型进行判断。数据类型主要分为下面几类:

代码语言:javascript
复制
@Override
protected void handlerData(ChannelHandlerContext ctx, Message.NettyMessage msg) {
    List<Message.ServiceData> serviceDataList = msg.getServiceDataList();
    for (Message.ServiceData serviceData : serviceDataList) {
        ByteString data = serviceData.getData();
        // 解压数据,处理数据业务逻辑
        byte[] message = GzipUtils.decompress(data.toByteArray());
        int dataType = serviceData.getDataTypeValue();
        switch (dataType) {
            case Message.ServiceData.DataType.HEARTBEAT_DATA_VALUE:
                handleHeartBeat(message);
                break;
            case Message.ServiceData.DataType.EVENT_DATA_VALUE:
                handleEvent(message);
                break;
            // 保存契约信息
            case Message.ServiceData.DataType.VISIBILITY_DATA_VALUE:
                handleServiceVisibility(message);
                break;
            default:
                LOGGER.warn("Can not find the corresponding data type {}.", dataType);
        }
    }
}

也即:

代码语言:javascript
复制
HEARTBEAT_DATA_VALUE 心跳数据
EVENT_DATA_VALUE  事件数据
VISIBILITY_DATA_VALUE 可视化数据

然后进行对应的逻辑处理。

对应事件数据的处理是,首先发布事件publishEvent,然后执行webHookClient.doNotify(needPushWebHook)。

webhook事件推送的主要分为三种方式:

代码语言:javascript
复制
钉钉
飞书
welink

处理服务可见性信息

代码语言:javascript
复制
保存契约信息SERVER_MAP => 服务器名称、服务信息
保存血缘关系信息

或者移除服务。

二、CommandProcessor的处理方法

代码语言:javascript
复制
获取命令执行器 => 执行对应的命令,然后execute
commandExecutor.execute(commandArgs)

以安装方法为例:

代码语言:javascript
复制
private static void doInitPlugin(Plugin plugin) {
    loadPluginLibs(plugin);
    loadServiceLibs(plugin);
    PluginConfigManager.loadPluginConfigs(plugin);
    PluginServiceManager.initPluginServices(plugin);

    // 适配逻辑,类加载器需要在字节码增强前加入到插件类检索器中,否则可能会在字节码增强时,找不到拦截器
    ClassLoaderManager.getPluginClassFinder().addPluginClassLoader(plugin);

    // 根据插件类型选择不同的字节码增强安装方式
    if (plugin.isDynamic()) {
        ByteEnhanceManager.enhanceDynamicPlugin(plugin);
    } else {
        ByteEnhanceManager.enhanceStaticPlugin(plugin);
    }

    // 插件成功加载后步骤
    PLUGIN_MAP.put(plugin.getName(), plugin);
    PluginSchemaValidator.setDefaultVersion(plugin.getName());
    FrameworkEventCollector.getInstance().collectPluginsLoadEvent(plugin.getName());
    LOGGER.log(Level.INFO, "Load plugin:{0} successful.", plugin.getName());
}

上面可以看的完成安装后会执行收集插件加载事件,同时进行上报,方便在backend中可以查看到。

其主要是这个方法,而增强则是 ByteEnhanceManager.enhanceDynamicPlugin(plugin)和ByteEnhanceManager.enhanceStaticPlugin(plugin)这个方法。

可以看的这个重要工作installOn交给了bytebuddy。而sermant做的重要工作在process上。

代码语言:javascript
复制
 public ResettableClassFileTransformer install(Instrumentation instrumentation) {
        AgentBuilder builder = new Default().disableClassFormatChanges();
        for (BuilderAction action : actions) {
            builder = action.process(builder);
        }
        return builder.installOn(instrumentation);
    }

创建BufferedAgentBuilder并依据配置设置基础操作:

代码语言:javascript
复制
 1.设置启动类加载器相关的增强策略,见{@link #setBootStrapStrategy}
 2.设置增强扫描过滤规则,见{@link #setIgnoredRule}
 3.设置增强时的扫描日志监听器,见{@link #setLogListener}
 4.设置输出增强后字节码的监听器,见{@link #setOutputListener}

最终基于{@link com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer}添加字节码增强

也即我们声明的插件增强。

代码语言:javascript
复制
public void addEnhance(AbstractPluginDeclarer pluginDeclarer) {
    addAction(builder -> {
        PluginDescription pluginDescription = new AbstractPluginDescription() {
            final AbstractPluginDeclarer abstractPluginDeclarer = pluginDeclarer;

            @Override
            public Builder<?> transform(Builder<?> builder, TypeDescription typeDescription,
                    ClassLoader classLoader,
                    JavaModule module, ProtectionDomain protectionDomain) {
                return new ReentrantTransformer(abstractPluginDeclarer.getInterceptDeclarers(classLoader),
                        virtualPlugin)
                        .transform(builder, typeDescription, classLoader, module, protectionDomain);
            }

            @Override
            public boolean matches(TypeDescription target) {
                return abstractPluginDeclarer.getClassMatcher().matches(target);
            }
        };
        return builder.type(pluginDescription).transform(pluginDescription);
    });
}

也即构建完成后,bytebuddy帮sermant完成了最终的install的工作。

参考:

开源项目地址:https://github.com/huaweicloud/Sermant

开源项目官网:https://sermant.io/zh/document/user-guide

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-01-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 后端技术学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、AgentCoreEntrance
  • 二、CommandProcessor的处理方法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档