sl-express/01-讲义/md/day12-分布式日志与链路追踪.md

39 KiB
Raw Blame History

1、课程安排

  • 了解什么是分布式日志
  • Graylog的部署安装
  • 使用Graylog进行日志收集
  • Graylog的搜索语法
  • 了解什么是链路追踪
  • Skywalking的基本使用
  • 整合微服务使用Skywalking
  • 将Skywalking整合到Docker中

2、背景说明

在微服务架构体系中,微服务上线后,有两个不容忽略的问题,一是日志该怎么存储、查看,二是如何在复杂的调用链中排查问题。 kb.gif

2.1、日志问题

在微服务架构下,微服务被拆分成多个微小的服务,每个微小的服务都部署在不同的服务器实例上,当我们定位问题,检索日志的时候需要依次登录每台服务器进行检索。 这样是不是感觉很繁琐和效率低下?所以我们还需要一个工具来帮助集中收集、存储和搜索这些跟踪信息。 集中化管理日志后日志的统计和检索又成为一件比较麻烦的事情。以前我们通过使用grep、awk和wc等Linux命令能实现检索和统计但是对于要求更高的查询、排序和统计等要求和庞大的机器数量依然使用这样的方法难免有点力不从心。 所以,需要通过分布式日志服务来帮我们解决上述问题的。

2.2、调用链问题

在微服务架构下如何排查异常的微服务比如发布新版本后发现系统处理用户请求变慢了要想解决这个问首先是要找出“慢”的环节此时就需要对整个微服务的调用链有清晰的监控否则是不容易找出问题的。下面所展现的就是通过skywalking可以查看微服务的调用链就会比较容易的找出问题 image.png

3、分布式日志

3.1、实现思路

分布式日志框架服务的实现思路基本是一致的,如下:

  • **日志收集器:**微服务中引入日志客户端,将记录的日志发送到日志服务端的收集器,然后以某种方式存储
  • **数据存储:**一般使用ElasticSearch分布式存储把收集器收集到的日志格式化然后存储到分布式存储中
  • **web服务**利用ElasticSearch的统计搜索功能实现日志查询和报表输出

比较知名的分布式日志服务包括:

  • ELKelasticsearch、Logstash、Kibana
  • GrayLog

本课程主要是基于GrayLog讲解。

3.2、为什么选择GrayLog

业界比较知名的分布式日志服务解决方案是ELK而我们今天要学习的是GrayLog。为什么呢 ELK解决方案的问题

  1. 不能处理多行日志比如Mysql慢查询Tomcat/Jetty应用的Java异常打印
  2. 不能保留原始日志只能把原始日志分字段保存这样搜索日志结果是一堆Json格式文本无法阅读。
  3. 不符合正则表达式匹配的日志行,被全部丢弃。

GrayLog方案的优势

  1. 一体化方案安装方便不像ELK有3个独立系统间的集成问题。
  2. 采集原始日志并可以事后再添加字段比如http_status_coderesponse_time等等。
  3. 自己开发采集日志的脚本并用curl/nc发送到Graylog Server发送格式是自定义的GELFFlunted和Logstash都有相应的输出GELF消息的插件。自己开发带来很大的自由度。实际上只需要用inotifywait监控日志的modify事件并把日志的新增行用curl/netcat发送到Graylog Server就可。
  4. 搜索结果高亮显示就像google一样。
  5. 搜索语法简单,比如: source:mongo AND reponse_time_ms:>5000避免直接输入elasticsearch搜索json语法
  6. 搜索条件可以导出为elasticsearch的搜索json文本方便直接开发调用elasticsearch rest api的搜索脚本。

3.3、GrayLog简介

GrayLog是一个轻量型的分布式日志管理平台一个开源的日志聚合、分析、审计、展示和预警工具。在功能上来说和 ELK类似但又比 ELK要简单轻量许多。依靠着更加简洁高效部署使用简单的优势很快受到许多公司的青睐。 官网:https://www.graylog.org/ 其基本框架如图: image.png 流程如下:

  • 微服务中的GrayLog客户端发送日志到GrayLog服务端
  • GrayLog把日志信息格式化存储到Elasticsearch
  • 客户端通过浏览器访问GrayLogGrayLog访问Elasticsearch

这里MongoDB是用来存储GrayLog的配置信息的这样搭建集群时GrayLog的各节点可以共享配置。

3.4、部署安装

我们在虚拟机中选择使用Docker来安装。需要安装的包括

  • MongoDB用来存储GrayLog的配置信息
  • Elasticsearch用来存储日志信息
  • GrayLogGrayLog服务端

下面将通过docker的方式部署镜像已经下载到101虚拟机中部署脚本如下

#部署Elasticsearch
docker run -d \
    --name elasticsearch \
    -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
    -e "discovery.type=single-node" \
    -v es-data:/usr/share/elasticsearch/data \
    -v es-plugins:/usr/share/elasticsearch/plugins \
    --privileged \
    -p 9200:9200 \
    -p 9300:9300 \
elasticsearch:7.17.5

#部署MongoDB使用之前部署的服务即可
docker run -d \
--name mongodb \
-p 27017:27017 \
--restart=always \
-v mongodb:/data/db \
-e MONGO_INITDB_ROOT_USERNAME=sl \
-e MONGO_INITDB_ROOT_PASSWORD=123321 \
mongo:4.4

#部署
docker run \
--name graylog \
-p 9000:9000 \
-p 12201:12201/udp \
-e GRAYLOG_HTTP_EXTERNAL_URI=http://192.168.150.101:9000/ \
-e GRAYLOG_ELASTICSEARCH_HOSTS=http://192.168.150.101:9200/ \
-e GRAYLOG_ROOT_TIMEZONE="Asia/Shanghai"  \
-e GRAYLOG_WEB_ENDPOINT_URI="http://192.168.150.101:9000/:9000/api" \
-e GRAYLOG_PASSWORD_SECRET="somepasswordpepper" \
-e GRAYLOG_ROOT_PASSWORD_SHA2=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918 \
-e GRAYLOG_MONGODB_URI=mongodb://sl:123321@192.168.150.101:27017/admin \
-d \
graylog/graylog:4.3

命令解读:

  • 端口信息:
    • -p 9000:9000GrayLog的http服务端口9000
    • -p 12201:12201/udpGrayLog的GELF UDP协议端口用于接收从微服务发来的日志信息
  • 环境变量
    • -e GRAYLOG_HTTP_EXTERNAL_URI对外开放的ip和端口信息这里用9000端口
    • -e GRAYLOG_ELASTICSEARCH_HOSTSGrayLog依赖于ES这里指定ES的地址
    • -e GRAYLOG_WEB_ENDPOINT_URI对外开放的API地址
    • -e GRAYLOG_PASSWORD_SECRET:密码加密的秘钥
    • -e GRAYLOG_ROOT_PASSWORD_SHA2:密码加密后的密文。明文是admin,账户也是admin
    • -e GRAYLOG_ROOT_TIMEZONE="Asia/Shanghai"GrayLog容器内时区
    • -e GRAYLOG_MONGODB_URI指定MongoDB的链接信息
  • graylog/graylog:4.3使用的镜像名称版本为4.3

访问地址 http://192.168.150.101:9000/ 如果可以看到如下界面说明启动成功。 image.png 通过 admin/admin登录,即可看到欢迎页面,目前还没有数据: image.png

3.5、收集日志

3.5.1、配置Inputs

部署完成GrayLog后需要配置Inputs才能接收微服务发来的日志数据。 第一步,在System菜单中选择Inputs image.png 第二步,在页面的下拉选框中,选择GELF UDP image.png 然后点击Launch new input按钮: image.png 点击save保存: image.png 可以看到GELF UDP Inputs 保存成功。

3.5.2、集成微服务

现在GrayLog的服务端日志收集器已经准备好我们还需要在项目中添加GrayLog的客户端将项目日志发送到GrayLog服务中保存到ElasticSearch。 基本步骤如下:

  • 引入GrayLog客户端依赖
  • 配置Logback集成GrayLog的Appender
  • 启动并测试

这里我们以work微服务为例其他的类似。 导入依赖:

<dependency>
    <groupId>biz.paluch.logging</groupId>
    <artifactId>logstash-gelf</artifactId>
    <version>1.15.0</version>
</dependency>

配置Logback在配置文件中增加 GELF的appender

<?xml version="1.0" encoding="UTF-8"?>
<!--scan: 当此属性设置为true时配置文件如果发生改变将会被重新加载默认值为true。-->
<!--scanPeriod: 设置监测配置文件是否有修改的时间间隔如果没有给出时间单位默认单位是毫秒。当scan为true时此属性生效。默认的时间间隔为1分钟。-->
<!--debug: 当此属性设置为true时将打印出logback内部日志信息实时查看logback运行状态。默认值为false。-->
<configuration debug="false" scan="false" scanPeriod="60 seconds">
    <springProperty scope="context" name="appName" source="spring.application.name"/>
    <!--文件名-->
    <property name="logback.appname" value="${appName}"/>
    <!--文件位置-->
    <property name="logback.logdir" value="/data/logs"/>

    <!-- 定义控制台输出 -->
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} - [%thread] - %-5level - %logger{50} - %msg%n</pattern>
        </layout>
    </appender>


    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
        <File>${logback.logdir}/${logback.appname}/${logback.appname}.log</File>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${logback.logdir}/${logback.appname}/${logback.appname}.%d{yyyy-MM-dd}.log.zip</FileNamePattern>
            <maxHistory>90</maxHistory>
        </rollingPolicy>
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d [%thread] %-5level %logger{36} %line - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="GELF" class="biz.paluch.logging.gelf.logback.GelfLogbackAppender">
        <!--GrayLog服务地址-->
        <host>udp:192.168.150.101</host>
        <!--GrayLog服务端口-->
        <port>12201</port>
        <version>1.1</version>
        <!--当前服务名称-->
        <facility>${appName}</facility>
        <extractStackTrace>true</extractStackTrace>
        <filterStackTrace>true</filterStackTrace>
        <mdcProfiling>true</mdcProfiling>
        <timestampPattern>yyyy-MM-dd HH:mm:ss,SSS</timestampPattern>
        <maximumMessageSize>8192</maximumMessageSize>
    </appender>

    <!--evel:用来设置打印级别大小写无关TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF-->
    <!--不能设置为INHERITED或者同义词NULL。默认是DEBUG。-->
    <root level="INFO">
        <appender-ref ref="stdout"/>
        <appender-ref ref="GELF"/>
    </root>
</configuration>

修改代码,com.sl.ms.work.controller.TransportOrderController#findStatusCount()进入打印日志便于查看数据启动服务点击search按钮即可看到日志数据 image.png

3.6、日志回收策略

到此graylog的基础配置就算完成了已经可以收到日志数据。 但是在实际工作中,服务日志会非常多,这么多的日志,如果不进行存储限制,那么不久就会占满磁盘,查询变慢等等,而且过久的历史日志对于实际工作中的有效性也会很低。 Graylog则自身集成了日志数据限制的配置可以通过如下进行设置 image.png 选择Default index setEdit按钮: image.png GrayLog有3种日志回收限制触发以后就会开始回收空间删除索引 image.png 分别是:

  • Index Message Count:按照日志数量统计,默认超过20000000条日志开始清理
    • 我们测试时,设置100000即可
  • Index Size:按照日志大小统计,默认超过1GB开始清理
  • Index Message Count按照日志日期清理默认日志存储1天

3.7、搜索语法

在search页面可以完成基本的日志搜索功能 image.png

3.7.1、搜索语法

搜索语法非常简单,输入关键字或指定字段进行搜索:

#不指定字段默认从message字段查询
输入undo

#输入两个关键字关系为or
undo 统计

#加引号是需要完整匹配
"undo 统计"

#指定字段查询level表示日志级别ERROR3、WARNING4、NOTICE5、INFO6、DEBUG7
level: 6

#或条件
level:(6 OR 7)

更多查询官网文档:https://docs.graylog.org/docs/query-language

3.7.2、自定义展示字段

image.png 效果如下: image.png

3.8、日志统计仪表盘

GrayLog支持把日志按照自己需要的方式形成统计报表并把许多报表组合一起形成DashBoard仪表盘方便对日志统计分析。

3.8.1、创建仪表盘

image.png image.png image.png 可以设置各种指标: image.png image.png image.png image.png 最终效果: image.png 官方给出的效果: dashboardexamplev2.png

4、链路追踪

4.1、APM

4.1.1、什么是APM

随着微服务架构的流行,一次请求往往需要涉及到多个服务,因此服务性能监控和排查就变得更复杂

  • 不同的服务可能由不同的团队开发、甚至可能使用不同的编程语言来实现
  • 服务有可能布在了几千台服务器,横跨多个不同的数据中心

因此就需要一些可以帮助理解系统行为、用于分析性能问题的工具以便发生故障的时候能够快速定位和解决问题这就是APM系统全称是Application Performance Monitor当然也有叫 Application Performance Management tools APM最早是谷歌公开的论文提到的 Google Dapper。Dapper是Google生产环境下的分布式跟踪系统自从Dapper发展成为一流的监控系统之后给google的开发者和运维团队帮了大忙所以谷歌公开论文分享了Dapper。

4.1.2、原理

先来看一次请求调用示例:

  1. 包括前端A两个中间层B和C以及两个后端D和E
  2. 当用户发起一个请求时首先到达前端A服务然后分别对B服务和C服务进行RPC调用
  3. B服务处理完给A做出响应但是C服务还需要和后端的D服务和E服务交互之后再返还给A服务最后由A服务来响应用户的请求

image.png 如何才能实现跟踪呢?需要明白下面几个概念:

  • 探针:负责在客户端程序运行时收集服务调用链路信息,发送给收集器
  • 收集器:负责将数据格式化,保存到存储器
  • 存储器:保存数据
  • UI界面统计并展示

探针会在链路追踪时记录每次调用的信息Span是基本单元一次链路调用可以是RPCDB等没有特定的限制创建一个span通过一个64位ID标识它同时附加Annotation作为payload负载信息用于记录性能等数据。 一个Span的基本数据结构

type Span struct {
    TraceID    int64 // 用于标示一次完整的请求id
    Name       string //名称
    ID         int64 // 当前这次调用span_id
    ParentID   int64 // 上层服务的调用span_id  最上层服务parent_id为null代表根服务root
    Annotation []Annotation // 记录性能等数据
    Debug      bool
}

一次请求的每个链路通过spanId、parentId就能串联起来 image.png 当然从请求到服务器开始服务器返回response结束每个span存在相同的唯一标识trace_id。

4.1.3、技术选型

市面上的全链路监控理论模型大多都是借鉴Google Dapper论文重点关注以下三种APM组件

  • Zipkin由Twitter公司开源开放源代码分布式的跟踪系统用于收集服务的定时数据以解决微服务架构中的延迟问题包括数据的收集、存储、查找和展现。
  • Pinpoint一款对Java编写的大规模分布式系统的APM工具由韩国人开源的分布式跟踪组件。
  • Skywalking国产的优秀APM组件是一个对JAVA分布式应用程序集群的业务运行情况进行追踪、告警和分析的系统。现在是Apache的顶级项目之一。

选项就是对比各个系统的使用差异,主要对比项:

  1. 探针的性能 主要是agent对服务的吞吐量、CPU和内存的影响。微服务的规模和动态性使得数据收集的成本大幅度提高。
  2. collector的可扩展性 能够水平扩展以便支持大规模服务器集群。
  3. 全面的调用链路数据分析 提供代码级别的可见性以便轻松定位失败点和瓶颈。
  4. 对于开发透明,容易开关 添加新功能而无需修改代码,容易启用或者禁用。
  5. 完整的调用链应用拓扑 自动检测应用拓扑,帮助你搞清楚应用的架构

三者对比如下:

对比项 zipkin pinpoint skywalking
探针性能
collector扩展性
调用链路数据分析
对开发透明性
调用链应用拓扑
社区支持

综上所述使用skywalking是最佳的选择。

4.2、Skywalking简介

SkyWalking创建与2015年提供分布式追踪功能是一个功能完备的APM系统。 官网地址:http://skywalking.apache.org/ image.png 主要的特征:

  • 多语言探针或类库
    • Java自动探针追踪和监控程序时不需要修改源码。
    • 社区提供的其他多语言探针
  • 多种后端存储: ElasticSearch H2
  • 支持OpenTracing
    • Java自动探针支持和OpenTracing API协同工作
  • 轻量级、完善功能的后端聚合和分析
  • 现代化Web UI
  • 日志集成
  • 应用、实例和服务的告警

官方架构图: image.png 大致分四个部分:

  • skywalking-oap-server就是Observability Analysis Platform的服务用来收集和处理探针发来的数据
  • skywalking-UI就是skywalking提供的Web UI 服务图形化方式展示服务链路、拓扑图、trace、性能监控等
  • agent探针获取服务调用的链路信息、性能信息发送到skywalking的OAP服务
  • Storage存储一般选择elasticsearch

因此我们安装部署也从这四个方面入手目前elasticsearch已经安装完成只需要部署其他3个即可。

4.3、部署安装

通过docker部署需要部署两部分分别是skywalking-oap-serverskywalking-UI

#oap服务需要指定Elasticsearch以及链接信息
docker run -d \
-e TZ=Asia/Shanghai \
--name oap \
-p 12800:12800 \
-p 11800:11800 \
-e SW_STORAGE=elasticsearch \
-e SW_STORAGE_ES_CLUSTER_NODES=192.168.150.101:9200 \
apache/skywalking-oap-server:9.1.0


#部署ui需要指定oap服务
docker run -d \
--name oap-ui \
-p 48080:8080 \
-e TZ=Asia/Shanghai \
-e SW_OAP_ADDRESS=http://192.168.150.101:12800 \
apache/skywalking-ui:9.1.0

启动成功后,访问地址http://192.168.150.101:48080/即可查看skywalking的ui界面。 image.png

4.4、微服务探针

现在Skywalking的服务端已经启动完成我们还需要在微服务中加入服务探针来收集数据。 image.pngskywalking-agent解压到非中文目录。 在微服务中设置启动参数以work微服务为例 image.png 输入如下内容:

-javaagent:F:\code\sl-express\docs\resources\skywalking-agent\skywalking-agent.jar
-Dskywalking.agent.service_name=ms::sl-express-ms-work
-Dskywalking.collector.backend_service=192.168.150.101:11800

参数说明:

  • javaagent 将skywalking-agent以代理的方式整合到微服务中
  • skywalking.agent.service_name指定服务名称格式[{group name}::]{logic name}
  • skywalking.collector.backend_service指定oap服务注意端口要走11800

设置完成后重新启动work微服务多请求几次接口即可自oap-ui中看到数据。 image.png image.png 查看链路: image.png 服务关系拓扑图: image.png

4.5、整合到docker服务

前面的测试是在本地测试如何将SkyWalking整合到docker服务中呢 这里以sl-express-ms-web-courier为例,其他的服务类似。 第一步修改Dockerfile文件

#FROM openjdk:11-jdk
#修改为基于整合了skywalking的镜像其他的不需要动
FROM apache/skywalking-java-agent:8.11.0-java11
LABEL maintainer="研究院研发组 <research@itcast.cn>"
 
# 时区修改为东八区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
 
WORKDIR /app
ARG JAR_FILE=target/*.jar
ADD ${JAR_FILE} app.jar

EXPOSE 8080
ENTRYPOINT ["sh","-c","java -Djava.security.egd=file:/dev/./urandom -jar $JAVA_OPTS app.jar"]

第二步在Jenkins中编辑修改配置 名称skywalkingServiceName 值ms::sl-express-ms-web-courier image.png 名称skywalkingBackendService 值192.168.150.101:11800 image.png 修改运行脚本,增加系统环境变量: -e SW_AGENT_NAME=${skywalkingServiceName} -e SW_AGENT_COLLECTOR_BACKEND_SERVICES=${skywalkingBackendService} image.png 第三步,重新部署服务: image.png 第四步,测试接口,查看数据。 image.png image.png

5、练习

5.1、练习1

难度系数:★★☆☆☆ 描述:修改所有微服务中的logback-spring.xml完成Graylog的整合。

5.1、练习2

难度系数:★★★★☆ 描述将所有的微服务与skywalking整合。