简介
skywalking又称应用程序性能管理(APM)工具,它和日志管理工具都具有相同的底线目标:它们可以帮助你更深入地了解应用程序中正在发生的事情。尽管目标相似,但执行方式却不同,并且每个目标都专注于应用程序中的不同方面。
APM工具提供有关应用程序性能的分析。这些分析可以包括执行代码中不同elements所花费的时间,完成某些事务所需的时间等等。
这些工具还使我们能够监视生产环境,应用程序负载(事务,请求和每秒的页面数),计算响应时间以及可能导致延迟响应的总体方向。 。
组件对比
首先有必要说明一下为什么使用skywalking。
针对zipkin
、cat
和skywalking
这几个较为主流的监控产品做了一些调研和对比,整理以后情况汇总如下表:
项目 | Cat | Zipkin | Skywalking |
---|---|---|---|
调用链可视化 | 有 | 有 | 有 |
聚合报表 | 非常丰富 | 少 | 较丰富 |
服务依赖图 | 简单 | 简单 | 好 |
埋点方式 | 侵入式 | 侵入式 | 非侵入,字节码增强 |
VM监控指标 | 好 | 无 | 有 |
支持语言 | java/.net | 丰富 | java/.net/Nodejs/php/go |
存储机制 | mysql(报表)、本地文件/HDFS(调用链) | 内存、es、mysql等 | H2、es、mysql等 |
社区支持 | 主要在国内 | 国外主流 | Apache支持 |
使用案例 | 美团、携程、陆金所 | 京东、阿里定制后不开源 | 华为、小米、当当、微众银行 |
APM | 是 | 否 | 是 |
开发基础 | eBay cal | Google Dapper | Google Dapper |
是否支持webflux | 否 | 是 | 是 |
根据上表说一下为什么我选择用Skywalking
,主要理由有以下几点:
我的微服务体系选用的服务网关是spring-cloud-gateway,是基于webflux实现的,很多监控并不支持,从资料来看
cat
不支持;我想要监控接口级别的指标,如吞吐量、p99等,这些是目前
zipkin
不足的地方,而Skywalking
这方面做得不错;Skywalking是非侵入式的,通过-javaagent机制运行时注入,即使以后更换监控方案也不需要对代码大动干戈。
架构
我使用的是最新版8.7.0,该版本下Skywalking主要分为oap、webapp和agent三部分,oap和webapp分别用于汇总数据和展示,这两块共同组成了Skywalking的平台;agent是探针,部署在需要收集数据的应用服务器上,并将数据同步到Skywalking的平台。数据持久化方案笔者选用了elasticsearch 6.8.0。
数据持久化
Skywalking提供了多种数据持久化的方案,常见的大致分为:
elasticsearch(7.x以下版本)
elasticsearch7
h2(默认方案)
mysql
tidb
influxdb (时序数据库)
postgresql
根据网上资料,influxdb较其他持久化方案是最优的。但是笔者还没有研究过influxdb,并且公司也没有使用,出于实际性的考虑,还是采用了elasticsearch作为持久化存储
搭建过程
环境依赖
JDK8
由于笔者选用的方案是skywalking 8.7.0 + elasticsearch 6.8.18, 而elasticsearch6.x版本需要依赖jdk8及以上版本,所以需要安装JDK
1、elasticsearch 下载安装
下载地址
Download Elasticsearch Free | Get Started Now | Elastic | Elastic
版本依赖关系
Elastic Support Matrix | Elasticsearch
环境依赖
elasticsearch 需要依赖jdk环境。
需要注意的是:7.x版本以上需要jdk11及以上版本, 否则会启动时会报错
也可以通过ES内置的JDK包进行环境设置
参考链接:ES 启动 warning future versions of Elasticsearch will require Java 11_走码观花-CSDN博客
安装流程
- 下载好后对elasticsearch进行解压
tar -zxvf elasticsearch-6.8.18.tar.gz
- 创建操作用户及分组
因为安全问题elasticsearch 不让用root用户直接运行,否则启动时会报错:
Exception in thread "main" java.nio.file.AccessDeniedException: /home/elasticsearch-6.8.18/config/jvm.options
所以要创建新用户。
具体操作如下:
useradd es
passwd es
再输入两次密码(自定义)
为用户赋权限
chown -R es:es /opt/elasticsearch-6.8.18
然后使用es用户启动 :su es
cd /opt/elasticsearch-6.8.18/bin
启动es命令:./elasticsearch -d
2、skywalking 下载安装
下载地址
安装流程
- 对下载好的skywalking进行解压
tar -zxvf apache-skywalking-apm-8.7.0.tar.gz
- 修改skywalking config,修改存储方式用es
vi /opt/apache-skywalking-apm-bin/config/application.yml
找到storage,修改selector为:${SW_STORAGE:elasticsearch}
- 修改启动端口。由于默认端口为8080,会跟一些应用存在冲突,所以需要修改启动端口来避免端口冲突。
vi /opt/apache-skywalking-apm-bin/webapp/webapp.yml
修改server.port
- 启动skywalking
cd /opt/apache-skywalking-apm-bin/bin
./startup.sh
在浏览器中输入ip:port
3、skywalking应用监控
skywalking的应用监控是无侵入型监控,需要把探针agent,部署在需要收集数据的应用服务器上,并在启动时加上探针位置参数即可完成数据收集。
将部署的skywalking的agent文件夹拷贝出来放到需要收集数据的应用服务器上
修改项目启动参数。
nohup /opt/jdk1.8.0_291/bin/java -javaagent:/opt/apache-skywalking-apm-bin/agent/skywalking-agent.jar -Dskywalking.agent.service_name=abc -Dskywalking.collector.backend_service=127.0.0.1:11800 -jar -Xms1024m -Xmx1024m $file_name --spring.profiles.active=test >/dev/null 2>&1 &
参数说明:
-javaagent:{2} -Dskywalking.collector.backend_service=${3}
${1}:agent文件夹下的skywalking-agent.jar的路径
${2}:注册到skywalking的服务名称,用于在skywalking拓扑图上展示
${3}:skywalking接收agent发送采集数据的服务及端口。端口默认11800
4、skywalking日志追踪
配置方式
官方默认支持三种日志框架。引入版本号取决于安装的skywalking的版本,如skywalking.version:8.7.0
log4j
依赖引入
<pre><dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-log4j-1.x</artifactId>
<version>${skywalking.version}</version>
</dependency></pre>
配置 log4j.properties
<pre>log4j.appender.CONSOLE.layout=TraceIdPatternLayout # 设置日志输出格式 log4j.appender.CONSOLE.layout.ConversionPattern=%d [%T] %-5p %c{1}:%L - %m%n</pre>
log4j2
依赖引入
<pre><dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-log4j-2.x</artifactId>
<version>${skywalking.version}</version>
</dependency></pre>
配置 log4j2.xml
<pre><Configuration status="debug">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d [%traceId] %-5p %c{1}:%L - %m%n"/>
</Console>
<GRPCLogClientAppender name="grpc-log">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</GRPCLogClientAppender>
</Appenders>
<Loggers>
<logger name="com.a.eye.skywalking.ui" level="debug" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="grpc-log"/>
</logger>
<logger name="org.apache.kafka" level="INFO"></logger>
<logger name="org.apache.skywalking.apm.dependencies" level="INFO"></logger>
<Root level="debug">
<AppenderRef ref="Console"/>
<AppenderRef ref="grpc-log"/>
</Root>
</Loggers>
</Configuration></pre>
Logback
依赖引入
<pre><dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-logback-1.x</artifactId>
<version>${skywalking.version}</version>
</dependency></pre>
配置 logback.xml
<pre><configuration>
<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">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%mdc] [%thread] %-5level %logger{36} -%msg%n</Pattern>
</layout>
</encoder>
</appender>
<! -- 配置异步记录 AsyncAppender -->
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>1024</queueSize>
<neverBlock>true</neverBlock>
<appender-ref ref="STDOUT"/>
</appender>
<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.TraceIdPatternLogbackLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%tid] [%thread] %-5level %logger{36} -%msg%n</Pattern>
</layout>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ASYNC"/>
<appender-ref ref="grpc-log"/>
</root></configuration></pre>
如果是使用GRPCLogClientAppender, 需要在agent的config/agent.config文件中加上grpc的配置,否则会默认访问127.0.0.1:11800的端口上传日志,导致远程日志上传失败
plugin.toolkit.log.grpc.reporter.server_host=${SW_GRPC_LOG_SERVER_HOST:xx.xx.xx.xx}
plugin.toolkit.log.grpc.reporter.server_port=${SW_GRPC_LOG_SERVER_PORT:11800}
plugin.toolkit.log.grpc.reporter.max_message_size=${SW_GRPC_LOG_MAX_MESSAGE_SIZE:10485760}
plugin.toolkit.log.grpc.reporter.upstream_timeout=${SW_GRPC_LOG_GRPC_UPSTREAM_TIMEOUT:30}