详解最新链路追踪skywalking框架介绍、架构、环境本地部署&配置、整合微服务springcloudalibaba 、日志收集、自定义链路追踪、告警等

1.skywalking介绍

  • 多种监控手段,可以通过语言探针和service mesh 获得监控数据
  • 支持多种语言自动探针,包含java/net/nodejs
  • 轻量高效,无需大数据平台和大量的服务器资源
  • 模块化,UI、存储、集群管理都有多种机制可选
  • 支持告警
  • 优秀的可视化解决方案

整体架构

  • 上部分 Agent :负责从应用中收集链路信息,发送给SkyWalking OAP服务器,目前支持SkyWalking、Zikpin、Jaeger等提供的Tracing 数据信息。而目前采用的是SkyWalking Agent收集 SkyWalking Tracing数据,传递给服务器

  • 下部分SkyWalking OAP :负责接收Agent发送的Tracing数据信息,然后进行分析(Analysis Core) ,存储到外部存储器(Storage ),最终提供查询( Query )功能

  • 右部分 Storage :Tracing 数据存储。目前支持ES、MySQL、Sharding Sphere、TiDB、H2多种存储器,目前采用的是 ES ,主要考虑是 SkyWalking 开发团队自己的生产环境采用 ES 为主

  • 左部分 SkyWalking UI :负责提供控台,查看链路等等

skywalking demo

默认登录账户: skywalking skywalking

https://demo.skywalking.apache.org/

资料

官网:https://skywalking.apache.org/

下载 skywalking本地安装包:

https://skywalking.apache.org/downloads/

文档:https://skywalking.apache.org/docs/#SkyWalking

github: https://github.com/apache/skywalking

https://skywalking.apache.org/docs/main/latest/en/setup/backend/backend-setup/#applicationyml

  1. SkyWalking 环境搭建部署(单机版)


1.安装elasticSearch

  • 参考之前博文安装&启动

    elasticsearch.bat 或者elasticsearch.sh启动服务

  • 访问默认地址:http://localhost:9200/

2.搭建skywalking 服务

  • 下载skywalking 安装包

    对于 SkyWalking 的软件包,有两种方式获取:

    • 手动编译
    • 官方包 (建议官方包,bug少)
  • 修改 skywalking config目录application.yml配置

  • 修改skywalking 安装目录中的webapp目录中的webapp.yml配置

  • 启动skywalking server &webapp 执行如下命令:

    备注说明:如果启动有问题,可以查看日志

  • skywalking ui访问地址:

    默认 http://localhost:8080

    3.启动一个 Spring Boot 应用,并配置 SkyWalking Agent

首先,下载skywalking agent 包如下:


其次,启动探针

通过探针方式配置微服务链路追踪*

properties 复制代码
   java -javaagent:/path/to/skywalking-agent.jar \
     -Dskywalking.agent.service_name=order-service \
     -Dskywalking.collector.backend_service=localhost:11800 \
     -jar order-service.jar

linux启动

idea中配置探针

properties 复制代码
#设置skywalking-agent.jar路径
-javaagent:D:\resource\skywalking\skywalking-agent\skywalking-agent.jar
#在skywalking上显示微服务名称
-DSW_AGENT_NAME=wemedia-oss-user
#skywalking的collector服务的ip以及端口
-DSW_AGENT_COLLECTOR_BACKEND_SERVICES=localhost:11800

启动服务之后,调用服务api:http://127.0.0.1:8889/api/user/vipRecharge ,在skywalking ui上查看服务如下:

查看拓扑图如下:

发现拓扑图不显示gateway服务 ,分析这是skywalking的bug,解决方法:
到agent optional-plugins目录下 复制最新的gateway lib到agent plugins目录里

重启skywalking

重启微服务

重新访问接口微服务:http://127.0.0.1:8889/api/user/vipRecharge

再次访问skywalking ui:

3.skywalking 日志收集

  1. 引入skywalking日志收集依赖

    xml 复制代码
        <!--skywalking 日志收集,引入工具类-->
            <dependency>
                <groupId>org.apache.skywalking</groupId>
                <artifactId>apm-toolkit-logback-1.x</artifactId>
                <version>9.3.0</version>
            </dependency>
  2. 调整logback-spring.xml

    xml 复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <configuration scan="true" scanPeriod=" 5 seconds">
    
        <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径,请根据需求配置路径-->
        <springProperty scope="context" name="log.path" source="path.log"/>
        <springProperty scope="context" name="app.anme" source="spring.application.name"/>
    
        <property name="app.name" value="${app.anme}"/>
    
        <!-- 业务日志路径-->
        <property name="logging.path" value="${log.path}"/>
        <!-- 系统日志路径-->
        <property name="system.log" value="system"/>
        <!-- 日志保存时间(天) -->
        <property name="log.save.time.day" value="30"/>
    
    
        <!-- 彩色日志依赖的渲染类 -->
        <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
        <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
        <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
        <!-- 彩色日志格式 -->
        <property name="CONSOLE_LOG_PATTERN"
                  value="${app.name} >> ${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}]){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(LN:%L){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />
    
        <!-- 控制台输出 -->
        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
                <!--把控制台的日志输出到sKywalking-->
                <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
                    <pattern>${CONSOLE_LOG_PATTERN}</pattern>
                </layout>
                <!--            <pattern>${CONSOLE_LOG_PATTERN}</pattern>-->
                <charset>utf8</charset>
            </encoder>
        </appender>
    
    
        <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
            <discardingThreshold>0</discardingThreshold>
            <queueSize>1024</queueSize>
            <neverBlock>true</neverBlock>
            <appender-ref ref="STDOUT"/>
        </appender>
    
    
        <!--skywalking日志上报-->
        <appender name="grpc-log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
            <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
                <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
                    <pattern>${CONSOLE_LOG_PATTERN}</pattern>
                </layout>
                <charset>utf8</charset>
            </encoder>
        </appender>
    
    
        <!-- 按照每天生成日志文件 -->
        <appender name="FILE"  class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>${log.path}/sys-info.log</file>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!--日志文件输出的文件名-->
                <FileNamePattern>${log.path}/sys-info-%d{yyyy-MM-dd}.log</FileNamePattern>
                <!--日志文件保留天数-->
                <MaxHistory>${log.save.time.day}</MaxHistory>
            </rollingPolicy>
            <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
                <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
                    <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
                    <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern>
                </layout>
            </encoder>
        </appender>
    
        <!-- 系统错误日志 -->
        <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>${log.path}/sys-error.log</file>
            <!-- 循环政策:基于时间创建日志文件 -->
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!-- 日志文件名格式 -->
                <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
                <!-- 日志最大的历史 60天 -->
                <maxHistory>${log.save.time.day}</maxHistory>
            </rollingPolicy>
            <encoder>
                <pattern>${log.pattern}</pattern>
            </encoder>
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <!-- 过滤的级别 -->
                <level>ERROR</level>
                <!-- 匹配时的操作:接收(记录) -->
                <onMatch>ACCEPT</onMatch>
                <!-- 不匹配时的操作:拒绝(不记录) -->
                <onMismatch>DENY</onMismatch>
            </filter>
        </appender>
    
        <!-- 显示形成的sql、使用的参数、结果集 生产环境需要删掉 -->
        <logger name="java.sql" level="debug"/>
        <logger name="org.springframework.jdbc" level="debug"/>
    
        <!-- 日志输出级别  ,注意:如果不写<appender-ref ref="FILE" /> ,将导致springbootadmin找不到文件,无法查看日志 -->
        <root level="INFO">
            <appender-ref ref="grpc-log" />
            <appender-ref ref="ASYNC" />
            <appender-ref ref="FILE"/>
        </root>
    
    </configuration>

备注说明: [%X{tid}] :添加skywalking 追踪id,方便追踪整个调用链路

  1. 访问接口,查看skywalking ui log界面,日志正常显示如下:

4.skywalking 自定义链路追踪

  • 自定义链路追踪主要是为了对项目中的业务方法,实现链路追踪,方便排查问题

  • 引入依赖

    xml 复制代码
     <!--自定义skywalking链路,引入工具类-->
            <dependency>
                <groupId>org.apache.skywalking</groupId>
                <artifactId>apm-toolkit-trace</artifactId>
                <version>9.3.0</version>
            </dependency>
  • 自定义链路
    方法1:使用@Trace注解在要追踪的接口上,只需要记录方法的出参 ,入参;如果要打印返回结果,一定要重写返回结果toString()方法,不然返回对象的地址

​ 加入@Tags或@Tag记录参数和返回信息

​ @Tag注解中key= 方法名 value= returnedObj 返回值 arg[0] 参数

java 复制代码
/***
*controller方法
*/

@GetMapping("/vipRecharge")
    public CommonResult<String> vipReCharge() {

        userService.vipReCharge("123");
        return CommonResult.success("vip用户充值成功!");
    }


/***
* servrice方法
*/
 
   @Trace
   @Tags({@Tag(key = "vipReCharge",value = "returnedObj"),
   @Tag(key = "vipReCharge",value = "arg[0]")
   })
 @SentinelResource(value = "vipReCharge",blockHandler ="vipReChargeFallback" )
    @Override
    public CommonResult<String> vipReCharge(String num) {
        List<TUser> userList=tUserMapper.selectAll();
        System.out.println("userList:"+userList.size());
        CommonResult<String> result=payFeignApi.callWechatPay();
        System.out.println("调用第三方payFeignApi.callWechatPay 返回结果:"+result);
        return CommonResult.success("调用支付服务成功!");
    }

再次查看skywalking链路追踪trace,发现上面该方法已经被加载进链路中

增加Tags之后, 查看方法请求和返回值

方法2:编码的方式,适合逻辑比较多,多个地方需要记录一些参数或关键信息,info,debug 或堆栈日志等

使用skywalking 的 ActiveSpan.error(); ActiveSpan.info();ActiveSpan.debug()等在需要追踪的关键地方记录日志

java 复制代码
    @GetMapping("/callWechatPay")
    public CommonResult<String> callWechatPay(HttpServletRequest request) {
        log.info("X-Token value:"+request.getHeader("X-Token"));

        ActiveSpan.tag("PayController.callWechatPay()","调用支付controller中callWechatPay()方法!");


        try {
            //模拟异常情况:
            int i=10/0;
//            TimeUnit.SECONDS.sleep(2);
        } catch (Exception e) {
            //ActiveSpan.error();//skywalking追踪事件为error级别 或debug或info级别
           // ActiveSpan.error("是除零异常");//错误message
            ActiveSpan.error(new RuntimeException("是除零异常"));
           // throw new RuntimeException(e);
        }
        return CommonResult.success("调用微信支付成功!");
    }

再次查看skywalking ui结果如下:

方法3 使用OpenTracing Java API定义链路追踪

  1. 在pom文件中引入依赖

    xml 复制代码
     <dependency>
                <groupId>org.apache.skywalking</groupId>
                <artifactId>apm-toolkit-opentracing</artifactId>
                <version>9.3.0</version>
            </dependency>
  2. 在代码中增加自定义的链路追踪代码,最后一定要进行finish,否则也收集不到信息。

    java 复制代码
    //在service中增加自定义链路追踪代码 
    
    @Override
        public CommonResult<String> vipReCharge(String num) {
            //在代码中使用opentracing代码自定义链路追踪
            Tracer tracer=new SkywalkingTracer();
            Tracer.SpanBuilder spanBuilder=tracer.buildSpan("UserServiceImpl.vipRecharge(String num)方法");
            Span span=spanBuilder.withTag("startTag",false).startManual();
    
            List<TUser> userList=tUserMapper.selectAll();
            System.out.println("userList:"+userList.size());
            CommonResult<String> result=payFeignApi.callWechatPay();
            System.out.println("调用第三方payFeignApi.callWechatPay 返回结果:"+result);
            
            span.log("调用第三方payFeignApi.callWechatPay 返回结果:"+result);
            span.finish();
            return CommonResult.success("调用支付服务成功!");
        }
  3. 查看结果如下:

5.skywalking 告警

配置告警接口:

实现高级接口nofity或go-wechat

6.参考资料

相关推荐
胡子发芽4 分钟前
请解释Java中的NIO(New I/O)与传统I/O的区别,并说明NIO中的关键组件及其作用
java
柚个朵朵20 分钟前
IDEA中使用Git
java·git·spring
Lilith的AI学习日记34 分钟前
从LLM到AI Agent的技术演进路径:架构解析与实现逻辑
人工智能·架构
前端小臻1 小时前
后端开发三层架构
架构
jerry6091 小时前
优先队列、堆笔记(算法第四版)
java·笔记·算法
666HZ6661 小时前
关于IDEA的循环依赖问题
java·ide·intellij-idea
isfox1 小时前
与传统累加器对比,LongAdder 为何如此出众?
java
只因从未离去1 小时前
黑马Java基础笔记-4
java·开发语言·笔记
kurer2 小时前
Java通配符深入理解
java
会功夫的李白2 小时前
PDF嵌入隐藏的文字
java·pdf·itext