2.微服务灰度发布落地实践(agent实现)
前言
据上一篇,设计方案的分析,综合考虑,最终决定,客户端采用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();@Overridepublic void channelReadComplete(ChannelHandlerContext ctx) {ctx.flush();}@Overrideprotected 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);@Overridepublic String path() {return "/env-status/update";}@Overridepublic 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 等信息
体验演示
下载地址
相关文章:
2.微服务灰度发布落地实践(agent实现)
前言 据上一篇,设计方案的分析,综合考虑,最终决定,客户端采用agent方案实现,具本原因不再赘述, 感觉兴趣的小伙伴可以回头了解一下.该篇主要讲java agent的实现,灰度agent客户端的基础框架实现 java agent的介绍 ja…...
搭建医疗客服知识库:智慧医疗的基石
在医疗行业,客服知识库不仅是提供患者咨询和支持的平台,更是提升医疗服务效率和质量的关键工具。 1. 明确知识库的目标和价值 构建医疗行业客服知识库的首要任务是明确其目标和价值。这包括提供患者教育、辅助临床决策、优化患者服务流程等。明确目标后…...
CES Asia 2025的低空经济展区有哪些亮点?
CES Asia 2025(赛逸展)的低空经济展区有以下亮点: • 前沿科技产品展示: 多款新型无人机将亮相,如固定翼无人机和系留无人机的最新型号,其在监测、救援和货物运输等方面功能强大。此外,还有可能…...
Java/Spring项目包名为何以“com”开头?
文章目录 包名的基本概念域名反转规则历史背景包名的结构实际应用总结 在Java和Spring项目中,我们常常看到包名以“com”开头,比如com.example.project。这种命名方式看似简单,其实背后蕴含着不少学问。今天,我们就来聊聊这个话题…...
影刀进阶应用 | 知乎发布想法
文章目录 影刀进阶应用 | 知乎发布想法一、流程流程解释: 二、单条想法发布2.1 素材生产2.2 **进入发布流程**2.3 **输入文本**2.4 插入图片2.5 发布查看 三、批量发布 影刀进阶应用 | 知乎发布想法 一、流程 流程解释: 素材生产 :用AI生成待…...
v-if 和 v-for 优先级
一、优先级规则 在 Vue.js 中,v-for的优先级比v-if高。这意味着当它们同时出现在一个元素上时,v-for会首先被解析和执行。 <div v-for"item in items" v-if"shouldShow(item)">{{ item }}</div> 二、可能导致的问题 …...
【数据结构与算法】单向链表
一、什么是链表 链表由一系列节点组成,每个节点都包含一个 data 域(存放数据)和一个 next 域(指向下一节点)。链表中的节点可以按照任意顺序存放在内存中,它们之间并不连续。每个节点都记录了下一个节点的地…...
网络编程UDP—socket实现(C++)
网络编程UDP—socket实现 前言UDP客户端和服务端UDP使用场景UDP socket C代码示例服务端接收数据示例(bindrecvfrom 阻塞式接收信息):bind 绑定-监听 函数为什么一般都是监听所有网络接口呢?为什么需要用inet_addr进行转换&#x…...
系统思考—冰山模型
“卓越不是因机遇而生,而是智慧的选择与用心的承诺。”—— 亚里士多德 卓越,从来不是一次性行为,而是一种习惯。正如我们在日常辅导中常提醒自己:行为的背后,隐藏着选择的逻辑,而选择的根源,源…...
MySQL 中存储金额数据一般使用什么数据类型
在 MySQL 中存储金额数据时,应该谨慎选择数据类型,以确保数据的精度和安全性。以下是几种常用的数据类型及其适用性: DECIMAL 类型: 描述:DECIMAL 类型是专门为存储精确的小数而设计的。它可以指定小数点前后的数字位数…...
Excel中一次查询返回多列
使用Excel或wps的时候,有时候需要一次查询返回多列内容,这种情况可以选择多次vlookup或者多次xlookup,但是这种做法费时费力不说,效率还有些低下,特别是要查询的列数过多时。我放了3种查询方法,效果图&…...
Java中各种数组复制方式的效率对比
在 Java 中,数组复制是一个常见的操作,尤其是在处理动态数组(如 ArrayList)时。Java 提供了多种数组复制的方式,每种方式在性能和使用场景上都有所不同。以下是对几种主要数组复制方式的比较,包括 System.a…...
STM32 FLASHdb
FlashDB是一款超轻量级的嵌入式数据库,专注于为嵌入式产品提供数据存储方案。以下是对STM32 FlashDB的详细介绍: 一、主要特性 资源占用极低:FlashDB的内存占用几乎为0,非常适合资源有限的嵌入式系统。支持多分区、多实例&#…...
【漏洞复现】Struts2(CVE-2024-53677)任意文件上传逻辑绕过漏洞
文章目录 前言一、漏洞描述二、漏洞详情三、影响版本四、危害描述五、漏洞分析六、漏洞复现七、修复建议前言 Struts2框架是一个用于开发Java EE网络应用程序的开放源代码网页应用程序架构。它利用并延伸了Java Servlet API,鼓励开发者采用MVC架构。Struts2以WebWork优秀的设…...
图的最短路径(C++实现图【4】)
目录 1. 最短路径 1.1单源最短路径--Dijkstra算法 代码实现 1.2 单源最短路径--Bellman-Ford算法 代码实现 1.3 多源最短路径--Floyd-Warshall算法 代码实现 1. 最短路径 最短路径问题:从在带权有向图G中的某一顶点出发,找出一条通往另一顶点的最短路径&…...
Pandas01
文章目录 内容简介1 常用数据分析三方库2 Jupyter notebook3 Series的创建3.1 通过Numpy的Ndarray 创建一个Series3.2 通过列表创建Series 4 Series的属性和方法4.1 常用属性4.2 常用方法4.3 布尔值列表筛选部分数据4.4 Series 的运算 5 DataFrame的创建通过字典创建通过列表[元…...
opencl 封装简单api
这是cl代码 kernel.c __kernel void add_one(__global float *output,__global float* pnum) {int xget_global_id(0);output[x]pnum[0]; } c代码 #include <CL/cl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include<st…...
超快速的路径优化IKD-SWOpt:SHIFT Planner 中增量 KD 树滑动窗口优化算法详解
IKD-SWOpt:SHIFT Planner 中增量 KD 树滑动窗口优化算法详解 今天本博主王婆卖瓜自卖自夸😄,介绍自己paper中的算法,本算法已经持续开源中(部分关键内容)Github,之前很多读者朋友一直说要详细讲讲路径优化算法&#x…...
精读DeepSeek v3技术文档的心得感悟
最近宋大宝同学读完了DeepSeekv3的文档,心中颇多感慨,忍不住想在这里记录一下对这款“业界有望启示未来低精度训练走向”的开源大模型的观察与思考。DeepSeek v3的亮点绝不仅仅是“Float8”或“超长上下文”这么简单,而是贯穿了从数值精度、注…...
【Java数据结构】LinkedList与链表
认识LinkedList LinkedList就是一个链表,它也是实现List接口的一个类。LinkedList就是通过next引用将所有的结点链接起来,所以不需要数组。LinkedList也是以泛型的方法实现的,所以使用这个类都需要实例化对象。 链表分为很多种,比…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式
简介 在我的 QT/C 开发工作中,合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式:工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...
密码学基础——SM4算法
博客主页:christine-rr-CSDN博客 专栏主页:密码学 📌 【今日更新】📌 对称密码算法——SM4 目录 一、国密SM系列算法概述 二、SM4算法 2.1算法背景 2.2算法特点 2.3 基本部件 2.3.1 S盒 2.3.2 非线性变换 编辑…...
WEB3全栈开发——面试专业技能点P4数据库
一、mysql2 原生驱动及其连接机制 概念介绍 mysql2 是 Node.js 环境中广泛使用的 MySQL 客户端库,基于 mysql 库改进而来,具有更好的性能、Promise 支持、流式查询、二进制数据处理能力等。 主要特点: 支持 Promise / async-await…...
