Skywalking使用与探针机制
對(duì)于 大型 幾十個(gè)、幾百個(gè)微服務(wù)構(gòu)成的微服務(wù)架構(gòu)系統(tǒng) 出現(xiàn)問(wèn)題無(wú)法快速定位、各個(gè)微服務(wù)之間的依賴(lài)關(guān)系理不清、各個(gè)微服務(wù)的接口性能很難分析、業(yè)務(wù)調(diào)用流程處理順序理不清
skywalking是一個(gè)國(guó)產(chǎn)開(kāi)源框架,2015年由吳晟開(kāi)源 , 2017年加入Apache孵化器。skywalking是分布式系統(tǒng)的應(yīng)用程序性能監(jiān)視工具,專(zhuān)為微服務(wù)、云原生架構(gòu)和基于容器(Docker、K8s、Mesos)架構(gòu)而設(shè)計(jì)。SkyWalking 是觀察性分析平臺(tái)和應(yīng)用性能管理系統(tǒng),提供分布式追蹤、服務(wù)網(wǎng)格遙測(cè)分析、度量聚合和可視化一體化解決方案。
官網(wǎng):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架構(gòu)的四個(gè)部分
上部分使用java的Agent機(jī)制從應(yīng)用中收集鏈路信息 發(fā)送給SkyWalking OAP服務(wù)器
下部分SkyWalking OAP 當(dāng)收到上部分發(fā)來(lái)的鏈路信息之后進(jìn)行分析 分析結(jié)果存到外部存儲(chǔ)器 以提供查詢(xún)
右部分Storage:Tracing數(shù)據(jù)存儲(chǔ),目前支持ES、MySQL、Sharding Sphere、TiDB、H2多種存儲(chǔ)器,目前采用較多的是ES,主要考慮是SkyWalking開(kāi)發(fā)團(tuán)隊(duì)自己的生產(chǎn)環(huán)境采用ES為主
左部分SkyWalking UI:負(fù)責(zé)提供控制臺(tái),查看鏈路等等
Agent機(jī)制 是jdk1.5提供的可以獲取jvm中的字節(jié)碼 然后對(duì)它進(jìn)行增強(qiáng)
在idea中使用Agent機(jī)制(探針機(jī)制)
給jvm傳參 javaagent: 傳入一個(gè)實(shí)現(xiàn)premain方法的jar 看下面代碼
Agent類(lèi) 加強(qiáng)類(lèi)
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); } }加強(qiáng)類(lèi)的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> 這個(gè)preamin會(huì)比main先運(yùn)行</manifestEntries></archive><skip>true</skip></configuration></plugin></plugins></build> </project>被加強(qiáng)類(lèi)
package com.am;public class AgentTest {public static void main(String[] args) {// TODO 啟動(dòng)服務(wù) 獲取進(jìn)程 memory jvm// Instrument 定位到UserService 統(tǒng)計(jì)方法執(zhí)行時(shí)間// 微服務(wù) 引入nacos pom jar ymlSystem.out.println("hello world");// TODO業(yè)務(wù)邏輯 UserService方法 統(tǒng)計(jì)方法執(zhí)行時(shí)間 } }被加強(qiáng)類(lèi)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>然后在被加強(qiáng)類(lèi)啟動(dòng)之前傳入jvm參數(shù)-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 所指的文件就是加強(qiáng)類(lèi)的jar 然后運(yùn)行被加強(qiáng)類(lèi)可以看到效果
以上是簡(jiǎn)單使用 下面加入了修改字節(jié)碼
加強(qiáng)類(lèi)
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:獲取方法調(diào)用時(shí)間");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()// 指定需要攔截的類(lèi).type(ElementMatchers.nameStartsWith("com.tuling")).transform(transformer).with(listener).installOn(inst); }}加強(qiáng)類(lèi)所用的
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 {// 原方法執(zhí)行return callable.call();} finally {System.out.println(method + ": cost " + (System.currentTimeMillis() - start) + "ms");} }}加強(qiáng)類(lèi)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>被加強(qiáng)類(lèi)
package com.am;public class AgentBytebuddyTest {public static void main(String[] args) {HelloService helloService = new HelloService();helloService.say();helloService.say2();} }被加強(qiáng)類(lèi)所用的
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"; }}被加強(qiáng)類(lèi)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機(jī)制 實(shí)現(xiàn)業(yè)務(wù)零侵入 打印jvm使用情況
加強(qiáng)類(lèi)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>加強(qiáng)類(lèi)
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內(nèi)存和GC信息Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {Metric.printMemoryInfo();Metric.printGCInfo();}}, 0, 5000, TimeUnit.MILLISECONDS); } }加強(qiáng)類(lèi)所用的 打印jvm使用情況實(shí)現(xiàn)
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 內(nèi)存以及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);} } }被加強(qiáng)類(lèi)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>被加強(qiáng)類(lèi)
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環(huán)境搭建
下載:http://skywalking.apache.org/downloads/
目錄結(jié)構(gòu):
搭建SkyWalking OAP 服務(wù)
先使用默認(rèn)的H2數(shù)據(jù)庫(kù)存儲(chǔ),不用修改配置
config/application.yml
使用vim指令進(jìn)入config/application.yml搜索storage 可以看到它的下一行是selector: ${SW_STORAGE:h2}
啟動(dòng)腳本 bin/startup.sh
日志信息存儲(chǔ)在logs目錄
啟動(dòng)成功后會(huì)啟動(dòng)兩個(gè)服務(wù),一個(gè)是skywalking-oap-server,一個(gè)是skywalking-web-ui
skywalking-oap-server服務(wù)啟動(dòng)后會(huì)暴露11800 和 12800 兩個(gè)端口,分別為收集監(jiān)控?cái)?shù)據(jù)的端口11800和接受前端請(qǐng)求的端口12800,修改端口可以修改config/applicaiton.yml
skywalking-web-ui服務(wù)會(huì)占用 8080 端口, 修改端口可以修改webapp/webapp.yml
Skywalking到這就搭建好了
然后使用
準(zhǔn)備一個(gè)springboot程序,打成可執(zhí)行jar包,寫(xiě)一個(gè)shell腳本,在啟動(dòng)項(xiàng)目的Shell腳本上,通過(guò) -javaagent 參數(shù)進(jìn)行配置SkyWalking Agent來(lái)跟蹤微服務(wù);
startup.sh腳本:
這樣啟動(dòng)之后 訪問(wèn)請(qǐng)求 就可以在Skywalking UI界面中查看到 多個(gè)微服務(wù) 只需要添加javaagent參數(shù)指定skywalking-agent.jar這個(gè)jar文件即可
在idea中使用 也是給jvm傳參
# skywalking-agent.jar的本地磁盤(pán)的路徑 -javaagent:D:\apache\apache-skywalking-apm-es7-8.4.0\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar # 在skywalking上顯示的服務(wù)名 -DSW_AGENT_NAME=springboot-skywalking-demo # skywalking的collector服務(wù)的IP及端口 -DSW_AGENT_COLLECTOR_BACKEND_SERVICES=192.168.3.100:11800自定義鏈路 就是可以讓Skywalking可以檢測(cè)到我們的業(yè)務(wù)代碼
導(dǎo)入依賴(lài)
<!-- SkyWalking 工具類(lèi) --> <dependency><groupId>org.apache.skywalking</groupId><artifactId>apm-toolkit-trace</artifactId><version>8.4.0</version> </dependency>在業(yè)務(wù)方法中可以TraceContext獲取到traceId
@RequestMapping("/list") public List<User> list(){//TraceContext可以得到Skywalking的上下文 下面的代碼時(shí)綁定一個(gè)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();會(huì)調(diào)用到下面的list 然后list方法加了@Trace注解 這樣Skywalking就可以把list方法加入到鏈路中 @Tag注解是用來(lái)把方法返回值寫(xiě)到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作為一個(gè)服務(wù)注冊(cè)到nacos上,只要skywalking oap服務(wù)沒(méi)有全部宕機(jī),保證有一個(gè)skywalking oap在運(yùn)行,就能進(jìn)行跟蹤。
搭建一個(gè)skywalking oap集群需要:
(1)至少一個(gè)Nacos(也可以是nacos集群)
(2)至少一個(gè)ElasticSearch(也可以是es集群)
(3)至少2個(gè)skywalking oap服務(wù);
(4)至少1個(gè)UI(UI也可以集群多個(gè),用Nginx代理統(tǒng)一入口)
1.修改config/application.yml文件
使用nacos作為注冊(cè)中心
修改nacos配置
修改存儲(chǔ)策略,使用elasticsearch7作為storage
修改elasticsearch7配置
配置ui服務(wù)webapp.yml文件的listOfServers,寫(xiě)兩個(gè)地址
listOfServers是OAP的地址
然后springboot應(yīng)用傳入的jvm參數(shù)的更改
-DSW_AGENT_COLLECTOR_BACKEND_SERVICES=192.168.3.10:11800,192.168.3.12:11800
總結(jié)
以上是生活随笔為你收集整理的Skywalking使用与探针机制的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: h.265不是视频压缩技术未来的5个原因
- 下一篇: 数字后端基本概念介绍Tie cell