掌握了这些 ELK Stack 中常见的难点问题和优化技巧,走遍天下都不怕!

公众号关注 「运维之美」

设为「星标」,每天带你玩转 Linux !




本文将分享一些 ELK Stack 使用中常见难点问题的解决方法和 ELK Stack 的优化技巧,全是干货,推荐一读!

ELK Stack 常见难点问题总结

1. 编码转换问题(主要就是中文乱码)

  • input 中的codec => plain 转码

codec => plain {
         charset => "GB2312"
}


将 GB2312 的文本编码,转为 UTF-8 的编码。

  • 在 filebeat 中实现编码的转换(推荐)

filebeat.prospectors:
- input_type: log
  paths:
    - c:\Users\Administrator\Desktop\performanceTrace.txt
  encoding: GB2312

2. 删除多余日志中的多余行

  • 通过 logstash filter 中 drop 删除

    if ([message] =~ "^20.*-\ task\ request,.*,start\ time.*") {   #用正则表达式删除的多余行
            drop {}
    } 
  • 日志示例

2018-03-20 10:44:01,523 [33]DEBUG Debug - task request,task Id:1cbb72f1-a5ea-4e73-957c-6d20e9e12a7a,start time:2018-03-20 10:43:59   # 需删除的行
-- Request String : {"UserName":"15046699923","Pwd":"ZYjyh727","DeviceType":2,"DeviceId":"PC-20170525SADY","EquipmentNo":null,"SSID":"pc","RegisterPhones":null,"AppKey":"ab09d78e3b2c40b789ddfc81674bc24deac","Version":"2.0.5.3"} -- End
-- Response String : {"ErrorCode":0,"Success":true,"ErrorMsg":null,"Result":null,"WaitInterval":30} -- End

 3. Grok 处理多种日志不同的行

  • 日志示例

2018-03-20 10:44:01,523 [33]DEBUG Debug - task request,task Id:1cbb72f1-a5ea-4e73-957c-6d20e9e12a7a,start time:2018-03-20 10:43:59
-- Request String : {"UserName":"15046699923","Pwd":"ZYjyh727","DeviceType":2,"DeviceId":"PC-20170525SADY","EquipmentNo":null,"SSID":"pc","RegisterPhones":null,"AppKey":"ab09d78e3b2c40b789ddfc81674bc24deac","Version":"2.0.5.3"} -- End
-- Response String : {"ErrorCode":0,"Success":true,"ErrorMsg":null,"Result":null,"WaitInterval":30} -- End

在 Logstash Filter 中 Grok 分别处理 3 行

match => {
    "message" => "^20.*-\ task\ request,.*,start\ time\:%{TIMESTAMP_ISO8601:RequestTime}"
match => {
    "message" => "^--\ Request\ String\ :\ \{\"UserName\":\"%{NUMBER:UserName:int}\",\"Pwd\":\"(?<Pwd>.*)\",\"DeviceType\":%{NUMBER:DeviceType:int},\"DeviceId\":\"(?<DeviceId>.*)\",\"EquipmentNo\":(?<EquipmentNo>.*),\"SSID\":(?<SSID>.*),\"RegisterPhones\":(?<RegisterPhones>.*),\"AppKey\":\"(?<AppKey>.*)\",\"Version\":\"(?<Version>.*)\"\}\ --\ \End.*"    
}
match => {
    "message" => "^--\ Response\ String\ :\ \{\"ErrorCode\":%{NUMBER:ErrorCode:int},\"Success\":(?<Success>[a-z]*),\"ErrorMsg\":(?<ErrorMsg>.*),\"Result\":(?<Result>.*),\"WaitInterval\":%{NUMBER:WaitInterval:int}\}\ --\ \End.*"
}
... 等多行

4. 日志多行合并处理—Multiline 插件(重点)

4.1 示例

  • 要处理的日志样本数据

2018-03-20 10:44:01,523 [33]DEBUG Debug - task request,task Id:1cbb72f1-a5ea-4e73-957c-6d20e9e12a7a,start time:2018-03-20 10:43:59
-- Request String : {"UserName":"15046699923","Pwd":"ZYjyh727","DeviceType":2,"DeviceId":"PC-20170525SADY","EquipmentNo":null,"SSID":"pc","RegisterPhones":null,"AppKey":"ab09d78e3b2c40b789ddfc81674bc24deac","Version":"2.0.5.3"} -- End
-- Response String : {"ErrorCode":0,"Success":true,"ErrorMsg":null,"Result":null,"WaitInterval":30} -- End
  • 通过 Logstash Grok 对合并后多行的处理(合并多行后续都一样,如下)

filter {
  grok {
    match => {
      "message" => "^%{TIMESTAMP_ISO8601:InsertTime}\ .*-\ task\ request,.*,start\ time:%{TIMESTAMP_ISO8601:RequestTime}\n--\ Request\ String\ :\ \{\"UserName\":\"%{NUMBER:UserName:int}\",\"Pwd\":\"(?<Pwd>.*)\",\"DeviceType\":%{NUMBER:DeviceType:int},\"DeviceId\":\"(?<DeviceId>.*)\",\"EquipmentNo\":(?<EquipmentNo>.*),\"SSID\":(?<SSID>.*),\"RegisterPhones\":(?<RegisterPhones>.*),\"AppKey\":\"(?<AppKey>.*)\",\"Version\":\"(?<Version>.*)\"\}\ --\ \End\n--\ Response\ String\ :\ \{\"ErrorCode\":%{NUMBER:ErrorCode:int},\"Success\":(?<Success>[a-z]*),\"ErrorMsg\":(?<ErrorMsg>.*),\"Result\":(?<Result>.*),\"WaitInterval\":%{NUMBER:WaitInterval:int}\}\ --\ \End"
    }
  }
}

4.2 在 Filebeat 中使用 Multiline 插件来处理(推荐)

  • 介绍 Multiline

pattern:正则匹配从哪行合并。

negate:true / false,匹配到 Pattern 部分开始合并,还是不配到的合并。

match:afte r/ before(需自己理解)。

    after:匹配到 Pattern 部分后合并,注意:这种情况最后一行日志不会被匹配处理。
    before:匹配到 Pattern 部分前合并(推荐)

  • 5.5 版本之后( Before 为例)

filebeat.prospectors:
- input_type: log
  paths:
    - /root/performanceTrace*
  fields:
    type: zidonghualog
  multiline.pattern: '.*\"WaitInterval\":.*--\ End'
  multiline.negate: true
  multiline.match: before
  • 5.5 版本之前( After 为例)

filebeat.prospectors:
- input_type: log 
     paths:
      - /root/performanceTrace*
      input_type: log 
      multiline:
           pattern: '^20.*'
           negate: true
           match: after

 4.3 在 Logstash Input 中使用 Multiline 插件(没有 Filebeat 时推荐)

  • 介绍 Multiline


pattern:正则匹配从哪行合并

negate:true / false,匹配到 Pattern 部分开始合并,还是不配到的合并

what:previous/next(需自己理解)

     previous:相当于filebeat 的after

     next:相当于filebeat 的before

  • 用法

input {
        file {
                path => ["/root/logs/log2"]
                start_position => "beginning"
                codec => multiline {
                        pattern => "^20.*"
                        negate => true
                        what => "previous"
                }
        }
}

4.4 在 Logstash Filter 中使用 Multiline 插件(不推荐)

  • 不推荐的原因


a). Filter 设置 Multiline 后,pipline worker 会自动为 1

b). 5.5 版本官方把 Multiline 去除了,要使用的话需下载,下载命令如下:

/usr/share/logstash/bin/logstash-plugin install logstash-filter-multiline
  • 示例

filter {
  multiline {
    pattern => "^20.*"
    negate => true
    what => "previous"
  }
} 

5. Logstash Filter 中的 date 使用

  • 日志示例

2018-03-20 10:44:01 [33]DEBUG Debug - task request,task Id:1cbb72f1-a5ea-4e73-957c-6d20e9e12a7a,start time:2018-03-20 10:43:59
  • date 使用

        date {
                match => ["InsertTime","YYYY-MM-dd HH:mm:ss "]
                remove_field => "InsertTime"
        }

注:match => ["timestamp" ,"dd/MMM/YYYY H:m:s Z"]

匹配这个字段,字段的格式为:日日/月月月/年年年年 时/分/秒 时区。也可写为:match => ["timestamp","ISO8601"](推荐)

  • date 介绍


就是将匹配日志中时间的 key 替换为@timestamp 的时间,因为@timestamp 的时间是日志送到 Logstash 的时间,并不是日志中真正的时间。

6. 对多类日志分类处理(重点)

  • 在 Filebeat 的配置中添加 type 分类

filebeat:
  prospectors:
    -
      paths:
        #- /mnt/data/WebApiDebugLog.txt*
        - /mnt/data_total/WebApiDebugLog.txt*
      fields:
        type: WebApiDebugLog_total
    -
      paths:
        - /mnt/data_request/WebApiDebugLog.txt*
        #- /mnt/data/WebApiDebugLog.txt*
      fields:
        type: WebApiDebugLog_request
    -
      paths:
        - /mnt/data_report/WebApiDebugLog.txt*
        #- /mnt/data/WebApiDebugLog.txt*
      fields:
        type: WebApiDebugLog_report
  • 在 Logstash Filter 中使用 if,可进行对不同类进行不同处理。

filter {
   if [fields][type] == "WebApiDebugLog_request" {   #对request 类日志
        if ([message] =~ "^20.*-\ task\ report,.*,start\ time.*") {   #删除report 行
                drop {}
        }
    grok {
        match => {"... ..."}
        }
}
  • 在 Logstash output 中使用 if

if [fields][type] == "WebApiDebugLog_total" {
    elasticsearch {
        hosts => ["6.6.6.6:9200"]
        index => "logstashl-WebApiDebugLog_total-%{+YYYY.MM.dd}"
        document_type => "WebApiDebugLog_total_logs"
} 

ELK Stack 整体性能优化

1. 性能分析

1.1 服务器硬件情况

Linux:1 CPU  4G RAM

假设每条日志 250 Byte

1.2 分析

  • logstash-Linux:1 CPU 4G RAM

每秒 500 条日志

去掉 ruby 每秒 660 条日志

去掉 grok 后每秒 1000 条数据

  • filebeat-Linux:1 CPU 4G RAM

每秒 2500-3500 条数据,每天每台机器可处理:24h*60min*60sec*3000*250Byte=64,800,000,000 Bytes,约 64 G。

  • 瓶颈在 Logstash 从 Redis 中取数据存入 ES,开启一个 Logstash,每秒约处理 6000 条数据;开启两个 Logstash,每秒约处理 10000 条数据( CPU 已基本跑满);

  • LogStash 的启动过程占用大量系统资源,因为脚本中要检查 Java、Ruby 以及其他环境变量,启动后资源占用会恢复到正常状态。 

2. 关于收集日志的选择:Logstash / Filter

2.1 没有原则要求使用 Filebeat 或 Logstash,两者作为 Shipper 的功能是一样的,区别在于:

  • LogStash 由于集成了众多插件,如 Grok,Ruby,所以相比 Beat是重量级的;

  • LogStash 启动后占用资源更多,如果硬件资源足够则无需考虑二者差异;

  • LogStash 基于 JVM,支持跨平台;而 Beat 使用 Golang 编写,AIX 不支持;

  • AIX 64 bit 平台上需要安装 jdk(jre) 1.7 32bit,64 bit 的不支持;

  • Filebeat 可以直接输入到 ES,但是系统中存在 Logstash 直接输入到 ES的情况,这将造成不同的索引类型造成检索复杂,最好统一输入到 els 的源。

2.2 总结

LogStash/Filter 总之各有千秋,但是,我推荐选择:在每个需要收集的日志服务器上配置 Filebeat,因为轻量级,用于收集日志;再统一输出给 Logstash,做对日志的处理;最后统一由 Logstash 输出给 els。

3、Logstash 的优化相关配置 

3.1 可以优化的参数,可根据自己的硬件进行优化配置

  • pipeline 线程数,官方建议是等于CPU内核数

默认配置 ---> pipeline.workers: 2

可优化为 ---> pipeline.workers: CPU内核数(或几倍cpu内核数)

  • 实际 output 时的线程数

默认配置 ---> pipeline.output.workers: 1

可优化为 ---> pipeline.output.workers: 不超过pipeline 线程数

  • 每次发送的事件数

默认配置 ---> pipeline.batch.size: 125

可优化为 ---> pipeline.batch.size: 1000

  • 发送延时

默认配置 ---> pipeline.batch.delay: 5

可优化为 ---> pipeline.batch.size: 10

3.2 总结

通过设置-w参数指定pipeline worker数量,也可直接修改配置文件logstash.yml。这会提高 Filter 和 Output 的线程数,如果需要的话,将其设置为 CPU核心数的几倍是安全的,线程在 I/O 上是空闲的。

默认每个输出在一个 pipeline worker 线程上活动,可以在输出 output 中设置 workers 设置,不要将该值设置大于 pipeline worker数。

还可以设置输出的 batch_size 数,例如 ES 输出与 batch size 一致。

Filter 设置 Multiline 后,pipline worker 会自动将为 1,如果使用 Filebeat,建议在 Beat 中就使用 Multiline,如果使用 Logstash 作为 Shipper,建议在 Input 中设置 Multiline,不要在 Filter 中设置 Multiline。

3.3 Logstash 中的 JVM 配置文件

Logstash 是一个基于 Java 开发的程序,需要运行在 JVM 中,可以通过配置 jvm.options 来针对 JVM 进行设定。比如内存的最大最小、垃圾清理机制等等。JVM 的内存分配不能太大不能太小,太大会拖慢操作系统。太小导致无法启动。默认如下:

-Xms256m #最小使用内存
-Xmx1g #最大使用内存

4. 引入 Redis 的相关问题

4.1 Filebeat 可以直接输入到 Logstash(indexer),但 Logstash 没有存储功能,如果需要重启需要先停所有连入的 Beat,再停 Logstash,造成运维麻烦;另外如果 Logstash 发生异常则会丢失数据;引入 Redis 作为数据缓冲池,当 Logstash 异常停止后可以从 Redis 的客户端看到数据缓存在 Redis 中;

4.2 Redis 可以使用 List(最长支持 4,294,967,295条)或发布订阅存储模式;

4.3 Redis 做 ELK 缓冲队列的优化:

  • bind 0.0.0.0  #不要监听本地端口

  • requirepass ilinux.io  #加密码,为了安全运行

  • 只做队列,没必要持久存储,把所有持久化功能关掉:快照(RDB文件)和追加式文件(AOF文件),性能更好

          save ""  禁用快照

          appendonly no 关闭RDB

  • 把内存的淘汰策略关掉,把内存空间最大

               maxmemory 0   maxmemory 为 0 的时候表示我们对 Redis 的内存使用没有限制

5. Elasticsearch 节点优化配置

5.1 服务器硬件配置和OS 参数

  • /etc/sysctl.conf 配置

$ vim /etc/sysctl.conf
vm.swappiness = 1                     #ES 推荐将此参数设置为 1,大幅降低 swap 分区的大小,强制最大程度的使用内存,注意,这里不要设置为 0, 这会很可能会造成 OOM
net.core.somaxconn = 65535     #定义了每个端口最大的监听队列的长度
vm.max_map_count= 262144    #限制一个进程可以拥有的VMA(虚拟内存区域)的数量。虚拟内存区域是一个连续的虚拟地址空间区域。当VMA 的数量超过这个值,OOM
fs.file-max = 518144                   #设置 Linux 内核分配的文件句柄的最大数量
[root@elasticsearch]# sysctl -p 生效一下
  • limits.conf 配置

$ vim /etc/security/limits.conf


elasticsearch    soft    nofile          65535
elasticsearch    hard    nofile          65535
elasticsearch    soft    memlock         unlimited
elasticsearch    hard    memlock         unlimited
  • 为了使以上参数永久生效,还要设置两个地方

/etc/pam.d/common-session-noninteractive

/etc/pam.d/common-session

# 添加如下属性,可能需重启后生效
session required pam_limits.so

5.2 Elasticsearch 中的 JVM 配置文件

-Xms2g
-Xmx2g
  • 将最小堆大小(Xms)和最大堆大小(Xmx)设置为彼此相等。

  • Elasticsearch 可用的堆越多,可用于缓存的内存就越多。但请注意,太多的堆可能会使您长时间垃圾收集暂停。

  • 设置 Xmx 为不超过物理 RAM 的 50%,以确保有足够的物理内存留给内核文件系统缓存。

  • 不要设置 Xmx 为 JVM 用于压缩对象指针的临界值以上;确切的截止值有所不同,但接近 32 GB。不要超过 32G,如果空间大,多跑几个实例,不要让一个实例太大内存

5.3 Elasticsearch 配置文件优化参数

  • 修改 elasticsearch.yml 文件

$ vim elasticsearch.yml
bootstrap.memory_lock: true  #锁住内存,不使用swap
#缓存、线程等优化如下
bootstrap.mlockall: true
transport.tcp.compress: true
indices.fielddata.cache.size: 40%
indices.cache.filter.size: 30%
indices.cache.filter.terms.size: 1024mb
threadpool:
    search:
        type: cached
        size: 100
        queue_size: 2000

 

  • 设置环境变量

$ vim /etc/profile.d/elasticsearch.sh export ES_HEAP_SIZE=2g    #Heap Size不超过物理内存的一半,且小于32G

 

5.4 集群的优化

  • ES是分布式存储,当设置同样的cluster.name后会自动发现并加入集群;

  • 集群会自动选举一个master,当master宕机后重新选举;

  • 为防止"脑裂",集群中个数最好为奇数个

  • 为有效管理节点,可关闭广播 discovery.zen.ping.multicast.enabled: false,并设置单播节点组discovery.zen.ping.unicast.hosts: ["ip1", "ip2", "ip3"]

6. 性能的检查

6.1 检查输入和输出的性能

Logstash 和其连接的服务运行速度一致,它可以和输入、输出的速度一样快。

6.2 检查系统参数

  • CPU

注意 CPU 是否过载。在 Linux/Unix 系统中可以使用 top -H 查看进程参数以及总计。

如果 CPU 使用过高,直接跳到检查 JVM 堆的章节并检查 Logstash worker 设置。

  • Memory

注意 Logstash 是运行在 Java 虚拟机中的,所以它只会用到你分配给它的最大内存。

检查其他应用使用大量内存的情况,这将造成 Logstash 使用硬盘 Swap,这种情况会在应用占用内存超出物理内存范围时。

  • I/O 监控磁盘 I/O 检查磁盘饱和度

使用 Logstash plugin(例如使用文件输出)磁盘会发生饱和。

当发生大量错误,Logstash 生成大量错误日志时磁盘也会发生饱和。

在 Linux中,可使用 iostat,dstat 或者其他命令监控磁盘 I/O

  • 监控网络 I/O

当使用大量网络操作的 input、output 时,会导致网络饱和。

在 Linux 中可使用 dstat 或 iftop 监控网络情况。

6.3 检查 JVM heap

heap 设置太小会导致 CPU 使用率过高,这是因为 JVM 的垃圾回收机制导致的。

一个快速检查该设置的方法是将 heap 设置为两倍大小然后检测性能改进。不要将 heap 设置超过物理内存大小,保留至少 1 G内存给操作系统和其他进程。

你可以使用类似 jmap 命令行或 Visual VM 更加精确的计算 JVM heap

来源:cnblogs
原文:http://t.cn/ExQhrdb
题图:来自谷歌图片搜索 
版权:本文版权归原作者所有
投稿:欢迎投稿,投稿邮箱: editor@hi-linux.com

你可能还喜欢

点击下方图片即可阅读

假如服务器上没有 Docker 环境,你还能愉快的拉取容器镜像吗?

点击上方图片,打开小程序,加入「玩转 Linux」圈子

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值