收集
传输
存储
分析
警告
介绍
组成
ElasticSearch
Logstash
Kibana
FileBeat
工作原理
文档
elastic中文社区
Elasticsearch
Logstash
Kibana
Filebeat
可扩展性
高可用
节点(Node)
主节点(Master Node)
请求
索引(index)
分片(shard)
数据分布示例
例如一个索引中分配了3个主分片(默认是5个)和一个副本
一个节点
3个主分片分布在主节点
集群健康情况
在同一个节点上保存相同的数据副本没有必要,如果这个节点故障了,所有的副本也会丢失
两个节点
3个主分片分布在主节点,3个复制分片分布在节点2
集群健康情况
三个节点
分片本身就是一个完整成熟的搜索引擎,它可以使用单一节点的所有资源。使用这6个分片(3主+3复制)最多可以扩展到6个节点,每个节点上有一个分片,这样每个分片就可以100%使用这个节点的资源了
服务端口
9200
9300
布署java环境(略)
安装elasticsearch
(所有节点)
创建用户
解压
创建数据目录
授权
配置本地解析
(所有节点)
配置es-master
1.1.1.11
cluster.name: es-cluster # 集群名称,各节点配成相同的集群名称
node.name: es1 # 节点名称,各节点配置不同。
node.master: true # 指示某个节点是否符合成为主节点的条件
node.data: true # 指示节点是否为数据节点。数据节点包含并管理索引的一部分
path.data: /data/es/data # 数据存储目录
path.logs: /data/es/logs # 日志存储目录
bootstrap.memory_lock: true # 内存锁定,是否禁用交换
network.host: 0.0.0.0 # 绑定节点IP
http.port: 9200 # rest api端口
discovery.zen.ping.unicast.hosts: [“es1”, “es2”] #集群节点IP或主机
http.cors.enabled: true #允许http跨域访问
http.cors.allow-origin: “*” #允许的源地址
配置es-data
1.1.1.12
设置JVM堆大小
(所有节点)
sed -i ‘s/-Xms1g/-Xms4g/’ /es/config/jvm.options
sed -i ‘s/-Xmx1g/-Xmx4g/’ /usr/local/es/config/jvm.options
注意
修改资源限制
[root@es ~]# echo “vm.max_map_count=262144” >> /etc/sysctl.conf
[root@es es]# sysctl -p
vm.max_map_count = 262144
启动服务
先启动master, 再启动data
su - es -c ‘/usr/local/es/bin/elasticsearch -d’
-c
-d
验证
查看端口
查看服务情况
查看集群
健康状况
curl 1.1.1.11:9200/_cluster/health?pretty
curl 1.1.1.12:9200/_cluster/health?pretty
字段
status
green
yellow
red
number_of_nodes、number_of_data_nodes
active_primary_shards
active_shards
relocating_shards
initializing_shards
unassigned_shards
安装问题
1
报错
解决
2
报错
解决
es soft nofile 65536 #第一列用户名
es hard nofile 65536
- ulimit -n
- 查看当前用户的进程最大可同时打开文件数
- ulimit -a
- 查看所有限制
- 3
- 报错
- memory locking requested for elasticsearch process but memory is not locked
- 请求锁内存失败,系统默认能让进程锁住的最大内存为64k
- 解决
- # vim /etc/security/limits.conf
es soft memlock unlimited
es hard memlock unlimited
- 4
- 报错
- max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
- es用户拥有的内存权限太小了,至少需要262114
- 解决
- echo vm.max_map_count=262144 >> /etc/sysctl.conf
- sysctl -p
- 从配置文件"/etc/sysctl.conf"加载内核参数设置
- 使用问题分析实例
一个10节点的ES集群,某天碰到问题了,集群健康状态看起来像是这样:
{
"cluster_name": "elasticsearch_zach",
"status": "red",
"timed_out": false,
"number_of_nodes": 8,
"number_of_data_nodes": 8,
"active_primary_shards": 90,
"active_shards": 180,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 20
}
我们集群是 red ,意味着我们缺数据(主分片 + 副本分片)了。
我们知道我们集群原先有 10 个节点,但是在这个健康状态里列出来的只有 8 个数据节点。
有两个数据节点不见了。我们看到有 20 个未分配分片。
这就是我们能收集到的全部信息。那些缺失分片的情况依然是个谜:
我们是缺了 20 个索引,每个索引里少 1 个主分片?
还是缺 1 个索引里的 20 个主分片?
还是 10 个索引里的各 1 主 1 副本分片?
具体是哪个索引?
要回答这个问题,我们需要使用 level 参数让 cluster-health 答出更多一点的信息:
GET _cluster/health?level=indices
{
"cluster_name": "elasticsearch_zach",
"status": "red",
"timed_out": false,
"number_of_nodes": 8,
"number_of_data_nodes": 8,
"active_primary_shards": 90,
"active_shards": 180,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 20
"indices": {
"v1": {
"status": "green",
"number_of_shards": 10,
"number_of_replicas": 1,
"active_primary_shards": 10,
"active_shards": 20,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 0
},
"v2": {
"status": "red",
"number_of_shards": 10,
"number_of_replicas": 1,
"active_primary_shards": 0,
"active_shards": 0,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 20
},
"v3": {
"status": "green",
"number_of_shards": 10,
"number_of_replicas": 1,
"active_primary_shards": 10,
"active_shards": 20,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 0
},
....
}
}
我们可以看到 v2 索引就是让集群变 red 的那个索引。
由此明确了,20 个缺失分片全部来自这个索引。
我们还可以看到这个索引曾经有 10 个主分片和一个副本,而现在这 20 个分片全不见了。
可以推测,这 20 个索引就是位于从我们集群里不见了的那两个节点上。
1.1.1.11
下载
head插件
node
安装
解压工具
node环境
export NODE_HOME=/usr/local/node
export NODE_PATH= N O D E H O M E / l i b / n o d e m o d u l e s e x p o r t P A T H = NODE_HOME/lib/node_modules export PATH= NODEHOME/lib/nodemodulesexportPATH=NODE_HOME/bin:$PATH
- . /etc/profile.d/node.sh
- node -v
- head
- unzip elasticsearch-head-master.zip
- mv elasticsearch-head-master /usr/local
- 注意不能安装在es的插件目录plugins中
- cd /usr/local/elasticsearch-head-master
- npm install -g cnpm --registry=https://registry.npmmirror.com/
- 安装cnmp工具
- cnpm install -g grunt-cli
- grunt -version
- cnpm install
服务端口
配置
hostname: '1.1.1.11', #port前面加上主机IP
port: 9100,
启动
grunt server &
使用
http://1.1.1.11:9100
连接集群
创建索引
默认为5分片1副本,最新版本貌似默认1分片,可自定义创建
默认
curl -X PUT “1.1.1.11:9200/twitter?pretty”
自定义
删除索引
curl -X DELETE “1.1.1.11:9200/twitter?pretty”
网页操作
简介
文档
官方文档
Logstash 参考
标准日志grok正则
常用filter插件
服务端口
input
filter
output
1.1.1.12
安装
配置
http.host: “0.0.0.0”
- ln -s /usr/local/logstash/bin/logstash /usr/bin/logstash
- 软链接
- cd /usr/local/logstash/config
- 进入配置目录
命令
logstash -f syslog-test.conf -t
logstash -f syslog-test.conf
选项
-f file
-t
插件](https://www.elastic.co/guide/en/logstash/6.4/input-plugins.html)
stdin
从标准输入读取
file
从本地文件中读取
配置项
path
start_position
起始位置,beginning或end,类型为字符串
beginning
end(默认)
例
syslog
接收系统日志信息(默认监听端口514), 并解析成RFC3164格式
例
input {
syslog {}
}
采集端系统日志配置
. @1.1.1.12
- systemctl restart rsyslog
beat
接收来自Filebeat的事件
配置项
port
例
redis
kafka
grok
介绍
配置项
match
语法规则
内置模式
例(httpd日志)
过滤IP
内置
自定义
结构化
内置
input { stdin {} }
filter {
grok {
remove_field => [“message”]
match => {“message” => “%{COMBINEDAPACHELOG}”}
}
}
output { stdout {} }
- 自定义
- # vim grok2.conf
input { stdin {} }
filter {
grok {
remove_field => [“message”]
patterns_dir => [“/logstash/patterns/”]
match => {“message” => “%{APACHE_LOG}”}
}
}
output { stdout {} }
- # vim /logstash/patterns/httpd
IPADDR (\d+.){3}\d+
ALL .*
UPPER [A-Z]+
NUMBER \d+
APACHE_LOG %{IPADDR:ip} .* [%{ALL:time}] “(%{UPPER:method} %{ALL:url} HTTP/%{ALL:http_version}|-)” %{NUMBER:http_code} %{NUMBER:bytes} “(%{ALL:http_referer}|-)” “(%{ALL:http_agent}|-)”
mutate
数据修改插件,提供了丰富的基础类型数据处理能力,包括重命名、删除、替换、修改日志事件中的字段
convert
gsub
lowercase
filter {
grok {
match => {“message” => “%{COMBINEDAPACHELOG}”}
}
mutate { #执行顺序从上到下
rename => [“clientip”,“ip”] #将client字段重命名为ip
update #更新某个字段的内容, 如果字段不存在, 不会新建
replace #替代某个字段的内容, 如果字段不存在, 会新建
convert => [“response”,“integer”,“bytes”,“integer”] #将response和bytes数据类型转换为整型
gsub => [“clientip”,“.”,““] #将clientip字段的值中”.“替换成””
uppercase #将小写字母全部转换成大写
lowercase => [“verb”] #将verb字段的值中大写字母转换为小写
strip #去除字段前后的空格
remove_field => [“message”] #删除message字段
split => [“clientip”,“.”] #将ip地址以"."为分隔符分割
join #合并数组中的元素
merge #合并数组或哈希字段
}
}
geoip
date
时间戳
@timestamp
timestamp
问题
data插件作用
配置
时区
clone
drop
通用配置项
可用于所有的filter插件
remove_field
remove_tag、periodic_flush、id、enable_metric、add_tag、add_field
stdout
elasticsearch
file
mongodb
redis
graphite
statsd
kafka
nginx
logstash
input {
file {
path => “/var/log/nginx/access_json.log”
codec => “json” #输入预定义好的JSON数据, 可以省略filter/grok 配置, 从而减轻logstash的负载
start_position => “beginning”
}
}
output {
elasticsearch {
hosts => [“1.1.1.11:9200”]
index => “nginx-log-%{+YYYY.MM.dd}”
}
}
1.1.1.11
server.port: 5601
server.host: “0.0.0.0”
elasticsearch.url: “http://1.1.1.11:9200” #es集群任意节点的套接字
logging.dest: /usr/local/kibana/logs
浏览器访问:1.1.1.11:5601
添加索引
索引管理
查看索引
filebeat.inputs:
cd /usr/local/filebeat
./filebeat -c filebeat.yml &
标准输出
output.console:
enable: true
发送到ES(默认)
output.elasticsearch:
hosts: [“1.1.1.11:9200”] #es集群节点的套接字
发送到kafka
output.kafka:
hosts: [“1.1.10.1:9092,1.1.10.2:9092,1.1.10.3:9092”]
topic: ‘nginx’
发送到logstash
output.logstash:
hosts: [“1.1.1.12:5044”] #logstash监听套接字
采集处理
单个日志
filebeat
type: log
paths:
output.logstash:
hosts: [“1.1.1.12:5044”]
- logstash
- input {
beats {port => 5044}
}
采集处理
多个日志
filebeat
type: log
paths:
type: log
paths:
output.logstash:
hosts: [“1.1.1.12:5044”]
- logstash
- input {
beats {port => 5044}
}
filter {
if [filetype] == “web” {
grok {
match => {
“message” => “%{COMBINEDAPACHELOG}”
}
remove_field => [“message”,“beat”,“offset”,“tags”,“prospector”]
}
}
}
output {
if [filetype] == “web” {
elasticsearch {
hosts => [“1.1.1.11:9200”] #es集群节点的套接字
index => “http-%{+YYYY.MM.dd}” #索引名自定义
}
}
else if [filetype] == “sys” {
elasticsearch {
hosts => [“1.1.1.11:9200”]
index => “syslog-%{+YYYY.MM.dd}”
}
}
}
作用
建议
设置
作用
建议
设置
集群部署建议
架构图
分层
数据采集层
数据处理层,数据缓冲层
数据转发层
数据持久化存储
数据检索,数据展示
是什么
使用场景
应用耦合
异步处理
限流削峰
优点
解耦
冗余
扩展性
峰值处理
可恢复性
顺序保证
缓冲
异步通信
模式
点对点模式
角色
特点
发布/订阅模式
角色
特点
常用开源消息队列
Kafka
RocketMQ
RabbitMQ
官网
概述
AMQP协议
基本概念
消费者(Consumer)
生产者(Producer)
AMQP服务端(broker)
主题(Topic)
分区(Partition)
备份(Replication)
支持的客户端语言
服务端口
官网
概述
分布式配置管理
kafka
服务端口
2181
2888
3888
集群
zookeeper
准备
软件版本
服务器
布署java环境
安装zookeeper
修改配置文件
dataDir=/data/zookeeper/data #快照日志的存储路径
dataLogDir=/data/zookeeper/datalog #事物日志的存储路径,默认存储到dataDir制定的目录(会严重影响zk的性能,当zk吞吐量较大的时候,产生的事物日志、快照日志太多)
server.1=1.1.1.21:2888:3888 #server.1 这个1是服务器的标识也可以是其他的数字, 表示这个是第几号服务器,用来标识服务器,这个标识要写到数据目录下面myid文件里
server.2=1.1.1.22:2888:3888
server.3=1.1.1.23:2888:3888
- 其他默认配置注释
tickTime=2000 #Zookeeper服务器之间或客户端与服务器之间维持心跳的时间间隔
initLimit=10 #这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,
#而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。
#当已经超过 5个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,
#那么表明这个客户端连接失败。总的时间长度就是 10*2=20 秒
syncLimit=5 #这个配置项标识 Leader 与Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,
#总的时间长度就是5*2=10秒
dataDir=/data/zookeeper/data #快照日志的存储路径
dataLogDir=/data/zookeeper/datalog #事物日志的存储路径,如果不配置这个那么事物日志会默认存储到dataDir制定的目录
#这样会严重影响zk的性能,当zk吞吐量较大的时候,产生的事物日志、快照日志太多
clientPort=2181 #这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求
server.1=192.168.10.21:2888:3888
server.2=192.168.10.22:2888:3888
server.3=192.168.10.23:2888:3888
#server.1 这个1是服务器的标识也可以是其他的数字, 表示这个是第几号服务器,用来标识服务器,这个标识要写到数据目录下面myid文件里
#192.168.10.21为IP地址,第一个端口是leader和follower之间的通信端口,默认是2888,服务启动后,只有leader会监听这个端口
#第二个端口是leader选举的端口,集群刚启动的时候选举或者leader挂掉之后进行新的选举的端口默认是3888
创建数据目录及服务器id
mkdir /data/zookeeper/data{,log} -p
echo 1 > /data/zookeeper/data/myid
启动服务
/usr/local/zookeeper/bin/zkServer.sh start
/usr/local/zookeeper/bin/zkServer.sh status
netstat -tanp |grep -E “2888|3888”
jps
重要说明
myid和server.myid
conf/zoo.cfg
conf/log4j.properties
bin/zkServer.sh
bin/zkEnv.sh
zookeeper不会主动的清除旧的快照和日志文件,这个是操作者的责任
清理方法
kafka
环境
已经搭建好的zookeeper集群(虽然kafka中集成了zookeeper,但还是建议使用独立的zk集群)
软件版本
安装kafka
创建数据目录
修改配置文件
broker.id=1 #当前机器在集群中的唯一标识,和zookeeper的myid性质一样
listeners=PLAINTEXT://1.1.1.21:9092 #监听套接字,每台服务器独立
log.dirs=/data/kafka-logs #消息存放的目录,多个目录’,'分隔,num.io.threads要大于这个目录的个数,如果配置多个目录,新创建的topic把消息持久化在分区数最少那一个目录中
num.partitions=1 #默认的分区数,一个topic默认1个分区数
default.replication.factor=2 #kafka保存消息的副本数
zookeeper.connect=1.1.1.21:2181,1.1.1.22:2181,1.1.1.23:2181 #zookeeper集群
- 其他默认配置注释
broker.id=1 #当前机器在集群中的唯一标识,和zookeeper的myid性质一样
listeners=PLAINTEXT://192.168.10.21:9092 #监听套接字
num.network.threads=3 #这个是borker进行网络处理的线程数
num.io.threads=8 #这个是borker进行I/O处理的线程数
socket.send.buffer.bytes=102400 #发送缓冲区buffer大小,数据不是一下子就发送的,先回存储到缓冲区了到达一定的大小后在发送,能提高性能
socket.receive.buffer.bytes=102400 #kafka接收缓冲区大小,当数据到达一定大小后在序列化到磁盘
socket.request.max.bytes=104857600 #这个参数是向kafka请求消息或者向kafka发送消息的请请求的最大数,这个值不能超过java的堆栈大小
log.dirs=/data/kafka-logs #消息存放的目录,这个目录可以配置为“,”逗号分割的表达式,上面的num.io.threads要大于这个目录的个数
#如果配置多个目录,新创建的topic把消息持久化在分区数最少那一个目录中
num.partitions=1 #默认的分区数,一个topic默认1个分区数
num.recovery.threads.per.data.dir=1 #在启动时恢复日志和关闭时刷新日志时每个数据目录的线程的数量,默认1
offsets.topic.replication.factor=2
transaction.state.log.replication.factor=1
transaction.state.log.min.isr=1
log.retention.hours=168 #默认消息的最大持久化时间,168小时,7天
message.max.byte=5242880 #消息保存的最大值5M
default.replication.factor=2 #kafka保存消息的副本数
replica.fetch.max.bytes=5242880 #取消息的最大字节数
log.segment.bytes=1073741824 #这个参数是:因为kafka的消息是以追加的形式落地到文件,当超过这个值的时候,kafka会新起一个文件
log.retention.check.interval.ms=300000 #每隔300000毫秒去检查上面配置的log失效时间,到目录查看是否有过期的消息如果有,删除
zookeeper.connect=192.168.10.21:2181,192.168.10.22:2181,192.168.10.23:2181
zookeeper.connection.timeout.ms=6000
group.initial.rebalance.delay.ms=0
启动kafka
/usr/local/kafka/bin/kafka-server-start.sh /usr/local/kafka/config/server.properties &
jps
验证
创建topic
创建发布者
创建订阅者
topic、发布者、订阅者在kafka集群中任意服务器上创建均可
其他操作
查看所有topic
查看指定topic的详细信息
删除topic
filebeat->logstash->kafka
input {
beats {
port => 5044
}
}
filter {
grok {
match => {
“message” => “%{COMBINEDAPACHELOG}”
}
remove_field => [“message”,“beat”,“offset”,“tags”,“prospector”]
}
}
output {
kafka {
bootstrap_servers => “1.1.1.21:9092,1.1.1.22:9092,1.1.1.23:9092”
topic_id => “httpd-log”
compression_type => “snappy”
codec => “json”
}
}
filebeat.inputs:
input {
kafka {
bootstrap_servers => “1.1.1.21:9092”,“1.1.1.22:9092”,“1.1.1.23:9092”
topics => “nginx-access-log”
auto_offset_reset => “earliest”
codec => “json”
decorate_events => true
}
}
filter {
grok {
match => {“log” => “%{COMBINEDAPACHELOG} %{QS:x-forwarded-for}”}
remove_field => [“error”,“beat”,“offset”,“auth”,“ident”,“log”]
}
}
output{
elasticsearch {
hosts => [“1.1.1.11:9200”]
index => “nginx-access-log-%{+YYYY.MM.dd}”
}
}