简介
在后端开发日常工作中,定位排查问题或是了解系统某些方面的情况时,会遇到以下的场景:
- 查询接口请求的日志。
- 查询服务的日志。
- 统计接口的每日调用数量以及时间分布。
- 统计接口每日的用户数量。
ELK(Elasticsearch + Logstash + Kibana
)平台很好的完成了上述工作,并且提供了友好便利的用户界面,普遍应用于生产日志的查询分析中。ELK一句话概括:用Logstash收集日志
或者数据到Elasticsearch存储
起来并建立相关索引
,再利用Kibana查询界面
到Elasticsearch上提供的索引进行查询和统计
。
- Logstash
Logstash
主要用于收集服务器日志
,它是一个开源数据收集引擎
,具有实时管道功能
。Logstash可以动态地将来自不同数据源的数据统一起来,并将数据标准化到所选择的目的地。
Logstash 收集数据的过程主要分为以下三个部分:
输入(input)
:数据往往都是以不同的形式、格式存储在不同的系统中,而Logstash支持从多种数据源中收集数据(File、Syslog、MySQL、消息中间件
等等)。过滤器(filter)
:实时解析和转换数据,识别已命名的字段以构建结构,并将它们转换成通用格式。输出(output)
:Elasticsearch并非存储的唯一选择,Logstash提供很多输出选择。
- Elasticsearch
Elasticsearch (ES)
是一个分布式Restful风格的搜索和数据分析引擎
,它具有以下特点:
查询
:允许执行和合并多种类型的搜索 (结构化、非结构化、地理位置、度量指标),搜索方式随心而变。分析
:Elasticsearch聚合让您能够从大处着眼,探索数据的趋势和模式。速度
:很快,可以做到亿万级的数据,毫秒级返回。可扩展性
:可以在笔记本电脑上运行,也可以在承载了 PB 级数据的成百上千台服务器上运行。弹性
:运行在一个分布式的环境中,从设计之初就考虑到了这一点。灵活性
:具备多个案例场景。支持数字、文本、地理位置、结构化、非结构化,所有的数据类型都欢迎。
- Kibana
基于浏览器
的界面便于快速创建和分享动态数据仪表板来追踪 Elasticsearch 的实时数据变化。其搭建过程也十分简单,您可以分分钟完成 Kibana 的安装,并开始探索 Elasticsearch 的索引数据,没有代码、不需要额外的基础设施。
- Filebeat
ELK 协议栈的新成员
,一个轻量级开源日志文件数据搜集器
,基于 Logstash-Forwarder 源代码开发,是对它的替代。在需要采集日志数据的服务器上安装 Filebeat,并指定·日志目录·或·日志文件·后,Filebeat 就能读取数据,迅速发送到 Logstash
进行解析,亦或直接发送到 Elasticsearch
(日志不需要Logstash过滤拆分时)进行集中式存储和分析。
这四者都是开源软件,通常配合使用,而且又先后归于 Elastic.co
公司名下,所以被简称为 ELK Stack
。根据 Google Trend 的信息显示,ELK Stack 已经成为目前最流行的集中式日志解决方案。
常用架构
Logstash架构
单服务
只有一个 Logstash、Elasticsearch 和 Kibana
实例。Logstash 通过输入插件从多种数据源(比如日志文件、标准输入 Stdin 等)获取数据,再经过滤插件加工数据,然后经 Elasticsearch 输出插件输出到 Elasticsearch,通过 Kibana 展示。
多服务
把一个 Logstash 数据搜集节点扩展到多个,分布于多台机器
,将解析好的数据发送到 Elasticsearch server 进行存储,最后在 Kibana 查询、生成日志报表等。
这种结构因为需要在各个服务器上部署 Logstash,而它比较消耗 CPU 和内存资源
,所以比较适合计算资源丰富的服务器,否则容易造成服务器性能下降,甚至可能导致无法正常工作。
Beats架构
这种架构引入 Beats 作为日志搜集器
。目前 Beats 包括四种:
- Packetbeat(搜集
网络流量
数据)- Topbeat(搜集
系统、进程和文件
,系统级别的CPU和内存使用
情况等数据)- Filebeat(搜集
文件
数据)- Winlogbeat(搜集
Windows 事件日志
数据)
Beats 将搜集到的数据发送到 Logstash,经 Logstash 解析、过滤后,将其发送到 Elasticsearch 存储,并由 Kibana 呈现给用户。
这种架构解决了 Logstash 在各服务器节点上占用系统资源高的问题
。相比 Logstash,Beats 所占系统的 CPU 和内存几乎可以忽略不计。另外,Beats 和 Logstash 之间支持 SSL/TLS 加密传输
,客户端和服务器双向认证,保证了通信安全。
因此这种架构适合对数据安全性要求较高
,同时各服务器性能比较敏感的场景。
消息队列架构
Beats 还不支持输出到消息队列
,所以在消息队列两端只能是 Logstash 实例
。这种架构使用 Logstash 从各个数据源搜集数据,然后经消息队列输出插件输出到消息队列中。目前 Logstash 支持 Kafka、Redis、RabbitMQ 等常见消息队列
。然后 Logstash 通过消息队列输入插件从队列中获取数据,分析过滤后经输出插件发送到 Elasticsearch,最后通过 Kibana 展示。
这种架构适合于日志规模比较庞大的情况。但由于 Logstash 日志解析节点和 Elasticsearch 的负荷比较重
,可将他们配置为集群模式
,以分担负荷。引入消息队列,均衡了网络传输,从而降低了网络闭塞,尤其是丢失数据的可能性
,但依然存在 Logstash 占用系统资源过多的问题
。
案例实操
elastic 官网下载地址:https://www.elastic.co/cn/downloads/
安装环境及版本:
- 操作系统:虚拟机 Centos7
- JDK:1.8
- ElasticSearch:7.3.0
- Logstash:7.3.0
- Kibana:7.3.0
- filebeat :7.3.0
本案例中的软件均在
同一台服务器部署
,所以host配置部分都为localhost,若是远程服务器,修改为具体ip地址即可
下面以Logstash单服务
和Beats
两个架构为例来进行实操详解
软件安装
JDK安装
- 下载
JDK 官网下载地址,本文使用:
jdk-8u131-linux-x64.tar.gz
- 解压安装
将JDK安装包上传到服务器,进行解压
tar -zxvf jdk-8u131-linux-x64.tar.gz |
- 修改环境变量
通过命令编辑profile
文件,在文件末尾(按大写"G"移至文件末尾
)添加以下内容(按"i"进入编辑
):
vi /etc/profile |
路径需与安装路径相符
export JAVA_HOME=/usr/local/java |
按左上方"esc"
键退出编辑模式,按wq!
强制保存;再通过命令source /etc/profile
重载profile文件,使其生效
- 验证
通过javac
和java -version
命令验证,如下图所示即为安装成功
项目部署
用IDEA将Spring Boot项目打包,并部署到服务器上。进入项目jar包所在路径,执行启动命令
java -jar 包名称.jar |
本项目log4j日志配置如下,log4j基础教程
|
Logstash安装
- 解压安装
将logstash安装包上传到服务器,进行解压
tar -zxvf logstash-7.3.0.tar.gz |
- 验证
执行以下命令,验证是否安装成功
cd logstash-7.3.0 |
在控制台输入 HelloWorld ,看到如下效果代表 Logstash 安装成功
也可通过进程命令,检查logstash是否启动
ps -ef|grep logstash |
Elasticsearch安装
- 解压安装
将Elasticsearch安装包上传到服务器,进行解压
tar -zxvf elasticsearch-7.3.0-linux-x86_64.tar.gz |
- 创建用户
Elasticsearch不能用root用户启动
,创建一个用户(名称随意),并赋予此用户与root同组(因为用root用户解压的包)
useradd nicky |
- 启动
启动Elasticsearch,会遇到如下两个报错问题
elasticsearch需在data目录
和logs目录
中存放与修改数据文件,因此在安装目录下创建data目录
,再赋予data目录和logs目录及其子文件的读写权限
mkdir data |
再次启动Elasticsearch,另起会话窗口执行 curl http://localhost:9200
命令,如出现如下效果,则 Elasticsearch 安装成功。
su - nicky |
Kibana安装
- 解压安装
将Kibana安装包上传到服务器,进行解压
tar -zxvf kibana-7.3.0-linux-x86_64.tar.gz |
- 启动
使用上述新建nicky
用户启动 Kibana (Kibana解压安装情况下,不能使用root用户启动
)
su - nicky |
在浏览器中访问 http://ip:5601
(可使用hostname - I
命令查询IP)
若出现以下界面,则表示 Kibana 安装成功
filebeat安装
- 解压安装
进入安装包所在位置,进行解压
tar -zxvf filebeat-7.3.0-linux-x86_64.tar.gz |
- 添加filebeat命令
先将filebeat命令加入到环境
# ln -s 安装路径/filebeat /usr/bin/ |
- 启动
cd filebeat-7.3.0-linux-x86_64 |
Supervisor安装
上述ELK
的启动是在前台启动
的,意味着如果关闭会话窗口,该组件就会停止导致整个 ELK 平台无法使用,至此使用Supervisor
来管理 ELK 的启停
。首先需要在服务器上安装 Supervisor (安装教程) 。安装成功后,还需要在 Supervisor 的配置文件中配置 ELK 三大组件(其配置文件默认为 /etc/supervisor/supervisord.conf
文件)。
[program:elasticsearch] |
执行sudo supervisorctl reload
即可完成整个 ELK 的启动,而且其默认是开机后台自启
。当然,也可以使用sudo supervisorctl start/stop program_name
来管理单独的应用.
Logstash单服务部署
- 修改Logstash配置
在config/
目录下创建配置文件(名称随意),并使用bin/logstash -f config/配置文件名.conf
命令启动
配置内容如下:
input { |
- 修改Kibana配置
修改配置文件 config/kibana.yml ,指定 Elasticsearch 的信息
。
如果elasticsearch没有设置密码
,密码配置可去掉;
elasticsearch.hosts: "http://localhost:9200" |
- 测试
Elasticsearch默认配置即可;ELK与项目启动后,登录Kibana的web界面,关联Elasticsearch索引
使用Postman请求接口,查看日志(环境内没有安装数据库,让其报个错吧)
项目控制台输出日志(如下三张截图,并非同一时期所截,不影响正常流程)
logstash控制台输出日志
Beats部署
- 修改filebeat配置
filebeat安装目录下,修改filebeat.yml
配置文件
- 修改Logstash配置
配置内容如下:
input { |
- 测试
ELK与项目启动后,关联Elasticsearch (Elasticsearch默认配置即可) 索引,查询结果如下
Nginx代理
ELK配置完之后,有些情况下外网无法连接Kibana,则需要使用Nginx代理到Kibana进行访问
- 安装nginx和http用户认证工具
yum -y install epel-release |
- 修改nginx配置
先备份nginx.conf文件,以防错改
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak |
将location配置部分
,注释掉
创建并编辑kibana.conf配置文件
mkdir /etc/nginx/conf.d/kibana.conf |
内容如下:
server { |
重新加载配置文件,并重启服务
systemctl reload nginx |
在浏览器输入http://nginx服务器ip:8000
, 就可以访问了kibana
基础使用
Filebeat
配置多个日志路径
如需要获取多个日志文件
路径(如tomcat、nginx等等
),只需修改filebeat
和logstash
配置文件即可
- 修改filebeat配置文件
vi 路径/filebeat.yml |
模版内容如下:
filebeat.prospectors: |
- 修改logstash配置文件
以elastic.conf配置文件为例
vi 路径/elastic.conf |
模版内容如下:
input{ |
Logstash
input
input模块支持从多个源收集数据,以下列举几个常用配置
文件
input { |
缓存
Redis 模式
input { |
Kafka 模式
input { |
消息队列
Rabbitmq 模式
input { |
数据库
# MySQL数据库 |
filter
filter模块是非必须
的,input接收到的数据如果需要类型转换
、过滤判断
、增减字段
等操作就需要用到filter模块。如果input得到的数据不需要二次加工可以不使用filter
,直接output到一个输出端。
合理的拆分字段和字段的数据类型转换是制作统计图表的基础,统计图表的制作直接依赖filter处理所产生的字段
。
正则处理插件grok
堪称Logstash中的神器组件,grok内置了丰富的预定义pattern,能够简单方便的匹配复杂的正则目标数据。
grok内置正则表达式文件路径:
/logstash安装路径\vendor\bundle\jruby\x.x\gems\logstash-patterns-core-x.x.x\patterns\grok-patterns
- 基本语法
用%{}
表示一组正则匹配规则
,SYNTAX
是指grok里已经预定义好的正则表达式匹配别名
,SEMANTIC
是指匹配之后准备输出的字段名称
。
%{SYNTAX:SEMANTIC} |
- 自定义
grok组件可以将多组复杂的pattern放到一个文件中,方便修改和管理,比如在/usr/local/logstash-7.3.0/patterns/
目录下,创建一个为test
(文件名随意)的文件。
以nginx日志为例:
23/May/2019:14:40:10 +0800,1558593610.753,1660,0.028,"0.028",647,200,10.16.172.20-"123.126.70.235",POST /330000/v6/feeds/detail/query HTTP/1.1,"app_key_vs=2.6.0&appid=330000&feed_count=10&feed_id=507297347911306752&flyer=1558593610700&idfa=A6719238-5AF6-4B57-B4B6-676B0905704D&log_user_id=248137098937342464&query_type=6&sig=28d2c189144c5380113afff158ea257d&since_time_comment=3000-01-01%2001%3A01%3A01.000&since_time_pure=3000-01-01%2001%3A01%3A01.000",UPS/"10.18.76.18:8080","sns/2.6.0 (com.sohu.sns; build:3; iOS 12.1.4) Alamofire/1.0",-,cs-ol.sns.sohu.com,"01374622096363527552","248137098937342464","872289029629325312@sohu.com","110501" |
nginx 配置的日志格式:
log_format nginx_nobody_log '$time_local,$msec,$request_length,$request_time,"$upstream_response_time",$body_bytes_sent,$status,$remote_addr-"$http_x_forwarded_for",$request,"$request_body",UPS/"$upstream_addr","$http_user_agent",$http_referer,$host,"$http_s_cid","$http_s_pid","$http_s_ppid","$http_p_appid"'; |
编辑test
文件如下:
SNS_NGINX_ACCESS %{HTTPDATE:time_local},%{NUMBER:msec},%{INT:request_length},%{BASE16FLOAT:request_time},"(?:-|%{BASE16FLOAT:upstream_response_time})(,%{NUMBER:upstream_response_time2})?",%{INT:body_bytes_sent},%{INT:status},%{IPORHOST:remote_addr}-"%{DATA:http_x_forwarded_for}(, %{DATA:http_x_forwarded_for2})?",%{WORD:method} %{URIPATH:interface}(?:%{DATA:uri_param})? HTTP/%{NUMBER:http_version},"%{DATA:request_body}",UPS/"%{DATA:upstream_addr}(, %{DATA:upstream_addr2})?","%{DATA:http_user_agent}",%{DATA:http_referer},%{IPORHOST:host},"%{DATA:http_s_cid}","%{DATA:http_s_pid}","%{DATA:http_s_ppid}","%{DATA:http_p_appid}" |
引用pattern文件:
# SNS_NGINX_ACCESS 自定义的pattern别名 |
在线调试
grok规则匹配地址
从Kibana 6.4.0版本开始,Dev Tools
自带了grok调试功能
- 其他配置
filter { |
output
output内输出配置与input内输入配置大同小异,其他中间件配置在此不再累述
output { |
Elasticsearch
Elasticsearch提供了众多的api和丰富的功能;常用的API分为如下几类
- Document APIs :es的文档的CRUD操作相关API
- Search APIs:查询检索相关的API
- Indices APIs:索引管理相关API
- cat APIs:集群健康状态、索引信息、分片信息等等,输出的是在命令行界面下更友好的制表信息
- Cluster APIs:es集群查看和管理配置相关API
以下借助Kibana的Dev Tools
工具来了解一下常用的API使用
获取es信息
- 查看es的基本信息(包括版本号、集群名称、lucene版本号等)
- 查看es对应index的aliases、mappings、settings信息
搜索(Search)
查询可以分别使用URI search
和Request body
两种查询方式
URI search
查询方式,语法参考 search-uri-requestrequest body
查询方式,语法参考 search-request-body
上图返回结果中有一个 _scroll_id
字段,要基于这个游标继续遍历
数据只需要像下面这样,调用 /_search/scroll
接口,将前面返回结果的_scroll_id作为scroll_id参数值
;scroll:5m
表示将当前的scroll_id查询窗口再次延长5分钟
。
GET /_search/scroll |
游标超过时间窗口会自动清理,也可以通过 DELETE /_search/scroll
来清理一个游标
DELETE /_search/scroll |
统计(Count)
统计数量可使用 Count;下右图count
表示查询命中的数量
query
部分es提供了Query DSL查询语法,语法参考 query-dsl
聚合(Aggregation)
统计某索引每天(每小时)的数量、按照某个字段计数等,类似的查询就要用到aggregation聚合查询
- 查询每天请求数量
aggs
:表示聚合查询;day_count
:自定义的一个聚合的名称(aggs可以有多个和多层,所以需要指定一个名称);date_histogram
:表示是一个日期分布器,是按照"@timestamp"
这个日期字段按照1d(1天)
的时间间隔进行分布的;size:0
:表示不返回具体的记录,hits部分是空数组
- 查询日期范围
查询的日期范围,并且只查询@version=1的数量,可以在查询增加query部分,如下
- 查询一天内接口调用次数
使用terms
进行聚合,将aggs部分修改成如下,interface.keyword
就是接口路径(这里的interface.keyword是经过grok插件过滤后的字段
),size:5 表示只展示前面5个(默认是按照doc_count倒序排序)
{ |
- 查询一天内每小时接口调用次数
"aggs": { |
Kibana
通过grok匹配
存储在Elasticsearch中的字段,都是可以使用Kibana的 Discover
菜单的中 “Add a filter” 进行查询
基础查询
两种过滤方式
"字段名"
:可以进行分词查询,如下图中interface字段存储的是/330003/v7/feeds/profile/template
的内容,那么每一个"/"
之间的字符串都可以单独查询,因为"/"是一个默认的分词符号
"字段名.keyword"
:使用interface整体进行查询不支持分词
,使用时Kibana时也会弹出下拉列表。
单字段多词查询
查询一个字段的多个值
可以使用“is one of”
或者 “is not one of”
,用来表示要查询的分词在其中或者不在其中:
多过滤条件查询
进行多个字段查询之间的关系是 and
关系,如下 查询的是“interface包含feeds关键字的并且 appid=330000 并且 status是200的 ”
高级查询
全文搜索
直接搜索框输入查询内容:content 或 "${content}"
,如果不写引号
,那么搜索内容将按照分词处理
,不区分内容顺序
字段搜索
通配符
?
:匹配单个字符,如app?d
*
:匹配0到多个字符,如searc*h
通配符不能做为第一个字符,如*test,?test
模糊搜索
~
:在单词后面加上~
启用模糊搜索,可搜到近似单词;还可指定相似度cromm~1
(默认2),越大值越接近搜索的原始值
近似搜索
在短语后加上~
,可以搜到被隔开或顺序不同的单词
逻辑操作
逻辑符 +、-
- +:搜索结果中必须包含此项
- -:不能含有此项,如
+appid -s-ppid aaa bbb ccc
结果中必须存在appid,不能有s-ppid,剩余部分尽量都匹配到
逻辑符 AND、OR
((quick AND fox) OR (brown AND fox) OR fox) AND NOT news
范围搜索
有如下写法:
- [1,5},含1但不含5
- age:>10
- age:<=10
- age:(>=10 AND <20)
- age:(+>=10 +<20)
转义特殊字符
以下字符搜索时需用\
转义
+ - = && || > < ! ( ) { } [ ] ^ " ~ * ? : \ / |
数据统计
若想清楚某个接口最近1小时都有哪些用户和都来自哪些城市。这里就用到了Kibana Visualize
。
选择 Data Table
数据表视图,它可以下载成csv格式的文件。
选择想要查询的索引
趋势图表
和数据表
都分为Metrics
和Buckets
两部分:
- Metrics:对Buckets里面的值做什么统计操作
- Buckets:对值的设置
下图的DataTable为查询接口
包含"repost"
字段,最近15分钟内 前10个调用最多的用户id。
在Bucket
上增加http_s_pid.keyword
和geoip.city_name
, 数据表 2 列是在 1 列的前提下查询出来的城市名称
给每个metric和bucket起别名
,然后点击Raw
或者Formatted
将查询到的数据下载
成csv文件
趋势图绘制
比如想要了解某些接口平均响应时间
和50%,75%,95%的响应时间走向
。就可以使用Line视图
想要进行均值,最大,最小,百分比分布等这些统计,必须得有
Number类型
的字段,如果前期logstash
没有进行合适的数据类型转换,就需要在Kibana对应索引下
的Script Field
来实现基于某个字段的类型转换(Script Field中需要编写Script语句,在此不做详解)
统计最近1小时包含timeline/template的接口调用数量折线图。想要统计响应时间,就要先修改Metric的统计方式。
增加两个Y-Axis
的metric,分别是对 request_time 求均值
和对 request_time 求百分比
分布