-
ELK日志收集架构:
-
第一层、数据采集层
数据采集层位于最左边的业务服务器集群上,在每个业务服务器上面安装了filebeat做日志收集,然后把采集到的原始日志发送到Kafka+zookeeper集群上。
-
第二层、消息队列层
原始日志发送到Kafka+zookeeper集群上后,会进行集中存储,此时,filbeat是消息的生产者,kafka作为消息队列进行存储消息,存储的消息可以随时被消费。
-
第三层、数据分析层
Logstash作为消费者,会去Kafka+zookeeper集群节点实时拉取原始日志,然后将获取到的原始日志根据规则进行分析、清洗、过滤,最后将清洗好的日志转发至Elasticsearch集群。
-
第四层、数据持久化存储
Elasticsearch集群在接收到logstash发送过来的数据后,执行写磁盘,建索引库等操作,最后将结构化的数据存储到Elasticsearch集群上。
-
第五层、数据查询、展示层
Kibana是一个可视化的数据展示平台,当有数据检索请求时,它从Elasticsearch集群上读取数据,然后进行可视化出图和多维度分析。
-
Filebeat:
角色分类:
- Input(新版)/ Prospecto(旧版):[勘探者]负责管理收割机并找到所要读取的源,在此处配置源日志路径。
- Harvester:[收割者]读取源路径log文件的内容,每个Harvester会逐行读取各个文件,并将文件内容发送到指定输出中。Harvester会负责打开和关闭文件如果文件在收集过程中被删除或重命名,Filebeat 会继续读取该文件。这会产生副作用,即磁盘上的空间会被保留,直到收割机关闭。
Filebeat 如何保持文件状态?
将文件状态记录在注册文件中(默认在/var/lib/filebeat/registry)。此状态可以记住Harvester收集文件的偏移量。
将状态刷新到注册表文件中的磁盘。该状态用于记住收割机读取的最后一个偏移量offset,并确保发送所有日志行。(注册表记录重建状态)
当输出无法访问,filebeat会跟踪发送的最后一行,在输出可以访问后继续读文件。
每个Input为它找到的每个文件保留一个状态,前提是Filebeat一直运行。由于文件可以重命名或移动,文件名和路径不足以识别文件。对于每个文件,Filebeat 存储唯一标识符以检测之前是否收集了文件。
如果在收割机关闭时移动或删除文件,则 Filebeat 将无法再次拾取该文件,收割机尚未读取的任何数据都将丢失。
Filebeat 如何确保至少一次交付?
将每个事件的传递状态存储在注册表文件中( Filebeat 将它收集的每个文件的状态存储在注册表中)
任何发送到输出但在 Filebeat 关闭之前未确认的事件,将在 Filebeat 重新启动时再次发送。这可确保每个事件至少发送一次,(最终可能重复发送)可通过设置shutdown_timeout选项将 Filebeat 配置为在关闭之前等待特定时间,时filebeat在真正关闭前确认事件已经收到。
一些常见codecs处理:
- json:使用json格式对数据进行编码/解码。
- multiline:将汇多个事件中数据汇总为一个单一的行。在此处对日志进行多行处理,防止在logstash处理会导致数据损坏。
配置信息(Filebeat只负责收集和多行处理,没有对日志信息作其他操作):
Input:输入类型type、源日志路径paths、扩展字段(即后续kafka的topic)fields 。
Output:主机组hosts、主题topic(此时output到kafka)、分片partition.hash 。
-
Kafka:
为什么选择kafka?
消息传递模式分为两种:点对点传递模式、发布-订阅模式
点对点模式:到达消息队列的每一条消息只能被消费一次,消费完该条数据从消息队列中删除,生产者发送一条消息到queue,只有一个消费者能收到。
Kafka就是一种发布-订阅模式。消息被持久化到一个topic中。与点对点消息系统不同的是,消费者可以订阅一个或多个topic,消费者可以消费该topic中所有的数据,同一条数据可以被多个消费者消费,数据被消费后不会立马删除。
kafka术语解释:
Broker:kafka集群服务器节点node,即主机节点,broker存储topic的数据,(当topic有n个partiton,集群有n个broker,每个broker存该topic的一个partition,其他数目另外策略)【建议:broker数大于某topic的paititon数】
Topic:发送到kafka集群的消息一个大类别,逻辑上一个topic的消息保存于一个或多个broker,物理上
不同topic
(可能是同topic不同partition)的消息分开存储????Partition:topic切分为一个或多个partition,切分提高了kafka的吞吐率。每个partition中的数据使用多个segment文件存储。
Partition:单个partition中的数据是有序的,不同partition间的数据丢失了数据的顺序。如果topic有多个partition,消费数据时就不能保证数据的顺序。在需要严格保证消息的消费顺序的场景下,需要将partition数目设为1。
Segment:文件存储单位,直接保存partiton数据。
Producer:broker接收到生产者Producer发送的消息后,broker将该消息追加到当前用于追加数据的segment文件中。生产者也可以指定数据存储的partition。此处生产者Producer是Filebeat。
Consumer:消费者,对应producer生产者。有对应的consumer group消费者组,zookeeper会在组变化时进行rebalance。此处的消费者Consumer是Logstash。
Leader:每个partition有多个副本,其中有且仅有一个作为Leader,Leader是当前负责数据的读写的partition。
Follwer:Follower跟随Leader,所有写请求都通过Leader路由,数据变更会广播给所有Follower,Follower与Leader保持数据同步。
机制:leader失效,follower选举新leader,通过zookeeper管理集群配置。follower卡住或者同步太慢,把此follower删掉,重新创建一个新follower。(leader和follwer基于zookeeper实现)
Offset:offset值表示在分区partition中的位置。
kafka工作机制:
每条消费都必须指定它的topic。
partiton顺序写磁盘,每条消息append到该partiton上。
kafka的pull模式,concumer消费者必须主动从kafka拉(pull)取数据、订阅数据。
Kafka提供两种策略删除旧数据。一是基于时间,二是基于Partition文件大小。
每个partiton相当于一个文件夹,里面存储这个partition的消息和索引。超过一个的partiton会失去数据的顺序。
配置信息:
- 配置文件配置保留数据策略log,分区数partition,zk监听地址connection,kafka唯一标识码broker.id。
- 提前在命令行创建写入kafka的主题topic、分区数partition以及副本数replication-factor。
-
Zookeeper:
功能作用:
在基于 Kafka 的分布式消息队列中,ZooKeeper 的作用有:broker 注册、topic 注册、消费组的控制、producer 和 consumer 负载均衡、维护 partition 与 consumer 的关系、记录消息消费的进度以及 consumer 注册等。
-
Logstash:
内部结构图:
角色类型:
- Input :从kafka集群订阅消息。(logstash 管道中的每个输入阶段都在自己的线程中运行)
- Filter:过滤器(做正则匹配和加解码)
- Output:输出es集群集群
配置信息:
配置input:kafka集群地址,组group id, kafka中的消费主题topics。
配置filter:过滤器,配置json解码,grok正则,ruby匹配。
配置output:es集群地址,es存放索引。
使用 Grok 正则过滤器例子:
- 原日志格式
55.3.244.1 GET /index.html 15824 0.043
- Grok match匹配
%{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration} #格式转换(IP WORD 这些是提前设定的正则表达式)
- 结果输出
client: 55.3.244.1
method: GET
request: /index.html
bytes: 15824
duration: 0.043
-
Elasticsearch(简称ES):
功能作用:
一个分布式的实时文档存储,每个字段可以被索引与搜索
一个分布式实时分析搜索引擎
ES术语解释:
node 节点:一个运行中的Elasticsearch 实例称为一个节点。(分为master节点,data节点,client节点)
cluster 集群:集群是由一个或者多个拥有相同 cluster.name配置的节点组成, 它们共同承担数据和负载的压力。
shard 分片:分片是数据的容器,文档保存在分片内,分片又被分配到集群内的各个节点里。分片 是一个底层的工作单元,它仅保存了全部数据中的一部分。它本身就是一个完整的搜索引擎。
文档:它是指最顶层或者根对象, 这个根对象被序列化成 JSON 并存储到 Elasticsearch 中,指定了唯一 ID。
文档被存储和索引到分片内。应用程序是直接与索引而不是与分片进行交互。
一个文档不仅仅包含它的数据 ,也包含元数据—— 有关文档的信息。 三个必须的元数据元素如下:
_index 索引名
文档在哪存放 [一个索引应该是因共同的特性被分组到一起的文档集合]
_type 索引类型
文档表示的对象类别
_id 文档名
它和 _index 以及 _type 组合就可以唯一确定 Elasticsearch 中的一个文档,生成一个文档
- 文档是不可变的:他们不能被修改,只能被替(当对文档作修改时底层是生成新文档,然后做新的索引)
ES集群健康状态:
- green
所有的主分片和副本分片都正常运行。
- yellow
所有的主分片都正常运行,但不是所有的副本分片都正常运行。
- red
有主分片没能正常运行。
(测试:curl -X GET "localhost:9200/_cluster/health?pretty”)
查看 status 字段中展示为 green 、 yellow 或者 red
ES集群内部工作操作:
- 新建、索引和删除 请求都是写操作(在主分片上面完成修改之后,被复制到相关的副本分片)
在客户端收到成功响应时,文档变更已经在主分片和所有副本分片执行完成,变更是安全的。
- 取回单个文档(读不一定要在主分片读,可以在副本分片上读取文档,负载均衡读)
- 作为用户,我们可以将请求发送到 集群中的任何节点 ,包括主节点。 每个节点都知道任意文档所处的位置,并且能够将我们的请求直接转发到存储我们所需文档的节点
ES集群配置:
- Elasticsearch 默认被配置为使用单播发现,以防止节点无意中加入集群。
- ES集群要有同样的 cluster.name配置,它就会自动发现集群并加入到其中。 但是在不同机器上启动节点的时候,为了加入到同一集群,你需要配置一个可连接到的单播主机列表[discovery.zen.ping.unicast.hosts#设置集群中master节点的初始列表,可以通过这些节点来自动发现新加入集群的节点] 。
ES数据结构:
Elasticsearch 使用一种称为倒排索引的结构。
一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,有一个包含它的文档列表。
倒排索引包含一个有序列表,列表包含所有文档出现过的不重复个体,或称为 词项 ,对于每一个词项,包含了它所有曾出现过文档的列表。
例子:
- <u>The quick brown fox jumped over the lazy dog</u>
- <u>Quick brown foxes leap over lazy dogs in summer</u>
Term Doc_1 Doc_2 #维护的文档列表
Quick | | X
The | X |
brown | X | X
dog | X |
dogs | | X
fox | X |
foxes | | X
in | | X
jumped | X |
lazy | X | X
leap | | X
over | X | X
quick | X |
summer | | X
the | X |
之后在根据近义词,大小写,单复数等等的相关性,对文档列表进行标准化
Term Doc_1 Doc_2 #维护的标准化文档列表
brown | X | X
dog | X | X
fox | X | X
in | | X
jump | X | X
lazy | X | X
over | X | X
quick | X | X
summer | | X
the | X | X
-
Kibana:
功能作用:
数据查询,数据展示,导出数据信息
语法:
url拆分:http_host 域名/upstream_name(服务名)/具体路径 #(upstream最终一定能到达)
url拆分:http_host 域名/request(请求详情) #(request不一定能全部到达)
status: 状态码
x-user-id: 用户ID
remote_addr: 远程IP
http_x_forwarded_for : 远程IP
request_api: 请求的api,不带参数
导出不需要统计的数据:
Step 1:
Step 2:
Step 3:
注意:从kibana中导出的数据有大小限制,此处最大支持导出文件大小500MB,可在配置文件修改maxsize,但是不建议过大,设置过大值可能会导致kibana服务器崩溃。
导出统计的数据:
步骤:visualize--加号(➕)----Data----Data Table----new search----选择检索的日志(index:ngxlog-public-*)----Metrics(选择监控项)----Buckets(选择切割方式)