- 简介
首先skywalking不仅仅是一个链路追踪系统,它其实是一款APM(应用性能管理)工具包括好多实用的功能:链路追踪、监控告警、性能诊断等,市面上主流的追踪平台包括zipkin、pinpoint等都是基于 google Dapper 论文的模型理论,其中skywalking和pinpoint是基于字节码植入实现,它能减少对业务侵入,zipkin和skywalking都遵循OpenTracing标准,有了标准,厂商和平台都去严格遵守,技术人员可以无缝切换,减少升级或改动成本。这个比较容易理解,举个例子:一段代码用openjdk和hotspot都能跑起来,因为底层他们都是遵循jvm规范进行的实现。 - 基本原理
1、架构组成
从整个架构图上看数据流向:client traceing->server reveiver->storage ->searchServer,客户端数据上报到服务端,经过简单聚合和加工,存储到相关设备,再有专门的查询控制台提供入口供使用者查询和分析,
2、数据采集
采用探针方式,做数据的收集,无论是Metrics、Tracing、还是Logging都会统一汇集到skywalking的receiver上,数据上报与应用共用一个jvm进程,上报通信的过程使用netty以grpc方式。skywalking提供了一系列的plugin,有专门针对jdbc和mysql、mq、spring、redis等,启动的时候以javaagent方式指定skywalking的agent,在应用启动之前做代码的增强,对各中间件或者组件做拦截(种入span和trace数据),只需要启动时指定:-javaagent:/Users/xxx/work/app/apache-skywalking-apm-bin/agent/skywalking-agent.jar
3、数据存储
支持多种类型的存储,mysql、ES、h2等,一般生产环境还是推荐使用ES,skywalking会启动独立的进程服务叫做OAPServerStartUp,接收agent端的上报数据,它做的事情:存储初始化包括创建索引和加载检查等,数据聚合以及上报数据的接收,如下是部分索引:
4、数据查询
skywalking会启动独立进程服务叫做webapp,可以方便使用者进行数据追踪和性能分析等等 - 实践心得
1、使用进阶
skywalking除了使用官方标准插件进行追踪和收集外,还可以自定义埋点,比如我不满足于目前的系统与系统之间、系统与组件/中间件之间的链路追踪,我还希望把某个函数或者某些service,也作为埋点和追踪的一环,那么我们可以自定义plugin,方式如下:
1.1.1、指定依赖<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>CusServicePlugin</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <properties> <skywalking.version>6.6.0</skywalking.version> <shade.package>org.apache.skywalking.apm.dependencies</shade.package> <shade.net.bytebuddy.source>net.bytebuddy</shade.net.bytebuddy.source> <shade.net.bytebuddy.target>${shade.package}.${shade.net.bytebuddy.source}</shade.net.bytebuddy.target> </properties> <dependencies> <dependency> <groupId>org.apache.skywalking</groupId> <artifactId>apm-agent-core</artifactId> <version>${skywalking.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.skywalking</groupId> <artifactId>apm-util</artifactId> <version>${skywalking.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.4</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.32</version> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-shade-plugin</artifactId> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <shadedArtifactAttached>false</shadedArtifactAttached> <createDependencyReducedPom>true</createDependencyReducedPom> <createSourcesJar>true</createSourcesJar> <shadeSourcesContent>true</shadeSourcesContent> <relocations> <relocation> <pattern>${shade.net.bytebuddy.source}</pattern> <shadedPattern>${shade.net.bytebuddy.target}</shadedPattern> </relocation> </relocations> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>6</source> <target>6</target> </configuration> </plugin> </plugins> </build> </project>
1.1.2、设置切入点-某类型的类、方法,继承
ClassInstanceMethodsEnhancePluginDefine
public class ServiceMethodInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { @Override protected ClassMatch enhanceClass() { String[] annos = new String[]{"org.springframework.stereotype.Service"}; System.out.println("xxxx:enhanceClass "); return ClassAnnotationMatch.byClassAnnotationMatch(annos); } @Override public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { return new ConstructorInterceptPoint[0]; } @Override public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() { @Override public ElementMatcher<MethodDescription> getMethodsMatcher() { //return ElementMatchers.any(); return named("getOrderByUser"); } @Override public String getMethodsInterceptor() { return "com.xx.sk.plugin.ServiceInterceptor";//该切入点的,切入逻辑实现类 } @Override public boolean isOverrideArgs() { return false; } }}; } }
1.1.3、指定拦截逻辑,继承InstanceMethodsAroundInterceptor
public class ServiceInterceptor implements InstanceMethodsAroundInterceptor { @Override public void beforeMethod(EnhancedInstance enhancedInstance, Method method, Object[] objects, Class<?>[] classes, MethodInterceptResult methodInterceptResult) throws Throwable { AbstractSpan span = ContextManager.createLocalSpan("service"); span.setComponent(ComponentsDefine.TOMCAT); String params = "NIL"; if(objects != null && objects.length > 0) { params = JSON.toJSONString(objects); } span.tag(new StringTag(1000, "params"),params); span.setLayer(SpanLayer.CACHE); } @Override public Object afterMethod(EnhancedInstance enhancedInstance, Method method, Object[] objects, Class<?>[] classes, Object o) throws Throwable { // String retString = "NIL"; // if(o != null) { // retString = JSON.toJSONString(o); // AbstractSpan span = ContextManager.activeSpan(); // Tags.STATUS_CODE.set(span, "1000"); // // ContextManager.stopSpan(); // } AbstractSpan span = ContextManager.activeSpan(); Tags.STATUS_CODE.set(span, "1000"); ContextManager.stopSpan(); return o; } @Override public void handleMethodException(EnhancedInstance enhancedInstance, Method method, Object[] objects, Class<?>[] classes, Throwable throwable) { } }
1.1.4、拷贝到skywalking的plugins内
2、追踪链路丢失问题
日志丢失,现象是系统日志中打印出了从A到B的调用日志,但是从skywalking的追踪查询页面,不能跟踪到这次调用;这个时候可以通过分析agent的dump信息,查看有异常’More than 300 spans required to create‘。
这个是skywalking的默认配置300;一个request对应一个trace,在这个请求中会出现多个服务依赖调用,用span表示一个跨组件或者服务的调用,大家更长用的叫法是’跨度‘,默认是300个大小的span,可以通过修改agent/config,将默认值改大,agent.span_limit_per_segment=${SW_AGENT_SPAN_LIMIT:300},但是对性能肯定会有影响,超过300以后,因为会自动trim,所以对性能是最友好的