- 簡介
首先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,所以對性能是最友好的