- SkyWalking是基于javaagent的两大字节码操作 工具 之一的Byte Buddy实现的无侵入APM(application performance monitor) 系统,目前项目在Apache孵化器中,想了解SkyWalking和Byte Buddy源码的同学可在文章底部参考链接中,跳转至对应的官方资源。
- 本文会已通过Byte Buddy实现应用组件SpringMVC记录请求路径、入参、执行时间的javagent项目、持续迭代javaagent项目的方法论、SkyWalking agent在项目如何持续debug插件代码、以及SkyWalking插件开发实践的四个章节,让大家掌握SkyWalking的玩法,进而让SkyWalking在自己公司中的二次开发变得触手可及。
Byte Buddy实现
- 首先如果你对javaagent还不是很了解可以先百度一下,或在公众号内看下《JavaAgent原理与实践》简单入门下。SpringMVC分发请求的关键方法相信已经不用我在赘述了,让我们代码代码一把唆吧。
- 编写Byte Buddy javaagent代码
public class AgentMain { public static void premain(String agentOps, Instrumentation instrumentation) { new AgentBuilder.Default() .type(ElementMatchers.named("org.springframework.web.servlet.DispatcherServlet")) .transform((builder, type, classLoader, module) -> builder.method(ElementMatchers.named("doDispatch")) .intercept(MethodDelegation.to(DoDispatchInterceptor.class))) .installOn(instrumentation); } } 复制代码
- 编写DispatcherServlet doDispatch拦截器代码(是不是跟AOP如出一辙)
public class DoDispatchInterceptor { @RuntimeType public static Object intercept(@Argument(0) HttpServletRequest request, @SuperCall Callable<?> callable) { final StringBuilder in = new StringBuilder(); if (request.getParameterMap() != null && request.getParameterMap().size() > 0) { request.getParameterMap().keySet().forEach(key -> in.append("key=" + key + "_value=" + request.getParameter(key) + ",")); } long agentStart = System.currentTimeMillis(); try { return callable.call(); } catch (Exception e) { System.out.println("Exception :" + e.getMessage()); return null; } finally { System.out.println("path:" + request.getRequestURI() + " 入参:" + in + " 耗时:" + (System.currentTimeMillis() - agentStart)); } } } 复制代码
- 增加agent描述文件resources.META-INF.MANIFEST.MF
Manifest-Version: 1.0 Premain-Class: com.z.test.agent.AgentMain Can-Redefine-Classes: true 复制代码
- pom.xml文件
dependencies +net.bytebuddy.byte-buddy +javax.servlet.javax.servlet-api *scope=provided plugins +maven-jar-plugin *manifestFile=src/main/resources/META-INF/MANIFEST.MF +maven-shade-plugin *include:net.bytebuddy:byte-buddy:jar: +maven-compiler-plugin 复制代码
- 小结:没几十行代码就完成了通过Byte Buddy实现应用组件SpringMVC记录请求路径、入参、执行时间javagent项目,是不是觉得自己很优秀。
持续迭代javaagent
- 本小结主要介绍javaagen如何debug,以及持续集成。
- 首先我的javajagent项目目录结构如图所示:
- 应用项目是用几行代码实现的SpringBootWeb项目:
@SpringBootApplication(scanBasePackages = {"com"}) public class TestBootWeb { public static void main(String[] args) { SpringApplication.run(TestBootWeb.class, args); } @RestController public class ApiController { @PostMapping("/ping") public String ping(HttpServletRequest request) { return "pong"; } } } 复制代码
- 下面是关键javaagent项目如何持续迭代与集成:
VM options增加:-javaagent:/Users/zhao/Code/github/z_my_test/test-agent/target/test-agent-1.0-SNAPSHOT.jar=aaaaa Before launch 在Build之前增加: Working directory:/Users/zhao/Code/github/incubator-skywalking Command line:-T 1C -pl test-agent -am clean package -Denforcer.skip=true -Dmaven.test.skip=true -Dmaven.compile.fork=true 复制代码
- 详细配置见图片:
- 小结:看到这里的将javaagent持续迭代集成,是不是瞬间觉得自己手心已经发痒起来,很想唆一个自己的agent代码了呢,等等还有一个好消息:test-demo这10几行的代码实现的Web服务居然有5k左右的类可以使用agent增强,根据二八原则,一般的 程序员 至少熟悉1k左右的类,还不挑一个自己熟悉的类去挑战下?
- 注意mvn编译加速的命令是maven3+版本以上才支持的哈。
SkyWalking Debug
- 峰回路转,到了文章的主题SkyWalking之高级玩法的正文啦,其实通过了上面的铺垫,我想大家也或多或少已经知道我要说怎么SkyWalking怎么Debug了。所以我这里主要讲几个可以优化点,避免大家觉得没有新意,提前卖个关子,我的集成时间优化到30秒左右哈:
VM options增加:-javaagent:-javaagent:/Users/zhao/Code/github/incubator-skywalking/skywalking-agent/skywalking-agent.jar:不要用dist里面的skywalking-agent.jar,具体原因大家可以看看源码^_^ Before launch 在Build之前增加: Working directory:/Users/zhao/Code/github/incubator-skywalking Command line:-T 1C -pl apm-sniffer/apm-sdk-plugin -amd clean package -Denforcer.skip=true -Dmaven.test.skip=true -Dmaven.compile.fork=true: 这里我针对插件包,因为紧接着下文要开发插件 另外根pom注释maven-checkstyle-plugin也可加速编译 复制代码
- javaagent项目想debug,还需要将agent代码与接入agent项目至少在同一个工作空间内,网上方法有很多,这里我推荐大家一个最简单的方法。File->New->Module from Exisiting Sources...引入skywalking-agent源码即可
kob之SkyWalking插件编写
- kob(贝壳分布式作业调度框架)是贝壳找房项目微服务集群中的基础组件,通过编写贝壳分布式作业调度框架的SkyWalking插件,可以实时收集作业调度任务的执行链路信息,从而及时得到基础组件的稳定性,了解细节可点击阅读《 贝壳分布式调度框架简介 》。想详细了解SkyWalking插件编写可在文章底部参考链接中,跳转至对应的官方资源,好话不多说,代码一把唆起来。
- apm-sdk-plugin pom.xml增加自己的插件model
<artifactId>apm-sdk-plugin</artifactId> <modules> <module>kob-plugin</module> ... <modules> 复制代码
- resources.skywalking-plugin.def增加自己的描述
kob=org.apache.skywalking.apm.plugin.kob.KobInstrumentation 复制代码
- 编写方法instrumentation
public class KobInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { private static final String ENHANCE_CLASS = "com.ke.kob.client.spring.core.TaskDispatcher"; private static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.kob.KobInterceptor"; @Override protected ClassMatch enhanceClass() { return NameMatch.byName(ENHANCE_CLASS); } @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { return null; } @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { return new InstanceMethodsInterceptPoint[] { new InstanceMethodsInterceptPoint() { @Override public ElementMatcher<MethodDescription> getMethodsMatcher() { return named("dispatcher1"); } @Override public String getMethodsInterceptor() { return INTERCEPT_CLASS; } @Override public boolean isOverrideArgs() { return false; } } }; } } 复制代码
- 自定义interceptor实现span的创建
public class KobInterceptor implements InstanceMethodsAroundInterceptor { @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable { final ContextCarrier contextCarrier = new ContextCarrier(); com.ke.kob.client.spring.model.TaskContext context = (TaskContext) allArguments[0]; CarrierItem next = contextCarrier.items(); while (next.hasNext()) { next = next.next(); next.setHeadValue(JSON.toJSONString(context.getUserParam())); } AbstractSpan span = ContextManager.createEntrySpan("client:"+allArguments[1]+",task:"+context.getTaskKey(), contextCarrier); span.setComponent(ComponentsDefine.TRANSPORT_CLIENT); SpanLayer.asRPCFramework(span); } @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable { ContextManager.stopSpan(); return ret; } @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) { } } 复制代码
- 实现效果,将操作名改成任务执行节点+任务执行方法,实现kob的SkyWalking的插件编写,加上报警体系,可以进一步增加公司基础组件的稳定性。
参考链接
- Apache SkyWalking(an APM system) github.com/apache/incu…
- Byte Buddy(runtime code generation for the Java virtual machine) github.com/raphw/byte-…
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- jsonp劫持入门玩法
- 【译】2019 JavaScript 新玩法
- PHP异步的的玩法
- Github 新玩法 -- Profile ReadMe
- Vue-loader 的巧妙玩法
- Hexo 博客终极玩法:云端写作,自动部署
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。