SpringCloud 分布式链路追踪、分布式日志系统


 

概述

链路追踪的功能

  • 快速定位链路故障
  • 便于查看链路调用流程、服务依赖关系
  • 可分析链路耗时,针对耗时多的部分使用多线程、异步、缓存等方式进行优化
     

链路id

  • trace id:唯一标识一条链路行踪
  • span id:唯一标识一个http请求,对应分布式系统中一个环节

一条链路对应一个trace id,往往包含多个span id。

 

常见的APM (Application Performance Management 应用性能分析管理) 工具

  • ZipKin:twitter开源的组件,轻量、使用简单,但要侵入应用代码,功能单一,只能查看链路调用流程、各阶段的耗时情况。
  • SkyWalking:国人开源的组件,已成为apache孵化的项目,不但能做链路追踪,还能监控应用状态,功能丰富强大,部署稍复杂一些。如果要结合elk搭建分布式日志系统,会对应用代码有侵入。
  • PinPoint:韩国人开源的组件
  • Cat:大众点评开源的组件

skywalking对应用性能的影响最小,zipkin对应用性能的影响居中,如果只是分析链路耗时,优先选择轻量级的zipkin;如果要分析链路调用的更多详细信息,优先选择skywalking。

apm工具一般都支持多种数据存储方式,比如直接存储在内存中、定时清理,持久化到es、mysql、nosql数据库中。生产环境一般是持久化链路数据到es中。

 

Zipkin的使用

sleuth埋点、收集链路数据,zipkin传输、展示链路数据。

 

搭建zipkin server

jar包下载地址:https://zipkin.io/pages/quickstart.html

#链路数据直接存储在内存中
#nohup java -jar zipkin-server-2.23.2-exec.jar > zipkin-server.log &

#持久化链路数据到es,es集群有多个url时逗号分隔
STORAGE_TYPE=elasticsearch ES_HOSTS=http://127.0.0.1:9200 nohup java -jar zipkin-server-2.23.2-exec.jar > zipkin-server.log &

访问 ip:9411 即可进入zipkin界面。

在这里插入图片描述
存储作为数据源,UI请求数据源获取数据展示出来。

更多细节参考:https://github.com/openzipkin/zipkin/blob/master/zipkin-server/README.md

zipkin、skywalking都是通过ip:port访问界面,如果只是单机部署,可以直接开放端口访问;如果是集群部署,用nginx做代理。

 

zipkin dependencies

如果链路数据持久化存储,不能直接看到链路服务之间的调用关系,需要额外引入zipkin dependencies。

jar包下载地址:https://search.maven.org/search?q=g:io.zipkin.dependencies

也可去maven仓库下载。

#执行jar包
STORAGE_TYPE=elasticsearch ES_HOSTS=http://127.0.0.1:9200 nohup java -jar zipkin-dependencies-2.6.1.jar > zipkin-dependencies.log &

更多细节可参考:https://github.com/openzipkin/zipkin-dependencies

 

在服务中添加zipkin的相关配置

网关、消费者、提供者都可以作为zipkin client,注册中心不需要作为zipkin client,就算注册中心作为zipkin client,也只是单独的一条链路。

创建时勾选Spring Cloud Tracing -> Zipkin Client,也可以手动添加依赖

<!-- 不需要加这个 -->
<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>

<!--已经包含了spring-cloud-starter-sleuth,不需要再添加sleuth的依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
spring:
  zipkin:
    #zipkin服务器的地址,默认 http://localhost:9411/
    base-url: http://localhost:9411/
    #需不需要?
    #discovery-client-enabled: false  #不用开启服务发现
  sleuth:
    sampler:
      #采样率,0-1上的小数,0.5即50%,默认0.1
      probability: 1.0

注意:采样率对性能有影响,采样率越大越影响应用性能,生产环境采样率设置低些,测试可设置为1。

 

日志示例

[order-service,96f95a0dd81fe3ab,852ef4cfcdecabf3,false]
    
    第一个值,spring.application.name的值
    
    第二个值,96f95a0dd81fe3ab ,sleuth生成的一个ID,叫Trace ID,用来标识一条请求链路,一条请求链路中包含一个Trace ID,多个Span ID
    
    第三个值,852ef4cfcdecabf3、spanid 基本的工作单元,获取元数据,如发送一个http
    
    第四个值:false,是否要将该信息输出到zipkin服务中来收集和展示。

 

SkyWalking的使用

部署skywalking web

下载地址:http://skywalking.apache.org/downloads/

SkyWalking APM -> Distribution -> 选择合适版本的tar下载
 

#解压、重命名
tar -xzvf apache-skywalking-apm-es7-8.2.0.tar.gz

rm -I apache-skywalking-apm-es7-8.2.0.tar.gz

mv apache-skywalking-apm-es7 skywalking

cd skywalking

 
vim config/application.yml

#指定集群方式,默认standalone 单机版、不集群
cluster:
  selector: ${SW_CLUSTER:standalone}
  
#存储方式默认使用内存数据库h2,改为es7以持久化数据  
storage:
  selector: ${SW_STORAGE:elasticsearch7}

  #其它一般不用改,改nameSpace、clusterNodes即可
  elasticsearch7:
  	#索引前缀,索引中自动包含年月日
    nameSpace: ${SW_NAMESPACE:"skywalking"}
    #es集群节点
    clusterNodes: ${SW_STORAGE_ES_CLUSTER_NODES:localhost:9200}
    protocol: ${SW_STORAGE_ES_HTTP_PROTOCOL:"http"}
    #存储单位,默认1,以1天为单位进行存储,把一天的日志存储为一个单独的index
    dayStep: ${SW_STORAGE_DAY_STEP:1}
    #分片数量
    indexShardsNumber: ${SW_STORAGE_ES_INDEX_SHARDS_NUMBER:1}
    #副本数量
    indexReplicasNumber: ${SW_STORAGE_ES_INDEX_REPLICAS_NUMBER:1}
    #如果es设置了用户名、密码,需要在此处填写
    user: ${SW_ES_USER:""}
    password: ${SW_ES_PASSWORD:""}

如果 skywalking 8.3 修改application.yml后,保存时一直提示 文件已变化,无法保存修改的内容,可以换一个skywalking版本。
 

vim webapp/webapp.yml

server:
  #指定skywalking web使用的端口,默认8080
  port: 8080

collector:
  path: /graphql
  ribbon:
    ReadTimeout: 10000
    #指定链路数据的传送地址,有多个时逗号分隔,默认127.0.0.1:12800
    listOfServers: 127.0.0.1:12800

 

#启动skywalking web,实际会启动2个进程
bin/startup.sh

jps看到有OAPServerStartUp、skywalking-webapp.jar2个进程才算启动成功,并非看到2个successfully就是启动成功,如果只有一个进程,一般是 config/application.yml 中的配置不对。kill -9杀死2个进程即停止。

浏览器访问 skywalking web的 ip:port 即可进入skywalking的界面。

 

部署服务

每部署一个服务时,就拷贝一份skywalking的agent目录。不管是部署注册中心、网关、还是其它服务,都这么做。
 
编辑拷贝得到的agent的config/agent.config

#指定服务名称
agent.service_name=${SW_AGENT_NAME:eureka-server}

#每3s的采样率,0表示不采样,负数表示100%采样
agent.sample_n_per_3_secs=${SW_AGENT_SAMPLE:-1}

#指定链路数据的传送地址,默认127.0.0.1:11800
collector.backend_service=${SW_AGENT_COLLECTOR_BACKEND_SERVICES:127.0.0.1:11800}

 
agent的plugins目录是已启用的插件,optional-plugins目录中是可选的插件。

plugins中默认没有springcloud getway插件,不支持监控springcloud gateway网关服务。

如果当前要部署的服务是springcloud getway网关服务,需要把optional-plugins中的apm-spring-cloud-gateway-2.1.x-plugin-8.2.0.jar拷贝到plugins中。

其它需要插件支持的中间件和框架也是同理操作。
 

#部署服务,要换为对应的agent下skywalking-agent.jar的路径,-javaagent要在-jar之前
nohup java -javaagent:agent/skywalking-agent.jar -jar xxx.jar > xxx.log &

#如果使用外置tomcat部署,linux版tomcat需要修改bin/catalina.sh,在首行加上
CATALINA_OPTS="$CATALINA_OPTS -javaagent:agent/skywalking-agent.jar"; export CATALINA_OPTS

#win版tomcat需要修改bin/catalina.bat,在首行加上
set "CATALINA_OPTS=-javaagent:agent/skywalking-agent.jar"

 

应用日志中输出trace_id

在kibana中查看链路数据时,有trace_id字段,但服务输出的日志中没有trace_id。

可以在各个服务中添加如下配置,使应用输出的日志中包含trace_id,建议加上这些配置。

pom.xml

<dependency>
    <groupId>org.apache.skywalking</groupId>
    <artifactId>apm-toolkit-logback-1.x</artifactId>
    <version>8.3.0</version>
</dependency>

 
logback-spring.xml

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
        <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
        	<!-- %tid即trace_id -->
            <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%tid] [%thread] %-5level %logger{36} -%msg%n</Pattern>
        </layout>
    </encoder>
</appender>

 

分布式日志系统ELK

ELK(ElasticSearch Logstash Kibana),es用于存储日志,logstash将各节点的日志传输到es上,kibana对es中的日志进行查看、分析统计。

logstash是一个开源的日志收集引擎,可以实现日志的实时传输,可以从多个日志源读取日志,并进行过滤,传输到目的地。支持多种日志源,日志源可以是日志文件、数据库、统计表等,可读取系统日志、服务器日志、应用日志等。

 

logstash的安装部署

下载地址:https://www.elastic.co/cn/downloads/logstash

es、logstash、kibana的版本尽量保持一致。

#解压
tar -xzvf logstash-7.10.0-linux-x86_64.tar.gz
rm -I logstash-7.10.0-linux-x86_64.tar.gz
mv logstash-7.10.0 logstash

cd logstash

 
修改 config/jvm.options 中的堆内存设置

-Xms1g
-Xmx1g

 
config下新建文件 logstash.conf

input {
   file {
	   path => "/app/eureka-server.log"
	   #type指定es index中type字段的值
	   type => "eureka-server"
	   # start_position => "beginning"  #默认只读取实时输入,可以指定为从文件开始处读取
   }

   file {
	   path => "/app/getway.log"
	   type => "getway"
	}

   file {
	    path => "/app/user-server.log"
	    type => "user-server"
	}

   file {
	   path => "/app/order-server.log"
	   type => "order-server"
  }

}


#filter可选
filter {  

}


output {
   #stdout {}  #原样输出到控制台
   #stdout{codec => rubydebug}  #使用ruby库进行编解码
    
    #输出到es
    elasticsearch {
    	#值是字符串数组
		hosts => ["http://localhost:9200"]
		#index 默认值是"logstash-%{+YYYY.MM.dd}",可以自行指定,index美岑不允许包含大写字母
		#index => "mall-log-%{+YYYY.MM.dd}"
		#user => "xxx"
		#password => "xxx"
    }
}


  • input:指定输入,可包含多个输入。如果日志流量大,可以将日志传输到kafka,从kafka读取日志输入。
  • filter:对日志过滤处理,常见的插件比如 grok 匹配得到指定字段,常用来获取message中的日志打印时间、trace_id。
  • output:指定输出,一般为es、file。

三者都可以包含多个组件,logstash的config下有官方提供的配置模板logstash-sample.conf,可以照着写。

input、filter、output的插件使用可参考:https://www.elastic.co/guide/en/logstash/current/index.html
 

#启动logstash,-f指定配置文件位置。logstash.bat是win版用的
bin/logstash -f config/logstash.conf &

logstash也是java编写的,可以jps查看,kill -9终止。
 
logstash自带了jdk,在根目录下有个jdk的目录,但版本往往很新,一般不用。

logstash很吃资源,可以使用轻量级的 filebeat 代替。

 

kibana查看链路数据、日志

1、Management -> Stack Management -> Kibana -> Advanced Settings 设置预选项。这些预选项很有用,可以指定Date格式、时间段范围等。

2、在Index Patterns中指定的index匹配规则

3、Kibana -> Discover -> 选择上一步建立的index匹配规则 -> 查看、筛选document
 

链路数据可以根据 trace_id 字段进行筛选;日志可以根据message字段中的trace_id进行筛选,根据timestamp排序。trace_id可以在skywalking的web页面中复制。

es日志文档中自带了@timestamp字段,但这个只是logstash接受到日志的时间,并非应用打印日志的时间,根据@timestamp排序看到的日志记录顺序往往有一些出入。最好是在logstash的filter中用grok插件从message中获取时间,查看日志时先用trace_id筛选,再根据时间排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值