Skywalking使用与探针机制
對于 大型 幾十個、幾百個微服務構成的微服務架構系統 出現問題無法快速定位、各個微服務之間的依賴關系理不清、各個微服務的接口性能很難分析、業務調用流程處理順序理不清
skywalking是一個國產開源框架,2015年由吳晟開源 , 2017年加入Apache孵化器。skywalking是分布式系統的應用程序性能監視工具,專為微服務、云原生架構和基于容器(Docker、K8s、Mesos)架構而設計。SkyWalking 是觀察性分析平臺和應用性能管理系統,提供分布式追蹤、服務網格遙測分析、度量聚合和可視化一體化解決方案。
官網:http://skywalking.apache.org/
下載:http://skywalking.apache.org/downloads/
Github:https://github.com/apache/skywalking
文檔: https://skywalking.apache.org/docs/main/v8.4.0/readme/
中文文檔: https://skyapm.github.io/document-cn-translation-of-skywalking/
Skywalking架構的四個部分
上部分使用java的Agent機制從應用中收集鏈路信息 發送給SkyWalking OAP服務器
下部分SkyWalking OAP 當收到上部分發來的鏈路信息之后進行分析 分析結果存到外部存儲器 以提供查詢
右部分Storage:Tracing數據存儲,目前支持ES、MySQL、Sharding Sphere、TiDB、H2多種存儲器,目前采用較多的是ES,主要考慮是SkyWalking開發團隊自己的生產環境采用ES為主
左部分SkyWalking UI:負責提供控制臺,查看鏈路等等
Agent機制 是jdk1.5提供的可以獲取jvm中的字節碼 然后對它進行增強
在idea中使用Agent機制(探針機制)
給jvm傳參 javaagent: 傳入一個實現premain方法的jar 看下面代碼
Agent類 加強類
package bat.ke.qq.com;import java.lang.instrument.Instrumentation;public class AmAgent {public static void premain(String args, Instrumentation instrumentation){System.out.println("premain:" + args); } }加強類的pom
<?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"><parent><artifactId>trace-agent</artifactId><groupId>bat.ke.qq.com</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>agent-demo</artifactId><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>2.2</version><configuration><archive><manifestEntries><Project-name>${project.name}</Project-name><Project-version>${project.version}</Project-version><Premain-Class>bat.ke.qq.com.AmAgent</Premain-Class> // 這里指定<Premain-Class> 這個preamin會比main先運行</manifestEntries></archive><skip>true</skip></configuration></plugin></plugins></build> </project>被加強類
package com.am;public class AgentTest {public static void main(String[] args) {// TODO 啟動服務 獲取進程 memory jvm// Instrument 定位到UserService 統計方法執行時間// 微服務 引入nacos pom jar ymlSystem.out.println("hello world");// TODO業務邏輯 UserService方法 統計方法執行時間 } }被加強類pom
<?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"><parent><artifactId>trace-agent</artifactId><groupId>bat.ke.qq.com</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>agent-demo2</artifactId><dependencies></dependencies> </project>然后在被加強類啟動之前傳入jvm參數-javaagent:D:\2021java代碼存放地\Skywalking\agent-demo\target\agent-demo-1.0-SNAPSHOT.jar=name=123
D:\2021java代碼存放地\Skywalking\agent-demo\target\agent-demo-1.0-SNAPSHOT.jar 所指的文件就是加強類的jar 然后運行被加強類可以看到效果
以上是簡單使用 下面加入了修改字節碼
加強類
package com.am;import net.bytebuddy.agent.builder.AgentBuilder; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.implementation.MethodDelegation; import net.bytebuddy.matcher.ElementMatchers; import net.bytebuddy.utility.JavaModule;import java.lang.instrument.Instrumentation;public class FoxAgent {public static void premain(String agentArgs, Instrumentation inst) {System.out.println("premain:獲取方法調用時間");AgentBuilder.Transformer transformer = new AgentBuilder.Transformer() {@Overridepublic DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,TypeDescription typeDescription,ClassLoader classLoader) {return builder// 攔截任意方法.method(ElementMatchers.<MethodDescription>any())// 指定方法攔截器,此攔截器中做具體的操作.intercept(MethodDelegation.to(TimeInterceptor.class));}};AgentBuilder.Listener listener = new AgentBuilder.Listener() {@Overridepublic void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, DynamicType dynamicType) {}@Overridepublic void onIgnored(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) { }@Overridepublic void onError(String typeName, ClassLoader classLoader, JavaModule module, Throwable throwable) { }@Overridepublic void onComplete(String typeName, ClassLoader classLoader, JavaModule module) { }};new AgentBuilder.Default()// 指定需要攔截的類.type(ElementMatchers.nameStartsWith("com.tuling")).transform(transformer).with(listener).installOn(inst); }}加強類所用的
package com.am;import net.bytebuddy.implementation.bind.annotation.Origin; import net.bytebuddy.implementation.bind.annotation.RuntimeType; import net.bytebuddy.implementation.bind.annotation.SuperCall;import java.lang.reflect.Method; import java.util.concurrent.Callable;public class TimeInterceptor {@RuntimeType public static Object intercept(@Origin Method method,@SuperCall Callable<?> callable) throws Exception {long start = System.currentTimeMillis();try {// 原方法執行return callable.call();} finally {System.out.println(method + ": cost " + (System.currentTimeMillis() - start) + "ms");} }}加強類pom
<?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"><parent><artifactId>trace-agent</artifactId><groupId>bat.ke.qq.com</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>bytebuddy-demo</artifactId><dependencies><dependency><groupId>javassist</groupId><artifactId>javassist</artifactId><version>3.12.1.GA</version><type>jar</type></dependency><dependency><groupId>net.bytebuddy</groupId><artifactId>byte-buddy</artifactId><version>1.5.13</version></dependency><dependency><groupId>net.bytebuddy</groupId><artifactId>byte-buddy-agent</artifactId><version>1.5.13</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>2.2</version><configuration><archive><manifestEntries><Project-name>${project.name}</Project-name><Project-version>${project.version}</Project-version><Premain-Class>com.tuling.FoxAgent</Premain-Class></manifestEntries></archive><skip>true</skip></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><executions><execution><phase>package</phase><goals><goal>shade</goal></goals></execution></executions><configuration><artifactSet><includes><include>javassist:javassist:jar:</include><include>net.bytebuddy:byte-buddy:jar:</include><include>net.bytebuddy:byte-buddy-agent:jar:</include></includes></artifactSet></configuration></plugin></plugins></build> </project>被加強類
package com.am;public class AgentBytebuddyTest {public static void main(String[] args) {HelloService helloService = new HelloService();helloService.say();helloService.say2();} }被加強類所用的
package com.am;public class HelloService {public String say(){System.out.println("===hello world====");return "hello world"; }public String say2(){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return "hello world"; }}被加強類pom
<?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"><parent><artifactId>trace-agent</artifactId><groupId>bat.ke.qq.com</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>bytebuddy-demo2</artifactId></project>利用agent機制 實現業務零侵入 打印jvm使用情況
加強類pom
<?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"><parent><artifactId>trace-agent</artifactId><groupId>bat.ke.qq.com</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>Metric-tool</artifactId><dependencies><dependency><groupId>javassist</groupId><artifactId>javassist</artifactId><version>3.12.1.GA</version><type>jar</type></dependency> </dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>2.2</version><configuration><archive><manifestEntries><Project-name>${project.name}</Project-name><Project-version>${project.version}</Project-version><Premain-Class>com.tuling.FoxAgent</Premain-Class></manifestEntries></archive><skip>true</skip></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><executions><execution><phase>package</phase><goals><goal>shade</goal></goals></execution></executions><configuration><artifactSet><includes><include>javassist:javassist:jar:</include></includes></artifactSet></configuration></plugin></plugins> </build> </project>加強類
package com.am;import java.lang.instrument.Instrumentation; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit;public class AmAgent {public static void premain(String agentArgs, Instrumentation inst) {//每隔5秒打印JVM內存和GC信息Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {Metric.printMemoryInfo();Metric.printGCInfo();}}, 0, 5000, TimeUnit.MILLISECONDS); } }加強類所用的 打印jvm使用情況實現
package com.am;import java.lang.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.MemoryUsage; import java.util.Arrays; import java.util.List;/**** 獲取JVM 內存以及GC信息**/ public class Metric { private static final long MB = 1048576L;public static void printMemoryInfo() {MemoryMXBean memory = ManagementFactory.getMemoryMXBean();MemoryUsage headMemory = memory.getHeapMemoryUsage();String info = String.format("\nHeapMemory init: %s\t max: %s\t used: %s\t committed: %s\t use rate: %s\n",headMemory.getInit() / MB + "MB",headMemory.getMax() / MB + "MB", headMemory.getUsed() / MB + "MB",headMemory.getCommitted() / MB + "MB",headMemory.getUsed() * 100 / headMemory.getCommitted() + "%");System.out.print(info);MemoryUsage nonheadMemory = memory.getNonHeapMemoryUsage();info = String.format("NonHeapMemory init: %s\t max: %s\t used: %s\t committed: %s\t use rate: %s\n",nonheadMemory.getInit() / MB + "MB",nonheadMemory.getMax() / MB + "MB", nonheadMemory.getUsed() / MB + "MB",nonheadMemory.getCommitted() / MB + "MB",nonheadMemory.getUsed() * 100 / nonheadMemory.getCommitted() + "%");System.out.println(info); }public static void printGCInfo() {List<GarbageCollectorMXBean> garbages = ManagementFactory.getGarbageCollectorMXBeans();for (GarbageCollectorMXBean garbage : garbages) {String info = String.format("name: %s\t count:%s\t took:%s\t pool name:%s",garbage.getName(),garbage.getCollectionCount(),garbage.getCollectionTime(),Arrays.deepToString(garbage.getMemoryPoolNames()));System.out.println(info);} } }被加強類pom
<?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"><parent><artifactId>trace-agent</artifactId><groupId>bat.ke.qq.com</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>Metric-tool-demo</artifactId></project>被加強類
package com.am;import java.util.ArrayList; import java.util.List;public class MetricToolAgentTest {public static void main(String[] args) {boolean flag = true;while (flag) {List<Object> list = new ArrayList<Object>();list.add("Hello World");}}}SkyWalking環境搭建
下載:http://skywalking.apache.org/downloads/
目錄結構:
搭建SkyWalking OAP 服務
先使用默認的H2數據庫存儲,不用修改配置
config/application.yml
使用vim指令進入config/application.yml搜索storage 可以看到它的下一行是selector: ${SW_STORAGE:h2}
啟動腳本 bin/startup.sh
日志信息存儲在logs目錄
啟動成功后會啟動兩個服務,一個是skywalking-oap-server,一個是skywalking-web-ui
skywalking-oap-server服務啟動后會暴露11800 和 12800 兩個端口,分別為收集監控數據的端口11800和接受前端請求的端口12800,修改端口可以修改config/applicaiton.yml
skywalking-web-ui服務會占用 8080 端口, 修改端口可以修改webapp/webapp.yml
Skywalking到這就搭建好了
然后使用
準備一個springboot程序,打成可執行jar包,寫一個shell腳本,在啟動項目的Shell腳本上,通過 -javaagent 參數進行配置SkyWalking Agent來跟蹤微服務;
startup.sh腳本:
這樣啟動之后 訪問請求 就可以在Skywalking UI界面中查看到 多個微服務 只需要添加javaagent參數指定skywalking-agent.jar這個jar文件即可
在idea中使用 也是給jvm傳參
# skywalking-agent.jar的本地磁盤的路徑 -javaagent:D:\apache\apache-skywalking-apm-es7-8.4.0\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar # 在skywalking上顯示的服務名 -DSW_AGENT_NAME=springboot-skywalking-demo # skywalking的collector服務的IP及端口 -DSW_AGENT_COLLECTOR_BACKEND_SERVICES=192.168.3.100:11800自定義鏈路 就是可以讓Skywalking可以檢測到我們的業務代碼
導入依賴
<!-- SkyWalking 工具類 --> <dependency><groupId>org.apache.skywalking</groupId><artifactId>apm-toolkit-trace</artifactId><version>8.4.0</version> </dependency>在業務方法中可以TraceContext獲取到traceId
@RequestMapping("/list") public List<User> list(){//TraceContext可以得到Skywalking的上下文 下面的代碼時綁定一個key-valueTraceContext.putCorrelation("name", "fox");Optional<String> op = TraceContext.getCorrelation("name");log.info("name = {} ", op.get());//獲取跟蹤的traceIdString traceId = TraceContext.traceId();log.info("traceId = {} ", traceId);return userService.list(); }userService.list();會調用到下面的list 然后list方法加了@Trace注解 這樣Skywalking就可以把list方法加入到鏈路中 @Tag注解是用來把方法返回值寫到SKywalking中
@Trace @Tag(key = "list", value = "returnedObj") public List<User> list(){return userMapper.list(); }@Trace @Tags({@Tag(key = "param", value = "arg[0]"),@Tag(key = "user", value = "returnedObj")}) public User getById(Integer id){return userMapper.getById(id); }日志集成
logback官方配置 https://github.com/apache/skywalking/blob/master/docs/en/setup/service-agent/java-agent/Application-toolkit-logback-1.x.md
log4j官方配置 https://skywalking.apache.org/docs/main/v8.4.0/en/setup/service-agent/java-agent/application-toolkit-log4j-1.x/
log4j2j官方配置 https://skywalking.apache.org/docs/main/v8.4.0/en/setup/service-agent/java-agent/application-toolkit-log4j-2.x
Skywalking集群部署
Skywalking集群是將skywalking oap作為一個服務注冊到nacos上,只要skywalking oap服務沒有全部宕機,保證有一個skywalking oap在運行,就能進行跟蹤。
搭建一個skywalking oap集群需要:
(1)至少一個Nacos(也可以是nacos集群)
(2)至少一個ElasticSearch(也可以是es集群)
(3)至少2個skywalking oap服務;
(4)至少1個UI(UI也可以集群多個,用Nginx代理統一入口)
1.修改config/application.yml文件
使用nacos作為注冊中心
修改nacos配置
修改存儲策略,使用elasticsearch7作為storage
修改elasticsearch7配置
配置ui服務webapp.yml文件的listOfServers,寫兩個地址
listOfServers是OAP的地址
然后springboot應用傳入的jvm參數的更改
-DSW_AGENT_COLLECTOR_BACKEND_SERVICES=192.168.3.10:11800,192.168.3.12:11800
總結
以上是生活随笔為你收集整理的Skywalking使用与探针机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: h.265不是视频压缩技术未来的5个原因
- 下一篇: 数字后端基本概念介绍Tie cell