java agent 实战 监控Elasticsearch(只需依赖一个jar 完全无侵入式)解决jar启动问题

这篇具有很好参考价值的文章主要介绍了java agent 实战 监控Elasticsearch(只需依赖一个jar 完全无侵入式)解决jar启动问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

需求背景

agent是什么大家应该很熟悉了,今天我们来实战下,效果就是为项目所有elasticsearch请求方法增加耗时告警!

学会Java Agent你能做什么?

  • 自动添加getter/setter方法的工具lombok就使用了这一技术
  • btrace、Arthas和housemd等动态诊断工具也是用了instrument技术
  • Intellij idea 的 HotSwap、Jrebel 等也是该技术的实现之一
  • pinpoint、skywalking、newrelic、听云的 APM 产品等都基于 Instrumentation 实现

使用方法

依赖maven

   <dependency>
		   	<groupId>com.uc.agent</groupId>
			<artifactId>neighbour-agent-elasticsearch-starter</artifactId>
			<version>0.0.56</version>
	</dependency>

到此我们的agent就已经集成了,不需要加任何启动参数,完全是无侵入式!!!!

解决了jar -jar方式启动的问题:

  • springboot自定义类加载器LaunchedURLClassLoader ,与agent的类加载器不同的冲突问题。
  • VirtualMachine绑定agent时,loadAgent方法找不到agentjar问题。
  • AgentLoader 加载之前 (agent动态绑定之前) 被JVM加载过的class是不会回调addTransformer方法的。 springboot扩展点和import方式导入的组件class优先AgentLoader 加载了,所以会造成agent拦截不到。
  • springboot本地可以,打包到线上jar启动方式agent无效等问题。

当es执行 search方法时,会自动打印方法耗时:

java agent 实战 监控Elasticsearch(只需依赖一个jar 完全无侵入式)解决jar启动问题,java,elasticsearch,jar

neighbour-agent-elasticsearch-starter 的下载地址 在github上面

https://github.com/HadLuo/neighbour-agent-elasticsearch-starter.git文章来源地址https://www.toymoban.com/news/detail-595122.html

下面我们看下简单的agent使用,但是没有解决上面 jar启动的问题,要了解实现请下载源码!!!

开场实例:

比如我们业务代码的网络请求框架代码(模拟):

public class HttpClient {

	public void post() {
		System.out.println("HttpClient pos 请求");
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

我们要实现的就是监听当网络请求超过1秒就钉钉告警出来。比如:

java agent 实战 监控Elasticsearch(只需依赖一个jar 完全无侵入式)解决jar启动问题,java,elasticsearch,jar

实现过程

AgentLoader

我们先实现一个AgentLoader 用来加载agent:

@Configuration
public class AgentLoader implements InitializingBean{
	@Override
	public void afterPropertiesSet() throws Exception {
		  // 动态获取SpringBoot启动类名称
                StartAppClassName = getMainClassName();
		// 加载agent jar包 得到路径
		File file = FileLoads.loadFile("agent-client-0.0.1-SNAPSHOT-jar-with-dependencies.jar");
		String jar = file.getAbsolutePath();
		try {
			for (VirtualMachineDescriptor virtualMachineDescriptor : VirtualMachine.list()) {
				// 针对指定名称的JVM实例
				if (virtualMachineDescriptor.displayName().equals(StartAppClassName)) {
					System.out.println(
							"将对该进程的vm进行增强:org.example.agent.AgentTest的vm进程, pid=" + virtualMachineDescriptor.id());
					// attach到新JVM
					VirtualMachine vm = VirtualMachine.attach(virtualMachineDescriptor);
					// 加载agentmain所在的jar包
					vm.loadAgent(jar);
					// detach
					vm.detach();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}    

当前放到SpringBoot初始化 Import 这个类 加载就行。

agent-client-0.0.1-SNAPSHOT-jar-with-dependencies.jar 为下面要制作的 agent jar名称,需要放到项目的resource目录下。

这里我们其实就是用到了agent的动态绑定方式去绑定。

agent jar制作:

agentmain方法:

JDK 1.6 引入了新的 agentmain 用于支持在类加载后再次加载该类,也就是重定义类,在重定义的时候可以修改类。但是这种方式对类的修改有较大的限制,修改后的类要兼容原来的旧类,具体的要求在 Java 官方文档 Instrumentation#retransformClasses()方法介绍 中可以找到: 转换类时禁止添加、删除、重命名成员变量和方法,禁止修改方法的签名,禁止改变类的继承关系。

public static void agentmain(String args, Instrumentation instrumentation) {
		instrumentation.addTransformer(new ClassFileTransformer() {
			public byte[] transform(ClassLoader l, String className, Class<?> c, ProtectionDomain pd, byte[] b) {
				try {
					if (className == null) {
						return null;
					}
//					System.err.println(className);
					className = className.replace("/", ".");
					if (className.equals("com.uc.riskcontroller.trace.HttpClient")) {
						final ClassPool classPool = ClassPool.getDefault();
						final CtClass clazz = classPool.get("com.uc.riskcontroller.trace.HttpClient");
						for (CtMethod method : clazz.getMethods()) {
							if (Modifier.isNative(method.getModifiers())) {
								continue;
							}
							method.addLocalVariable("s", classPool.get("long"));
							method.insertBefore("s = System.currentTimeMillis();");
							method.insertAfter("System.out.println(System.currentTimeMillis() - s);", false);
							method.insertAfter("com.uc.framework.alert.AlertContext.robot(com.uc.framework.env.EnvironmentServer.UnkownExceptionWebwork).alert(\"http客户端请求耗时:\" + (System.currentTimeMillis() - s ));", false);
						}

						return clazz.toBytecode();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				return null;
			}
		}, true);
		Class<?>[] classes = instrumentation.getAllLoadedClasses();
		if (classes != null) {
			for (Class<?> c : classes) {
				if (c.isInterface() || c.isAnnotation() || c.isArray() || c.isEnum()) {
					continue;
				}
				if (c.getName().equals("com.uc.riskcontroller.trace.HttpClient")) {
					try {
						System.out.println("retransformClasses start, class: " + c.getName());
						instrumentation.retransformClasses(c);
						System.out.println("retransformClasses end, class: " + c.getName());
					} catch (UnmodifiableClassException e) {
						System.out.println("retransformClasses error, class: " + c.getName() + ", ex:" + e);
						e.printStackTrace();
					}
				}
			}
		}
	}

核心就在于Instrumentation的两个方法:

void addTransformer(ClassFileTransformer transformer, boolean canRetransform);

 void retransformClasses(Class<?>... classes) throws UnmodifiableClassException;
  • addTransformer()用来注册类的修改器;JVM每装载一个类,transform 都会被回调执行。
  • retransformClasses()会让类重新加载,从而使得注册的类修改器能够重新修改类的字节码。

在利用javaassit进行字节码修改,达到了增加耗时告警目的。

到此我们实例已经制作完毕。

但是上面会有一个问题,在线上 我们用jar -jar 启动时,会有各种问题, 但是在文章的前面实现的案例都已经解决了,需要读者自行下载。

下载地址在github上面

https://github.com/HadLuo/neighbour-agent-elasticsearch-starter.git

到了这里,关于java agent 实战 监控Elasticsearch(只需依赖一个jar 完全无侵入式)解决jar启动问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • flume系列之:监控Systemctl托管的flume agent组

    flume接kafka集群,一个kafka集群对应一个flume agent组,会把一组flume agent用systemctl托管 每接一个kafka集群会自动化部署一组flume agent 现在对每个flume agent组设置监控,确保所有的flume agent组都处于运行状态 不在运行中的flume agent组发出告警信息或者自动拉起服务 flume系列之:监控

    2024年02月13日
    浏览(32)
  • Zabbix6 通过zabbix-agent2监控MySQL

         Zabbix6 自带mysql模版,无须再使用第三方,也不用自己写监控脚本,而且zabbix-agent2比zabbix-agent,功能更强大,应用也更简单。 1、登录要被监控的mysql, 创建监控用户 2、登录Zabbix Server WEB,【配置】--【模版】- 【MySQL by Zabbix agent 2】,修改此【宏】 3、【配置】-【主机】

    2024年02月11日
    浏览(55)
  • 【python】只需一段代码,剪辑一个视频——Moviepy详解

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 知道吗,用moviepy一行代码就能够快速剪辑视频中某个区间的片段: clip = VideoFileClip(“videoplayback.mp4”).subclip(50,60) 这一段代码,能够在3秒内将videoplayback.mp4的50秒-60秒的视频片段提取出来,非常方便。

    2023年04月16日
    浏览(41)
  • 只需三步,教你搭建一个进销存管理系统!

    如果你常常面临: 进销存软件功能不全、功能冗余、价格昂贵,性价比不高的情况—— 可以考虑使用【零代码搭建】了! 在简道云可以根据自身需求快速搭建出进销存管理系统。相比较其他标准进销存软件,用简道云搭建进销存具备以下优势: 功能灵活: 可以对进销存模

    2024年02月06日
    浏览(78)
  • 安装及配置zabbix_agent代理端(监控FTP服务器)

    监控agent的linux主机我们在之前的文章里已经做好了 现在直接安装ftp服务即可             监控成功

    2024年02月16日
    浏览(41)
  • Java实战场景下的ElasticSearch

    ES官方提供了各种不同语言的客户端 ,用来操作ES。这些客户端的本质就是组装DSL语句,通过http请求发送给ES,其中的Java Rest Client又包括两种: Java Low Level Rest Client Java High Level Rest Client 本文介绍的是Java HighLevel Rest Client客户端API; 在elasticsearch提供的API中,与elasticsearch一切交

    2024年02月11日
    浏览(37)
  • 狂收 3K Star!一个高性能、无侵入的 Java 性能监控和统计工具,十分强悍!

    随着所在公司的发展,应用服务的规模不断扩大,原有的垂直应用架构已无法满足产品的发展,几十个工程师在一个项目里并行开发不同的功能,开发效率不断降低。 于是公司开始全面推进服务化进程,把团队内的大部分工程师主要精力全部都集中到服务化中。服务化可以让

    2024年02月11日
    浏览(57)
  • Java实战:SpringBoot+ElasticSearch 实现模糊查询

    本文将详细介绍如何使用SpringBoot整合ElasticSearch,实现模糊查询、批量CRUD、排序、分页和高亮功能。我们将深入探讨ElasticSearch的相关概念和技术细节,以及如何使用SpringData Elasticsearch库简化开发过程。 ElasticSearch是一个基于Lucene构建的开源搜索引擎,它提供了一个分布式、多

    2024年04月25日
    浏览(36)
  • Langchain+ElasticSearch+文心千帆 构建检索增强LLM Agent

    很早就开始做检索增强的大语言模型Agent了,通过外接知识库为LLM提供外部知识能增强它回答的准确性。这里我们使用ElasticSearch作为数据库存储相关知识,使用百度文心千帆的embedding API提供向量嵌入;借助langchain搭建LLM Agent. 需要安装的环境有: Python, ElasticSearch, langchain, q

    2024年02月04日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包