2.微服务灰度发布落地实践(agent实现)

news2024/12/28 23:00:10

前言

据上一篇,设计方案的分析,综合考虑,最终决定,客户端采用agent方案实现,具本原因不再赘述,
感觉兴趣的小伙伴可以回头了解一下.该篇主要讲java agent的实现,灰度agent客户端的基础框架实现

java agent的介绍

java Agent 是一种允许你在 Java 应用程序启动时或运行时修改其字节码的技术。
它通过 JVM 提供的 java.lang.instrument 包来实现,可以用于各种用途,
如性能监控、代码增强、AOP(面向切面编程)、日志记录等。
Java Agent 的核心功能是能够在类加载到 JVM 之前对其进行修改,
而无需修改应用程序的源代码。启动时代理(Premain Agent):在 JVM 启动时加载的代理。你需要通过 -javaagent 参数指定代理的 JAR 文件路径,并提供一个 premain 方法作为入口点。

public static void premain(String agentArgs, Instrumentation inst) {
    // 在这里注册 ClassFileTransformer 或执行其他初始化逻辑
}

基础实现

agent的实现的基础,是基于开源项目skywalking的插件核心实现,没必要重复造轮子,要做的是专注
去实现灰度相关的功能.

agent端 http服务实现

为了方便灰度管理端,给agent端实时推送数据,agent端,基于netty实现单简的http服务,; 会提供接口,供服务端对实例状态的控制,以及其它服务实例状态的推送;实例在收发消息或路由时,依赖这些信息作相应处理。
如果不太了解这块功能的作用,可以去第一篇看一下整个系统的架构图;下需要agent http server代码片段

SimpleChannelInboundHandler agentServerHttpInboundHandler = new AgentServerHttpInboundHandler();
agentChannelInitializer = new AgentServerChannelInitializer(agentServerHttpInboundHandler);
Thread serverThread = new Thread(new RunnableWithExceptionProtection(() -> {
    LOGGER.info("dbcat gray agent netty server.");
    ServerBootstrap serverBootstrap = new ServerBootstrap();
    bossGroup = new NioEventLoopGroup(1, new DefaultNamedThreadFactory("server-boss"));
    workerGroup = new NioEventLoopGroup(4, new DefaultNamedThreadFactory("server-worker"));
    serverBootstrap.group(bossGroup, workerGroup)
           .channel(NioServerSocketChannel.class)
           .option(ChannelOption.SO_REUSEADDR, true)
           .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
           .childOption(ChannelOption.TCP_NODELAY, true)
           .childOption(ChannelOption.SO_KEEPALIVE, true)
           .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
           .childHandler(agentChannelInitializer);
    int port = Config.Agent.SERVER_PORT;
    try {
         ChannelFuture f = serverBootstrap.bind(port).sync();
         LOGGER.info("dbcat gray agent server started, port is {}.", port);
         f.channel().closeFuture().sync();
         LOGGER.info("dbcat gray agent server closed, port is {}.", port);
    } catch (InterruptedException e) {
         LOGGER.error("dbcat gray agent server start failed", e);
         Thread.currentThread().interrupt();
    }
}, t -> {
}), "gray-agent-server");
serverThread.setDaemon(true);
serverThread.start();

agent端api接口

上面实现agent端的http服务,灰度服务端如果需要控制agent客户端,必需还要提供api接口,才能进行交互
http 接口实现片段

   public class AgentServerHttpInboundHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
       private static final ILog log = LogManager.getLogger(AgentServerHttpInboundHandler.class);
       private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create();
       @Override
       public void channelReadComplete(ChannelHandlerContext ctx) {
           ctx.flush();
       }
       @Override
       protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) {
           //收到http请求
           QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.uri());
           String requestUri = queryStringDecoder.rawPath();
           String method = request.method().name();
           if (!"POST".equals(method.toUpperCase())) {
               complete(ctx, request,  RestResult.buildFailure(HttpResponseStatus.METHOD_NOT_ALLOWED.toString(),HttpResponseStatus.METHOD_NOT_ALLOWED.code()));
               return;
           }
           //通过url配置接口对应用实现
           Endpoint endpoint = EndpointManager.getEndpoint(requestUri);
           if (endpoint == null) {
               complete(ctx, request, RestResult.buildFailure(HttpResponseStatus.NOT_FOUND.toString(),HttpResponseStatus.NOT_FOUND.code()));
               return;
           }
           Throwable throwable = null;
           RestResult result = null;
           try {
               ByteBuf content = request.content();
               byte[] requestBodyBytes = new byte[content.readableBytes()];
               content.readBytes(requestBodyBytes);
               String requestBodyString = new String(requestBodyBytes, "UTF-8");
               ParameterizedType parameterizedType = ((ParameterizedType) endpoint.getClass().getGenericInterfaces()[0]);
               Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
               Object data =  GSON.fromJson(requestBodyString,actualTypeArguments[0]);
               //调用相应的接口
               result = endpoint.invoke(data);
           } catch (Throwable e) {
               log.error(String.format("接口响应异常%s", requestUri), e);
               throwable = e;
           } finally {
               if (throwable == null) {
                   complete(ctx, request, result);
               } else {
                   complete(ctx, request, RestResult.buildFailure(throwable.getMessage(),HttpResponseStatus.INTERNAL_SERVER_ERROR.code()));
               }
           }
       }
   }

Endpoint api 接口类,通过spi 方式加载实现

    public class EndpointManager {
        private static final Map<String, Endpoint> ENDPOINT_INVOKER_MAP = new HashMap<>();
        static {
            for (final Endpoint endpointInvoker : ServiceLoader.load(Endpoint.class, AgentClassLoader.getDefault())) {
                ENDPOINT_INVOKER_MAP.put(endpointInvoker.path(), endpointInvoker);
            }
        }
        public static Endpoint<?, ?> getEndpoint(String requestUri) {
            return ENDPOINT_INVOKER_MAP.get(requestUri);
        }
    }

Endpoint 的实某个实现,如更新实例状态接口

public class EnvStatusUpdateEndpoint implements Endpoint<InstanceEnvUpdateRequest, List<ExecuteResponse>> {
    private static final ILog log = LogManager.getLogger(EnvStatusUpdateEndpoint.class);
    @Override
    public String path() {
        return "/env-status/update";
    }

    @Override
    public RestResult<List<ExecuteResponse>> invoke(InstanceEnvUpdateRequest request) throws Exception {
        log.info("更新实例信息");
        ServerInstance.getInstance().setEnvStatus(request.getEnvStatus());
        List<ExecuteResponse> executeResponses = MQConnectionManager.restartAll(request.getStrategy());
        return RestResult.buildSuccess(executeResponses);
    }
}

到此,agent客户端的基础框加已实现,下一篇将开始介绍相关核心组件灰度的增强实现

硬广

最后,不要脸给大家安利一款mysql监控软件: 安装方便,消耗低,可视化,傻瓜式操作,可以监控慢日志详情、cpu、内存、连接数、tps 等信息
体验演示
下载地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2267144.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

面向对象的设计原则与设计模式

目的 设计模式的目的是提高代码的重用性&#xff0c;可读性、可扩展性、可靠性&#xff0c;使程序呈现高内聚&#xff0c;低耦合的特性 原则 单一职责原则 假设有一个class负责两个职责&#xff0c;一旦发生需求变更&#xff0c;修改其中一个职责的逻辑代码&#xff0c;有可能…

网络安全词云图与技术浅谈

网络安全词云图与技术浅谈 一、网络安全词云图生成 为了直观地展示网络安全领域的关键术语&#xff0c;我们可以通过词云图&#xff08;Word Cloud&#xff09;的形式来呈现。词云图是一种数据可视化工具&#xff0c;它通过字体大小和颜色的差异来突出显示文本中出现频率较高…

Jsonlizer,一个把C++各类数据转成 Json 结构体的玩意儿

这段时间突发奇想&#xff0c;觉得可以弄一个Json和C各种数据类型互转的工具&#xff0c;因为Json在进行数据储存的时候&#xff0c;有一些先天的优势&#xff0c;传统的C的序列化方式是将数据序列化到流数据里面&#xff0c;而流数据是典型的串行结构&#xff08;或则说是一维…

删除拼排序链表中的重复元素(最优解)

题目来源 82. 删除排序链表中的重复元素 II - 力扣&#xff08;LeetCode&#xff09; 题目描述 给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head…

OpenHarmony-5.PM 子系统(2)

电池服务组件OpenHarmony-4.1-Release 1.电池服务组件 Battery Manager 提供了电池信息查询的接口&#xff0c;同时开发者也可以通过公共事件监听电池状态和充放电状态的变化。电池服务组件提供如下功能&#xff1a; 电池信息查询。充放电状态查询。关机充电。 电池服务组件架…

深入浅出 Linux 操作系统

深入浅出 Linux 操作系统 引言 在当今数字化的时代&#xff0c;Linux 操作系统无处不在。从支撑互联网巨头庞大的数据中心&#xff0c;到嵌入智能家居设备的微型芯片&#xff0c;Linux 都发挥着关键作用。然而&#xff0c;对于许多人来说&#xff0c;Linux 仍笼罩着一层神秘的…

uniapp 文本转语音

uniapp 文本转语音 基于 Minimax API 的 UniApp 文本转语音工具&#xff0c;支持文本分段、队列播放、暂停恢复等功能。目前只内置了 Minimax文本转语音Minimax 的语音生成技术以其自然、情感丰富和实时性强而著称 API_KEY、GroupId 获取方法 https://platform.minimaxi.com…

前端图像处理(二)

目录 一、上传 1.1、文件夹上传以及进度追踪 1.2、拖拽上传 1.3、图片裁剪上传原理 二、图片布局 2.1、渐进式图片 2.2、图片九宫格 2.3、轮播图(Js) 2.3.1、3D动画轮播图 2.3.2、旋转切换的轮播图 2.4、卡片移入翻转效果 2.5、环绕式照片墙 一、上传 1.1、文件夹…

3.BMS系统原理图解读

一、BMS电池板 (1)电池的连接关系&#xff1a;串联 (2)采样控制点&#xff1a;CELL0 - CELL5 (3)端子P1和P3&#xff1a;BAT和BAT- (4)开关S1&#xff1a;控制充放电回路的机械开关 二、BMS控制板 (1)主控MCU 电源 复位 晶振 (2)LED指示灯&#xff1a;4电量指示 1调试指…

用于汽车碰撞仿真的 Ansys LS-DYNA

使用 Ansys LS-DYNA 进行汽车碰撞仿真汽车碰撞仿真 简介 汽车碰撞仿真是汽车设计和安全工程的一个关键方面。这些仿真使工程师能够预测车辆在碰撞过程中的行为&#xff0c;从而有助于改进安全功能、增强车辆结构并符合监管标准。Ansys LS-DYNA 是一款广泛用于此类仿真的强大工具…

使用Java和不同HTTP客户端库发送各种Content-Type类型请求

1. 引言 在HTTP协议中&#xff0c;Content-Type头用于指示请求或响应中数据的媒体类型。了解和正确设置Content-Type 对于确保客户端和服务器之间正确解析数据至关重要。本文将介绍如何使用Java 和 不同的HTTP客户端发送各种Content-Type 类型的请求。 2. 常见的Content-Type…

YOLO11改进-注意力-引入自调制特征聚合模块SMFA

本篇文章将介绍一个新的改进机制——SMFA&#xff08;自调制特征聚合模块&#xff09;&#xff0c;并阐述如何将其应用于YOLOv11中&#xff0c;显著提升模型性能。随着深度学习在计算机视觉中的不断进展&#xff0c;目标检测任务也在快速发展。YOLO系列模型&#xff08;You Onl…

【单片机通讯协议】—— 常用的UART/I2C/SPI等通讯协议的基本原理与时序分析

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、通信基本知识1.1 MCU的参见外设1.2 通信的分类按基本的类型从传输方向上来分 二、UART&#xff08;串口通讯&#xff09;2.1 简介2.2 时序图分析2.3 UART的…

Docker 部署 plumelog 最新版本 实现日志采集

1.配置plumelog.yml version: 3 services:plumelog:#此镜像是基于plumelog-3.5.3版本image: registry.cn-hangzhou.aliyuncs.com/k8s-xiyan/plumelog:3.5.3container_name: plumelogports:- "8891:8891"environment:plumelog.model: redisplumelog.queue.redis.redi…

Empire Lupin One靶机

靶机 ip&#xff1a;192.168.152.157 我们访问页面 第一步信息收集 我们先扫描一下端口 扫描到开启了 22 端口 80 端口 我们使用御剑扫描一下网站的后台 我们挨个访问一下 发现 apache 的帮助页面&#xff0c;暂时记录&#xff0c;看看等会有没有需要 我们查看到 robots.tx…

WPF 绘制过顶点的圆滑曲线(样条,贝塞尔)

项目中要用到样条曲线&#xff0c;必须过顶点&#xff0c;圆滑后还不能太走样&#xff0c;捣鼓一番&#xff0c;发现里面颇有玄机&#xff0c;于是把我多方抄来改造的方法发出来&#xff0c;方便新手&#xff1a; 如上图&#xff0c;看代码吧&#xff1a; -------------------…

绝美的数据处理图-三坐标轴-散点图-堆叠图-数据可视化图

clc clear close all %% 读取数据 load(MyColor.mat) %读取颜色包for iloop 1:25 %提取工作表数据data0(iloop) {readtable(data.xlsx,sheet,iloop)}; end%% 解析数据 countzeros(23,14); for iloop 1:25index(iloop) { cell2mat(table2array(data0{1,iloop}(1,1)))};data(i…

hdfs命令(三)- hdfs 管理命令(三)- hdfs dfsadmin命令

文章目录 前言一、hdfs分布式文件系统管理命令1. 介绍2. 语法及解释3. 命令3.1 生成HDFS集群的状态报告3.1.1 语法及解释3.1.2 示例 3.2 重新加载配置文件并更新NameNode中的节点列表3.3 刷新指定DataNode上的NameNode信息3.3.1 语法 3.4 获取并显示指定DataNode的信息3.4.1 语…

Word论文交叉引用一键上标

Word论文交叉引用一键上标 1.进入Microsoft word使用CtrlH快捷键或单击替换按钮 2.在查找内容中输入[^#] 3.鼠标点击&#xff0c;标签为“替换为&#xff1a;”的文本框&#xff0c;注意光标一定要打在图红色方框圈中的文本框中&#xff01; 4.点击格式选择字体 5.勾选上标…

JAVA:最简单多线程方法调用

以下介绍在JAVA中&#xff0c;最简单调用多线程的方法。 在需要使用多线程方法的类中&#xff0c;新增线程类Thread并实现方法run。 //定义多线程class ThreadLinePoints extends Thread{private String m;public ThreadLinePoints(){}public ThreadLinePoints(String m){this…