安装ELK用于Spring boot项目日志收集和分析

原创
2020/04/30 11:18
阅读数 1.7K

项目环境:spring boot

日志框架 :slf4j+logback

ELK安装(docker方式):

具体步骤:

1,下载elk镜像(不带版本号应该可以下到最新版的)

docker pull sebp/elk

2,设置线程大小,该数值过小可能导致无法启动elk容器;

echo "vm.max_map_count=262144" > /etc/sysctl.conf
sysctl -p

 3,启动命令

docker run -dit --name elk -e ES_JAVA_OPTS="-Xms3072m -Xmx3072m" -p 5601:5601 -p 9200:9200 -p 5044:5044 -v /data/elk:/var/lib/elasticsearch -v /etc/localtime:/etc/localtime sebp/elk

   -name 给容器去个名字,我这里容器名字是: elk

    -e 设置elasticsearch参数,也可以在配置文件中改(稍后会说);

    -p docker端口映射,5601kibana端口,9200es端口,5044 logstash端口;

    -v 目录映射

4,ELK容器内配置

docker exec -it elk /bin/bash

   进入docker终端后可在一下路径中找到相关配置文件

/etc/logstash/        ## logstash 配置文件路径
/etc/elasticsearch/   ## es 配置文件路径
/var/log/             ## 日志路径

 注意:部分配置可能并不在上面的文件夹中,需要进入 /etc/init.d/ 文件夹中找到对应的配置更改后才能生效;

  • Logstash 配置:
vim /etc/logstash/conf.d/02-beats-input.conf

input {
  tcp {
    port => 5044  //logstash 端口
    codec=>json_lines //半结构化的json字符串数据格式
  }
}
output {
  elasticsearch {
    hosts => ["127.0.0.1:9200"] //elasticsearch的地址和端口,127.0.0.1只是个示例,最好不要天回环地址
    index => "logstash-%{+YYYY.MM.dd}" //索引名称,可以应用变量的。这里我配置成了logstash-XXX 稍后和spring boot集成时会说明
  }
}

  • kibana配置    

    这个其实没有太多要配置的,我改过内存,然鹅并没有什么卵用,还没找到原因

vim /opt/kibana/config/kibana.yml

在文件内追加 i18n.locale: "zh-CN"  可以改成中文

 配置完后按Ctrl+D退出docker终端;

 重启容器,配置生效

docker restart elk

5,集成到spring boot  项目

  • POM依赖

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

  • application.properties配置

    spring.profiles.active=release

    logging.config=classpath:logback-spring.xml

  • logback-spring.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <contextName>third-party-gateway-api</contextName>
    <property name="LOG_HOME" value="./logs" />
    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{40}.%M %L %X{sessionId} - %msg%n</pattern>
        </encoder>
    </appender>
    <!-- 按照每天生成日志文件 -->
    <appender name="FILE"  class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${LOG_HOME}/log.%d{yyyy-MM-dd}.log</FileNamePattern>
            <!--日志文件保留天数-->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{40}.%M %L %X{sessionId} - %msg%n</pattern>
        </encoder>
        <!--日志文件最大的大小-->
        <!-- <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy> -->
    </appender>

    <springProfile name="release">
     <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>
                        {
                        "hostName":"${HOSTNAME}",
                        "contextName":"%contextName",
                        "thread":"%thread",
                        "level":"%-5level",
                        "sessionId": "%X{sessionId}",
                        "class": "%logger{40}",
                        "method":"%M",
                        "line":"%L",
                        "msg": "%msg"
                        }
                    </pattern>
                </pattern>
            </providers>
        </encoder>
    </appender>
    </springProfile>
    <!-- 日志输出级别 -->
    <root level="INFO">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="FILE" />
        <springProfile name="release">
          <appender-ref ref="LOGSTASH" />
        </springProfile >
    </root>
    <!--日志异步到数据库 -->
    <!--<appender name="DB" class="ch.qos.logback.classic.db.DBAppender">-->
        <!--&lt;!&ndash;日志异步到数据库 &ndash;&gt;-->
        <!--<connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">-->
            <!--&lt;!&ndash;连接池 &ndash;&gt;-->
            <!--<dataSource class="com.mchange.v2.c3p0.ComboPooledDataSource">-->
                <!--<driverClass>com.mysql.jdbc.Driver</driverClass>-->
                <!--<url>jdbc:mysql://127.0.0.1:3306/databaseName</url>-->
                <!--<user>root</user>-->
                <!--<password>root</password>-->
            <!--</dataSource>-->
        <!--</connectionSource>-->
    <!--</appender>-->
</configuration>

 几个关键点说明:

  • <contextName>third-party-gateway-api</contextName>工程或模块名称
  • %X{sessionId} 这是一个自定义参数,可以用sfl4j的MDC.put("sessionId","123"),设置会话ID以便追踪日志,分析问题,一般在过滤器或拦截器中设置此值
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		
		String contentPath = request.getContextPath();
		String uri = request.getServletPath();
		MDC.put("sessionId",IdUtil.fastSimpleUUID());
        //MDC.put("sessionId",request.getParameter("requestId"));
		logger.info("-----------------------------------------------");
		logger.info("client IP {}",ServletUtil.getClientIP(request));
		logger.info("access url : {},{}",request.getMethod(),request.getRequestURL());
		logger.info("access content : {}",contentPath);
		logger.info("access ServletPath : {}",uri);
		
		return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// TODO Auto-generated method stub
		MDC.clear();
}
  •  <springProfile name="release"> 表示只在spring.profiles.active=release的情况下才激活logstash配置,因为一般开发环境不会安装ELK
  • <pattern>
    	{
    	"hostName":"${HOSTNAME}",
        "contextName":"%contextName",
        "thread":"%thread",
        "level":"%-5level",
        "sessionId": "%X{sessionId}",
        "class": "%logger{40}",
        "method":"%M",
        "line":"%L",
        "msg": "%msg"
        }
    </pattern>

    这段是传送给logstash的数据格式,每个字段都可以在ES中做成索引

6,kibana使用

    浏览器打开 http://127.0.0.1:5601 第一次进去会提示加载示例数据,选“否”就可以了;

  •     建立索引模式,在索引模式中输入logstash-*(建立之前先启动 spring boot 项目,如不启动,恐无法建立logstash-*模式的索引,还记得第4步中的配置吗:"logstash-%{+YYYY.MM.dd}" ),如图:

  • 配置索引策略和生命周期

  • 日志查询

看到了么,JSON字符串的所有字段有显示出来了,并且可以快速筛选,KQL语法还支持模糊全文索引,可以用不同的组合查询方式提高查询速度;

7,问题

  •     告警,运行状态一直是yellow,(我的是green状态)

        

        其实这个问题并不影响适用,原因是我们采用的是单机ES模式,改一下索引模式的配置就可以了

        任意点击一索引,index.number_of_replicas值改成0

       

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部