JoyLau's Blog

JoyLau 的技术学习与思考

前言

好久不用 mybatis 了,今天突然遇到了一个时间参数的格式化问题…..
mysql 后台取出的时间格式的字段,传到前台变成了时间戳
一下就想到有一个注解进行格式化
可是半天想不到那个注解怎么写的了,于是一顿查

记下来

以前经常使用的注解,现在都忘了,得记下来

  1. @JsonFormat(pattern=”yyyy-MM-dd HH:mm:ss”,timezone=”GMT+8”) : 后台 Date 类型转时间字符串,注意时区 (后台 -> 前台)
  2. @DateTimeFormat(pattern=”yyyy-MM-dd HH:mm:ss”) :前台时间格式参数转为 javabean 的 Date 类型 (前台 -> 后台)
  3. @JSONField(name=”end_time”, format=”yyyy-MM-dd HH:mm:ss”) : fastjson 专用,定义json 的 key,还有时间的格式化,也可以分别在 get set 方法上注解

前言

一般我们搭建起来的 es 集群都可以通过默认的 9200 端口来进行 API 访问,这在局域网上没有什么大问题,如果说搭建的环境在公网上,这将埋下巨大的隐患,因为任何人都可以操作 API 来进行增删改查,这是多么的恐怖!!

说明

  1. 集群环境: elasticsearch 5.3.0;centos 7.2
  2. 集群公网环境

解决方案

elasticsearch 集群搭建完成后,通过制定的端口都可以访问,但是实际情况中,我们并不想这样。我们可能想只有固定的ip地址才能访问,或者需要用户名、密码才能访问
对于如何控制 Elasticsearch 的安全性,我详细查了下资料,现有如下解决方式

  1. 官方的 x-pack 插件,收费的,一下子就觉得用不了了,截止现在(2018年5月21日16:23:19),有最新消息,在 ElasticON 2018 的开幕主题演讲中,x-pack 负责人在博客宣布将开放 X-Pack的代码,但是现在为止只是第一阶段完成,
    最后在博客中宣布在6.3版本,其中免费的X-Pack功能将包含在Elastic Stack的默认发行版中,所以说现在没戏

  2. 官方推荐的shield插件,再5.x的版本后已经集成到 x-pack里了,版本不适合,不用

  3. elasticsearch-http-basic 插件, 已经不支持 5.x的版本了,没法用

  4. ReadonlyREST : 官网地址: https://readonlyrest.com/download/ elasticsearch 版的插件,是免费的, kibana 的插件是收费的,此法可用

  5. 使用 nginx 的 http-basic,可用

ReadonlyREST 插件的使用

  1. 官网选择 elasticsearch 的版本,填写邮箱地址,收到邮件后下载插件文件
    注意:只能通过官网填写邮箱的方式来进行下载,注意看的话,下载的地址后面有校验参数
  2. 运行 bin/elasticsearch-plugin install file:///tmp/readonlyrest-1.16.19_es5.3.0.zip 安装插件,注意是 file:// 再加上绝对路径
    卸载插件 bin/elasticsearch-plugin remove readonlyrest
  3. 配置文件 readonlyrest.yml,这个比较坑,插件生成好之后,居然不生成 readonlyrest.yml,还需要我们自己配置,还不知道需要配置什么东西,没办法,只能去 github 上查看文档,
    文档地址: https://github.com/beshu-tech/readonlyrest-docs/blob/master/elasticsearch.md
  4. 文档说了很多,我找了半天才找到我需要的配置:
1
2
3
4
5
6
7
readonlyrest:
prompt_for_basic_auth: true

access_control_rules:

- name: "::ADMIN::"
auth_key: admin:12333

此时启动 elasticsearch, 再次访问 localhost:9200 就会弹出输入用户名和密码的窗口,此时输入 admin/12333 即可看到接口信息,请求成功后,在日志里会看到 ALLOWED by { name: ‘::PERSONAL_GRP::’, p。。。 的日志信息。
想要屏蔽这样的日志信息,只需再 auth_key 下面加上配置 verbosity: error 即可。默认为 info

这里吐槽一下,ReadonlyREST 插件的文档是真的难读,可能是国外人和我们的思维方式不一样吧。

至此 ReadonlyREST 插件的使用就完毕了。

nginx http-basic 的使用

利用 nginx 的反向代理,分配一个二级域名来进行使用

  1. 一个二级域名,比如xxxx.joylau.cn
  2. 添加 nginx 的配置文件:/etc/nginx/conf.d/elasticsearch.conf, nginx 会默认读取 /etc/nginx/conf.d/ 目录下的 *.conf的文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
upstream JoyElasticSearch {
server localhost:port weight=1;
}


server {
listen 80;
server_name xxxxx.joylau.cn;

location / {
# 提示信息
auth_basic "请输入账号密码";
# 密码文件,最好写绝对路径
auth_basic_user_file /etc/nginx/conf.d/es-password;
autoindex on;
proxy_pass http://JoyElasticSearch;
}
}

在这里访问 xxxxx.joylau.cn 会被定向到 elasticsearch 的http端口
auth_basic_user_file :指的是密码文件,注意这里写绝对路径,防止出错

  1. 用户名,密码文件 es-password
1
2
# root:123
root:Hx53TyjMWNmLo

这里假设 用户名是root,密码是123(实际上不是123),该加密方式为 httpd 加密,怎么获取明文加密后的密文,这个在网上有很多的在线工具可以直接使用,这里不再赘述

  1. 保存并重新加载配置
1
nginx -s reload

访问 xxxxx.joylau.cn 就会提示输入用户名密码,输入正确即可。

至此,nginx http-basic 就结束了

但是还有一个问题,就是直接访问 host + elasticsearch的端口也是可以访问的,解决这个问题,需要使用 iptables 来进行端口的限制访问。

iptables 限制端口的访问

  1. 禁用防火墙 systemctl stop firewalld

  2. 禁用firewalld服务 systemctl mask firewalld

  3. 安装iptables yum install -y iptables

  4. 开机自启 systemctl enable iptables

  5. 启动 iptables systemctl start iptables

  6. 查看现在的所有规则 iptables -L -n

  7. 清空所有默认规则 iptables -F

  8. 清空所有自定义规则 iptables -X

  9. 添加限制规则 iptables -A INPUT -p tcp --dport 9200 ! -s 127.0.0.1 -j DROP
    这句规则的意思是,除了本机,其他的地址都不允许 访问 9200 端口

  10. 保存:service iptables save

注: 后续想要删除这条规则的话
直接修改 iptables.conf 文件后 service iptables save
或者 iptables -L INPUT --line-numbers 查看所有规则
iptables -D INPUT 1 (注意,这个1是行号,num下面的数字)
保存:service iptables save

这样的话,其他机器就不能访问 elasticsearch 的http 服务的端口了,这能通过 配置好的二级域名来访问

至此配置结束

集群环境下的配置

在多个 elasticsearch 集群环境下,可配置一台机器作为负载均衡的机器,配置

1
2
node.master: false
node.data: false

即可,其他机器的配置 http.enabled: false ,即对外不提供 http 服务
访问的时候只需访问那台负载均衡的节点。

至此,文章结束。

说明

  1. 系统 centos 7
  2. 能够开机启动
  3. 能够一键开启,关闭,重启

文件

注意文件编码的问题

  • service 文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[Unit]
Description=frp server Service
After=network.target

[Service]
## 可以包含的值为simple、forking、oneshot、dbus、notify、idel其中之一。
## Type=forking

## 守护进程的PID文件,必须是绝对路径,强烈建议在Type=forking的情况下明确设置此选项
## PIDFile=/project/frp_0.19.0_linux_amd64

## 设置启动服务是要执行的命令(命令+参数)
ExecStart=/project/frp_0.19.0_linux_amd64/systemctl-frps start
## ExecStop=
## ExecReload=

## 当服务进程正常退出、异常退出、被杀死、超时的时候,是否重启系统该服务。进程通过正常操作被停止则不会被执行重启。可选值为:
## no:默认值,表示任何时候都不会被重启
## always:表示会被无条件重启
## no-success:表示仅在服务进程正常退出时重启
## on-failure:表示仅在服务进程异常退出时重启
## 所谓正常退出是指,退出码为“0”,或者到IGHUP, SIGINT, SIGTERM, SIGPIPE 信号之一,并且退出码符合 SuccessExitStatus= 的设置。
## 所谓异常退出时指,退出码不为“0”,或者被强杀或者因为超时被杀死。
Restart=on-abort


[Install]
WantedBy=multi-user.target

文件放到 /usr/lib/systemd/system/ 下

Service 部分的启动、重启、停止命令全部要求使用绝对路径

如果单独运行的是命令,这个就已经足够了,但是如果运行一些守护进程的话或者更复杂的情况的话,需要单独写一个脚本来运行

关于 service 里面的详细配置可以参考: http://blog.51cto.com/littledevil/1912570

  • 脚本文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#!/bin/bash

#set service name
SERVICE_NAME=frpServerService
BIN_FILE_NAME=frps

# set basic executable environment, do not modify those lines
BIN_HOME=$(dirname $0)
if [ "${BIN_HOME}" = "." ]; then
BIN_HOME=$(pwd)
fi

cd ${BIN_HOME}

#the service pid
pid=`ps -ef|grep $SERVICE_NAME|grep -v grep|grep -v kill|awk '{print $2}'`

start() {
if [ -n "$pid" ]; then
echo "service ${SERVICE_NAME} already start with PID :$pid"
return 0
fi
nohup ./$BIN_FILE_NAME -c ./$BIN_FILE_NAME.ini >/dev/null 2>&1 &
echo "Starting $SERVICE_NAME : "
pid=`ps -ef|grep $SERVICE_NAME|grep -v grep|grep -v kill|awk '{print $2}'`
if [ ${pid} ]; then
echo "start ${SERVICE_NAME} successfully with PID: ${pid}"
else
echo "start ${SERIVCE_NAME} failed"
fi
}

debug() {
if [ ${pid} ]; then
kill -9 $pid
fi
./${BIN_FILE_NAME} -c ./${BIN_FILE_NAME}.ini
}

stop() {
if [ -z ${pid} ]; then
echo "service $SERVICE_NAME already stopped"
else
kill -9 $pid
echo -n "Shutting down $SERVICE_NAME : "
check_pid=`jps | grep ${SERVICE_NAME}|grep -v grep|awk '{print $1}'`
while [ -n "${check_pid}" ]
do
check_pid=`jps | grep ${SERVICE_NAME}|grep -v grep|awk '{print $1}'`
if [ -z "${check_pid}" ];then
break;
fi
done
echo "stop ${SERVICE_NAME} with PID: ${pid}"
fi
}


status() {
pid=`jps | grep ${SERVICE_NAME}|grep -v grep|awk '{print $1}'`
if [ -n "$pid" ] ;then
echo "service $SERVICE_NAME (pid $pid) is running ..."
else
echo "service $SERVICE_NAME is stopped"
fi
}

# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart)
stop
start
;;
debug)
debug
;;
*)
echo $"Usage: $0 {start|stop|status|restart|debug}"
exit 2
esac

上面这个脚本是一个模板,包括了start,stop,status,restart,debug各个命令,是可以直接传参执行的
在一个文件上的 ExecStart= 就可以运行脚本文件 并传入 start 参数

注意: 如果运行的是守护进程的话,Type=forking 要配置上,意指 ExecStart 命令里面运行进程才是主进程

使用命令

  1. 启动服务:systemctl start serviceName
  2. 停止服务:systemctl stop serviceName
  3. 服务状态:systemctl status serviceName
  4. 项目日志:journalctl -u serviceName
  5. 开机启动:systemctl enable serviceName
  6. 重新加载service文件:systemctl daemon-reload

说明

  1. 以前的笔记本是 windows7 的操作系统
  2. 6GB 内存
  3. 还剩 96G 硬盘
  4. 打算安装 Centos 7.2

材料

  1. U 盘一个(>= 8G)
  2. centos 镜像文件
  3. 刻录软件 UltraISO (官网直接下载试用版的即可)

安装过程

  1. 在 windows 系统下压缩出磁盘空间或者直接格式化一个盘出来用来装 centos ,注意盘的格式 要为fat32
  2. UltraISO 烧录镜像到U盘,U盘会被磁盘格式会改变且会被格式化
  3. 重启系统,以U盘启动
  4. 指定U盘安装
  5. 安装配置
  6. 等待进入系统

注意事项

  1. 在 U 盘启动的时候,在安装界面上会有三个选项,选择第一个 Install Centos,按tab键进行配置
  2. 找到U盘位置的方法: vmlinuz initrd=initrd.img linux dd
  3. 这个时候很容易找到 U 的device,记下来(我当时U的device是 sdb4),重启机器,在进入上一步的步骤
  4. 这时,将参数改为 : vmlinuz initrd=initrd.img inst.stage2=hd:/dev/sdb4 接下来等待即可
  5. 选择安装位置,下方一定要选择自定义分区
  6. 分区策略就选默认的,创建新的分区,分区的大小就按照默认分配的就好,不需要改变

WiFi 问题

因为笔记本自带了 wifi 模块,想着不要用网线扯来扯去的,直接用wifi连接网络就好了啊
一切都没想象的那么简单….

因为我之前安装的时候选择了最小化安装,进去系统后什么都没有,一起都用通过命令行来解决
第一次我是根据这篇文章的步骤来的 http://www.jb51.net/article/100300.htm
中间遇到了很多问题 network 服务不可用;systemctl restart network 也起不来,一直报错;ping 域名不通,ping ip 不通;ifconfig 命令不存在….总之一大堆问题
问题一个个解决,最后终于连上家里的wifi
后来重启了下,一切回到解放前
我去….
一顿惆怅
后来我装了个gnome图形界面,连上了wifi
在切换命令行使用,不使用图形界面,现在一切完好,而且内存占用空间大幅减少

WiFi 连接命令

  1. 设置NetworkManager自动启动
    chkconfig NetworkManager on
  2. 安装NetworkManager-wifi
    yum -y install NetworkManager-wifi
  3. 开启WiFi
    nmcli r wifi on
  4. 测试(扫描信号)
    nmcli dev wifi
    扫描不到可用 iw wlp8s0b1(网卡名称) scan | grep SSID 扫描一下
  5. 连接
    nmcli dev wifi connect password

注: 总结多次安装 centos 系统得出一个结论,如果在安装过程中选择打开 WiFi 并连接网络,系统安装完成后,会在 /etc/sysconfig/network-scripts/ 目录下生成一个 ifcfg-WiFi名称 文件和 keys-WiFi名称的密码文件,之后安装 NetworkManage-wifi 便可每次开机都能自动启动 WiFi,如果是装完系统在命令连接的话则每次重启后都需要自己手动连接 WiFi,这是扫描原因暂且不得而知

切换命令行和图形界面

1
2
systemctl set-default multi-user.target  //设置成命令模式
systemctl set-default graphical.target //设置成图形模式

关闭盖子不睡眠

vim /etc/systemd/logind.conf

HandlePowerKey     按下电源键后会触发的行为
HandleSleepKey      按下挂起键后会触发的行为
HandleHibernateKey   按下休眠键后会触发的行为
HandleLidSwitch     关闭笔记本盖子后会触发的行为

只需要把HandleLidSwitch选项设置为 HandleLidSwitch=lock

设置完成保存后运行 systemctl restart systemd-logind 命令才生效

恢复 Windows 启动项

windows 7、8/10 安装centos7双系统后,默认会将mbr改写成为grub2,而默认的centos7不识别windows 的ntfs分区,所以启动项没有windows。
可以用3条命令,即可将windows添加到grub2的启动项。

1
2
3
yum -y install epel-release
yum -y install ntfs-3g
grub2-mkconfig -o /boot/grub2/grub.cfg

重启

最小化安装时配置静态 IP 地址

  1. vim /etc/sysconfig/network-scripts/ifcfg-网络接口名称,默认第一个是网络接口名称

  2. 修改以下红色标注的配置

    TYPE=Ethernet

    BOOTPROTO=static

    DEFROUTE=yes

    IPV4_FAILURE_FATAL=no

    IPV6INIT=yes

    IPV6_AUTOCONF=yes

    IPV6_DEFROUTE=yes

    IPV6_FAILURE_FATAL=no

    NAME=eno16777736

    UUID=9e8d604f-d991-4aa2-88a3-4c679e6f139c

    DEVICE=eno16777736

    ONBOOT=yes

    PEERDNS=yes

    PEERROUTES=yes

    IPV6_PEERDNS=yes

    IPV6_PEERROUTES=yes

    HWADDR=B8:70:F4:24:61:A7 #MAC地址

    IPADDR=192.168.10.29 #静态IP

    GATEWAY=192.168.10.1 #默认网关

    NETMASK=255.255.255.0 #子网掩码

    DNS1=61.132.163.68 #DNS配置

  3. 重启网络服务 :service network restart

时间同步

更新时间 2018-08-01 16:36:09
系统安装 ntpdate
查看本地时间: date
本地时间与服务器时间同步 : ntpdate ntp1.aliyun.com
查看bois时间: hwclock
将本地时间写入到bois时间内: hwclock -w

img

  • val可以将变量申明是final类型。
  • @NonNull注解能够为方法或构造函数的参数提供非空检查。
  • @Cleanup注解能够自动释放资源。
  • @Getter/@Setter注解可以针对类的属性字段自动生成Get/Set方法。
  • @ToString注解,为使用该注解的类生成一个toString方法,默认的toString格式为:ClassName(fieldName= fieleValue ,fieldName1=fieleValue)。
  • @EqualsAndHashCode注解,为使用该注解的类自动生成equals和hashCode方法。
  • @NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor,这几个注解分别为类自动生成了无参构造器、指定参数的构造器和包含所有参数的构造器。
  • @Data注解作用比较全,其包含注解的集合 @ToString, @EqualsAndHashCode,所有字段的 @Getter和所有非final字段的 @Setter, @RequiredArgsConstructor。
  • @Builder注解提供了一种比较推崇的构建值对象的方式。
  • @Synchronized注解类似Java中的Synchronized 关键字,但是可以隐藏同步锁

官网地址: https://www.projectlombok.org/features/all

说明

  1. Filebeat 版本为 5.3.0
    之所以使用 beats 家族的 Filebeat 来替代 Logstash 是因为 Logstash 实在太消耗资源了(服务器资源充足的土豪请无视)
    在官网下载 Logstash 有 89M,而 Filebeat 才8.4M,由此可见一斑
    Logstash 可以配置 jvm 参数,经过我本身的调试,内存分配小了,启动很慢有时根本起不来,分配大了,其他服务就没有资源了
    所有说对于配置低的服务器,选择 Filebeat 是最好的选择了,而且现在 Filebeat 已经开始替代 Logstash 了
  2. 依然需要修改 nginx 的日志格式

nginx.config

更改日志记录的格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
log_format json '{ "@timestamp": "$time_iso8601", '
'"time": "$time_iso8601", '
'"remote_addr": "$remote_addr", '
'"remote_user": "$remote_user", '
'"body_bytes_sent": "$body_bytes_sent", '
'"request_time": "$request_time", '
'"status": "$status", '
'"host": "$host", '
'"request": "$request", '
'"request_method": "$request_method", '
'"uri": "$uri", '
'"http_referrer": "$http_referer", '
'"body_bytes_sent":"$body_bytes_sent", '
'"http_x_forwarded_for": "$http_x_forwarded_for", '
'"http_user_agent": "$http_user_agent" '
'}';

access_log /var/log/nginx/access.log json;

filebeat.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#=========================== Filebeat prospectors =============================

filebeat.prospectors:

- input_type: log

# Paths that should be crawled and fetched. Glob based paths.
paths:
- /var/log/nginx/*access*.log
json.keys_under_root: true
json.overwrite_keys: true

#-------------------------- Elasticsearch output ------------------------------
output.elasticsearch:
# Array of hosts to connect to.
hosts: ["ip:port","ip:port"]
index: "filebeat_server_nginx_%{+YYYY-MM}"

这里面需要注意的是
json.keys_under_root: 默认这个值是FALSE的,也就是我们的json日志解析后会被放在json键上。设为TRUE,所有的keys就会被放到根节点
json.overwrite_keys: 是否要覆盖原有的key,这是关键配置,将keys_under_root设为TRUE后,再将overwrite_keys也设为TRUE,就能把filebeat默认的key值给覆盖了

还有其他的配置
json.add_error_key:添加json_error key键记录json解析失败错误
json.message_key:指定json日志解析后放到哪个key上,默认是json,你也可以指定为log等。

说白了,差别就是,未配置前elasticsearch的数据是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"_index": "filebeat_server_nginx_2018-05",
"_type": "log",
"_id": "AWM9sVOkCcRcg0IPg399",
"_version": 1,
"_score": 1,
"_source": {
"@timestamp": "2018-05-08T03:00:17.544Z",
"beat": {
"hostname": "VM_252_18_centos",
"name": "VM_252_18_centos",
"version": "5.3.0"
},
"input_type": "log",
"json": {},
"message": "{ "@timestamp": "2018-05-08T11:00:11+08:00", "time": "2018-05-08T11:00:11+08:00", "remote_addr": "113.16.251.67", "remote_user": "-", "body_bytes_sent": "403", "request_time": "0.000", "status": "200", "host": "blog.joylau.cn", "request": "GET /img/%E7%BD%91%E6%98%93%E4%BA%91%E9%9F%B3%E4%B9%90.png HTTP/1.1", "request_method": "GET", "uri": "/img/\xE7\xBD\x91\xE6\x98\x93\xE4\xBA\x91\xE9\x9F\xB3\xE4\xB9\x90.png", "http_referrer": "http://blog.joylau.cn/css/style.css", "body_bytes_sent":"403", "http_x_forwarded_for": "-", "http_user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36" }",
"offset": 7633,
"source": "/var/log/nginx/access.log",
"type": "log"
}
}

配置后,是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
"_index": "filebeat_server_nginx_2018-05",
"_type": "log",
"_id": "AWM9rjLd8mVZNgvhdnN9",
"_version": 1,
"_score": 1,
"_source": {
"@timestamp": "2018-05-08T02:56:50.000Z",
"beat": {
"hostname": "VM_252_18_centos",
"name": "VM_252_18_centos",
"version": "5.3.0"
},
"body_bytes_sent": "12576",
"host": "blog.joylau.cn",
"http_referrer": "http://blog.joylau.cn/",
"http_user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36",
"http_x_forwarded_for": "-",
"input_type": "log",
"offset": 3916,
"remote_addr": "60.166.12.138",
"remote_user": "-",
"request": "GET /2018/03/01/JDK8-Stream-Distinct/ HTTP/1.1",
"request_method": "GET",
"request_time": "0.000",
"source": "/var/log/nginx/access.log",
"status": "200",
"time": "2018-05-08T10:56:50+08:00",
"type": "log",
"uri": "/2018/03/01/JDK8-Stream-Distinct/index.html"
}
}

这样看起来就很舒服了

启动 FileBeat

进入 Filebeat 目录

1
nohup sudo ./filebeat -e -c filebeat.yml >/dev/null 2>&1 & 

更新

nginx 的日志里含有中文的话,会将中文转为 Unicode 编码,如果不转的话,加入 escape=json 参数就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
log_format json escape=json '{ "@timestamp": "$time_iso8601", '
'"time": "$time_iso8601", '
'"remote_addr": "$remote_addr", '
'"remote_user": "$remote_user", '
'"body_bytes_sent": "$body_bytes_sent", '
'"request_time": "$request_time", '
'"status": "$status", '
'"host": "$host", '
'"request": "$request", '
'"request_method": "$request_method", '
'"uri": "$uri", '
'"http_referrer": "$http_referer", '
'"body_bytes_sent":"$body_bytes_sent", '
'"http_x_forwarded_for": "$http_x_forwarded_for", '
'"http_user_agent": "$http_user_agent" '
'}';

access_log /var/log/nginx/access.log json;

说明

logstash 需要和 nginx 部署到一台机器
需要修改 nginx 的日志格式

nginx.config

更改日志记录的格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
log_format json '{ "@timestamp": "$time_iso8601", '
'"time": "$time_iso8601", '
'"remote_addr": "$remote_addr", '
'"remote_user": "$remote_user", '
'"body_bytes_sent": "$body_bytes_sent", '
'"request_time": "$request_time", '
'"status": "$status", '
'"host": "$host", '
'"request": "$request", '
'"request_method": "$request_method", '
'"uri": "$uri", '
'"http_referrer": "$http_referer", '
'"body_bytes_sent":"$body_bytes_sent", '
'"http_x_forwarded_for": "$http_x_forwarded_for", '
'"http_user_agent": "$http_user_agent" '
'}';

access_log /var/log/nginx/access.log json;

log-file.config

input 里添加 file 类型

1
2
3
4
5
6
7
8
9
10
input {
file {
path => "/var/log/nginx/access.log"
codec => "json"
start_position => "beginning"
type => "server_nginx"
tags => ["nginx"]
}
}

说明

  1. Elasticsearch, Logstash,Kibana 版本都是5.3.0
  2. SpringBoot 集成 ELK,实际上指的就是 SpringBoot 与 Logstash 的整合
  3. Elasticsearch 负责数据的存储,Logstash 负责数据的接受和数据的发送,相当于一个中转站,Kibana 负责数据的展示,查询
  4. SpringBoot 项目是我们产生日志并且需要存储和分析的项目
  5. SpringBoot 我还是使用的默认的 logback 日志系统,当然也可以采用 log4j,不过我还是比较喜欢 logback,性能好,配置少,有颜色

Elasticsearch 集群搭建

Logstash 安装

  1. 官网下载 Logstash
  2. 解压
  3. 添加配置文件 log.config
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
input {
tcp {
host => "192.168.10.78"
type => "dev"
tags => ["spring-boot"]
port => 4560
codec => json_lines
}

tcp {
host => "192.168.10.78"
type => "server"
tags => ["spring-boot"]
port => 4561
codec => json_lines
}

tcp {
host => "192.168.10.78"
type => "work_dev"
tags => ["boot"]
port => 4568
codec => json_lines
}
}

filter {

}

output {
if[type] == "work_dev" {
elasticsearch {
hosts => ["ip:9268"]
index => "logstash_%{type}_%{+YYYY-MM}"
}
} else {
elasticsearch {
hosts => ["http://192.168.10.232:9211"]
index => "logstash_%{type}_%{+YYYY-MM}"
}
}
}

总的来说,配置文件里由 input,filter,output,这里我没有特别复杂的需求,filter就没有配置
我这里有三个input,但是都是 tcp 类型的
意思配置了三个input,分别监听192.168.10.78(就是安装logstash的机器)的4560,4561,和4568端口,有数据发送过来的话就进行output处理
这里我配置了3个type,这个type也就是elasticsearch里索引的type,并且该type可作为参数在output里判断进行不同的处理
codec 是的对日志数据进行处理的插件,这里是 json_lines
所以需要安装插件

1
sh bin/logstash-plugin install logstash-codec-json_lines

elasticsearch:hosts es的http地址和端口
index 是创建的索引名
如果要配置索引模板的话,可以添加以下配置
manage_template => true
template_name => “template_name”
template_overwrite => true
template => “/usr/local/path.json”

配置好了,我们检验下配置文件是否正确

1
sh /app/logstash-5.3.0/bin/logstash -f /app/logstash-5.3.0/config/log.config -t

没有问题的话就可启动了,后台启动的就用 nohup

1
sh /app/logstash-5.3.0/bin/logstash -f /app/logstash-5.3.0/config/log.config

启动成功的话,9600端口可以获取到 logstash 的相关信息

SpringBoot 集成 Logstash

  1. 添加依赖:
1
2
3
4
5
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>5.1</version>
</dependency>
  1. 添加配置 logstash 文件
    在 resources 下直接添加 logback.xml 文件即可
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>ip:4568</destination>
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder" />
</appender>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<root level="INFO">
<appender-ref ref="LOGSTASH" />
</root>

</configuration>

这里我是使用的是 SpringBoot 自带的 logback 日志
SpringBoot 默认会读取 resources 目录下的 logback.xml 作为配置文件,别问我怎么知道的(我特地查看了源码:org.springframework.boot.logging.logback.LogbackLoggingSystem,”logback-test.groovy”, “logback-test.xml”, “logback.groovy”, “logback.xml”这些文件检测到都会读取其中的配置的)
配置文件里我只配置了 一个Appender,就是net.logstash.logback.appender.LogstashTcpSocketAppender,用来输出日志到logstash的,并且级别是 INFO
destination 指的就是 logstash 的地址
encoder 就配置LogstashEncoder不要变
再把 SpringBoot默认的配置引入base.xml

好了,SpringBoot 集成 Logstash 完毕

注 :后来我想用 javaConfig 去配置 SpringBoot和Logstash,不过没有成功,哪位大佬看到这个信息,可以给我留言下怎么配置
xml,也很方便,打包部署后可以作为配置文件修改

那么,这个时候启动项目,elasticsearch里面就会看到有新的索引数据了

Kibana 安装

  1. 其实 Kibana 非必须安装,只是用来统计数据和查询数据的,用来提供一个可视化的界面
  2. 下载 Kibana
  3. 修改配置文件 kibana.yml
    server.port: 5668
    server.host: “0.0.0.0”
    elasticsearch.url: “http://localhost:9268
  4. 后台启动
  5. 访问kibana的地址即可
0%