微服务的项目大多都有好几个工程,日志缺少一个统一的管理,研究了一下elk,logstash接受日志,elasticsearch 处理数据,kibana展示数据。

elk使用现成的docker镜像 

docker run -p 5601:5601 -p 9200:9200 -p 5044:5044 -it --name elk sebp/elk
5601 - Kibana web 接口
9200 - Elasticsearch JSON 接口
5044 - Logstash 日志接收接口

logstash有许多种接受数据的方式,这边我尝试了两种,一种是应用使用logback直接通过tcp的方式发送日志到logstash,还有就是使用redis作为消息队列对日志数据做一个中转 。

tcp的方式

由于sebp/elk中logstash的input的方式默认是filebeat,首先们需要进入elk容器中修改input方式。logstash默认会将etc/logstash/conf.d/中的配置文件进行整合然后启动

docker exec -it elk /bin/bash 进入容器

cd etc/logstash/conf.d/

vim 02-beats-input.conf 修改input配置

input {    
    tcp {         
        port => 5044         
        codec => json_lines     
        
    } 
    
} 
output{  
    elasticsearch { 
    hosts => ["localhost:9200"] 
    
    } 
    
}

 然后退出容器。

重启容器

docker restart elk

到pom文件添加依赖

<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>4.7</version>
</dependency>

接下来到工程中添加logback的配置

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--该日志将日志级别不同的log信息保存到不同的文件中 -->
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />

    <springProperty scope="context" name="springAppName"
                    source="spring.application.name" />

    <!-- 日志在工程中的输出位置 -->
    <property name="LOG_FILE" value="${BUILD_FOLDER:-build}/${springAppName}" />

    <!-- 控制台的日志输出样式 -->
    <property name="CONSOLE_LOG_PATTERN"
              value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />

    <!-- 控制台输出 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <!-- 日志输出编码 -->
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>

    <!-- 为logstash输出的JSON格式的Appender -->
    <appender name="logstash"
              class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <destination>127.0.0.1:5044</destination>
        <!-- 日志输出编码 -->
        <encoder
                class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <timestamp>
                    <timeZone>UTC</timeZone>
                </timestamp>
                <pattern>
                    <pattern>
                        {
                        "severity": "%level",
                        "service": "${springAppName:-}",
                        "trace": "%X{X-B3-TraceId:-}",
                        "span": "%X{X-B3-SpanId:-}",
                        "exportable": "%X{X-Span-Export:-}",
                        "pid": "${PID:-}",
                        "thread": "%thread",
                        "class": "%logger{40}",
                        "rest": "%message"
                        }
                    </pattern>
                </pattern>
            </providers>
        </encoder>
    </appender>

    <!-- 日志输出级别 -->
    <root level="INFO">
        <appender-ref ref="console" />
        <appender-ref ref="logstash" />
    </root>
</configuration>
>

启动工程,日志就被发送到logstash中了。访问localhost:5601可以进入kibana界面

 

 配置pattern

输入*,匹配所有数据

选择时间@timestamp,这样数据展示会以时间排序

点击discover

 

 

可以显示日志信息

redis的方式

Redis 服务器是 logstash 官方推荐的 broker 选择。
读取 Redis 数据
LogStash data_type(实际上是redis_type) ,不同的数据类型会导致实际采用不同的 Redis 命令操作:
list => BLPOP
channel => SUBSCRIBE
pattern_channel => PSUBSCRIBE

配置示例

input {
 redis {
  codec => json
  host => "192.168.2.246"
  port => 56379
  key => "data-mgr"
  data_type => "list"
 }
}

我这边是使用list的方式,更改完input配置后,同样的重启elk容器

工程这边pom文件中添加依赖

<dependency>
  <groupId>com.cwbase</groupId>
  <artifactId>logback-redis-appender</artifactId>
  <version>1.1.5</version>
</dependency>

将LOGSTASH的appender换成

<appender name="LOGSTASH" class="com.cwbase.logback.RedisAppender">
    <source>mySource</source>
    <sourcePath>mySourcePath</sourcePath>
    <type>appName</type>
    <tags>dev</tags>
    <host>127.0.0.1</host>
    <port>56379</port>
    <key>data-mgr</key>
</appender>

一般考虑到性能上的影响,日志使用异步的方式发送到redis,再添加一个异步的appender

<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="LOGSTASH" />
    </appender>
    <!-- 日志输出级别 -->
    <root level="INFO">
        <appender-ref ref="console" />
        <appender-ref ref="ASYNC" />
    </root>

启动应用多个微服务应用

 完成!

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐