ELK搭建使用过程
背景说明
ELK(Elasticsearch+Logstash+Kibana)是目前互联网公司常用的分布式日志收集、存储、分析系统。
最近有一个新需求:汇总统计公司内部各系统的访问量。原来有一套类似功能模块,也能使用,但是如果需要修改统计指标就需要改密码,特别麻烦。所以想通过搭建一套ELK实现类似的功能,而且输出的图表可以在Kibana上编辑,免去了之前“要改就改源码”的麻烦。
通过几天的努力终于基本实现了需求。大体架构如下:
前端埋点->后端收集并且生成日志->logstash收集日志->elasticsearch存储日志->kibana分析展示。
版本
logstash:6.2.2
elasticsearch:6.2.2
kibana:6.2.2
前端埋点
用户访问前端页面时,收集用户的基本信息(根据实际需求来设计,这里提供一个通用的埋点脚本,不过我测试的时候都没有用到,我只收集了两个字段:系统名称、页面名称)。
###通用埋点脚本
文件内容较多,我放到附近中了,这里只贴关键代码。
track.js
function jt_main(server,page) {
//收集完日志 提交到的路径
var logserverUrl = "http://192.168.154.6:8888/log/upLoadLog";
//这里可以把你需要的参数都拼接上去
dest = logserverUrl
+"?server="+server
+"&page="+page;
//通过插入图片访问该地址,并不返回图片内容
document.getElementsByTagName("body")[0].innerHTML += "<img src=\""+dest+"\" border=\"0\" width=\"1\" height=\"1\" />";
}
这段代码的主要作用就是将你需要收集的用户信息(访问了哪个页面?做了什么操作?用户的浏览器是什么?屏幕大小?等等)发送到指定的服务器上。
各页面调用
用户管理页面
<script type="text/javascript" src="/js/track.js"></script>
<script type="text/javascript">
window.onload = function(){
//触发main方法
jt_main("测试系统","用户管理页面");
}
</script>
首页面
<script type="text/javascript" src="/js/track.js"></script>
<script type="text/javascript">
window.onload = function(){
//触发main方法
jt_main("测试系统","首页");
}
</script>
页面加载之后自动调用jt_main方法,将用户访问信息发送到指定的服务器上收集起来。任何你需要统计的页面都可以加这段代码。
后端信息收集服务
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
@RestController
@RequestMapping("/log")
public class LogController {
private final static Logger LOGGER = LoggerFactory.getLogger(LogController.class);
@GetMapping("/upLoadLog")
public void upLoadLog(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
//对get请求串解码,防止中文乱码
String qs = URLDecoder.decode(request.getQueryString(), "utf-8");
//请求串中各指标以&符号分割
String [] attrs = qs.split("\\&");
StringBuffer buf = new StringBuffer();
for(String attr : attrs){
//每个指标以kv形式存在,中间用=分割
String [] kv = attr.split("=");
String key = kv[0]; //指标名称
String val = kv.length == 2 ? kv[1] : ""; //指标值
buf.append(val + "|"); //指标以|分割
}
buf.append(request.getRemoteAddr()); //增加服务器端IP地址指标
buf.append("\n"); //在一个FlumeData文件中有多条数据,之间必须换行
String loginfo = buf.toString();
LOGGER.info(loginfo);
}
}
也很简单,就是接受请求,解析参数,并且打印日志。这里我把日志打印到了项目根目录的all.log文件。当然,由于日志量比较大,这里还需要更多的配置,比如每天打印一个新的文件中,等等。这里就不说了,这里只是把整个ELK流程走完。
logging.file.name=all.log
部署elasticsearch
ELK中最关键的就是elasticsearch。logstash采集的信息需要存储到elasticsearch中,所以,我们先部署elasticsearch。
安装JDK
elasticsearch是java语言开发的,需要安装JRE运行环境,这里我安装的是jdk。
下载JDK8
wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/8u141-b15/336fa29ff2bb4ef291e347e091f7f4a7/jdk-8u141-linux-x64.tar.gz"
配置环境变量
vim /etc/profile
在文件的最下方加入 以下内容
export JAVA_HOME=/usr/local/software/jdk8
export JAVA_BIN=/usr/local/software/jdk8
export PATH=$PATH:$JAVA_HOME/bin
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export JAVA_HOME JAVA_BIN PATH CLASSPATH
安装Elasticsearch
下载安装包
最近公司不能访问外网,用手机流量下的,可能用手机流量下载依然很慢,我在这里提供附近,欢迎下载。
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.2.2.tar.gz
解压
tar -zxvf elasticsearch-6.2.2.tar.gz
为elasticsearch的解压文件设置权限
chmod 777 -R /usr/local/src/elasticsearch-6.2.2
修改elasticsearch的配置
elasticsearch.yum配置文件
设置IP及端口
network.host: 192.168.154.6
http.port: 9200
jvm.options
设置JVM初始内存和最大内存。
-Xms2g
-Xmx2g
创建启动elasticsearch的用户
#添加用户
useradd -m username
#设置密码
passwd username
#切换至username用户
su username
启动elasticsearch
后台启动elasticsearch
cd /usr/local/src/elasticsearch-6.2.2/bin
nohup ./elasticsearch &
验证启动是否成功
[root@localhost bin]# curl 192.168.154.6:9200
{
"name" : "SFSAZpy",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "51CRtCikTbCF-lupcVy8Ww",
"version" : {
"number" : "6.2.2",
"build_hash" : "10b1edd",
"build_date" : "2018-02-16T19:01:30.685723Z",
"build_snapshot" : false,
"lucene_version" : "7.2.1",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
注意:把防火墙给关了吧。
更多elasticsearch相关内容以后再说,这里只是简单使用。
部署logstash
下载安装包
wget https://artifacts.elastic.co/downloads/logstash/logstash-6.2.2.tar.gz
解压
tar -zxvf logstash-6.2.2.tar.gz
添加配置
在config目录下创建applog.conf文件,并编辑。
input{
file{
path=>"/usr/local/src/logServer/all.log"
type=>"applog"
start_position=>"beginning"
}
}
filter{
grok{
match=>{"message"=>"%{TIMESTAMP_ISO8601:time}(.*):(?<server>[\u4e00-\u9fa5|0-9|a-z|A-Z]+)\|(?<page>[\u4e00-\u9fa5|0-9|a-z|A-Z]+)\|%{IP:ip}"}
}
if "_grokparsefailure" in [tags] {
drop { }
}
}
output{
elasticsearch{
hosts=>["192.168.154.6:9200"]
index=>"applog"
}
stdout{codec=>rubydebug}
}
input
input,是指logstash从哪里采集信息,这里指向了后端信息收集服务的日志文件,当然logstash的数据源很丰富,比如可以通过jdbc连接到数据库等等。
filter
filter过滤器,logstash采集到信息后,一般会不原封不动的再发送出去,一般要做一些处理后再发送出去。这里个grok就是一个切分日志的插件,通过正则表达式或者grok定义的语法,匹配采集到的内容,如果匹配失败则丢弃该行数据。
output
output,即你要把经过处理、筛选后的信息发送到哪里,这里发送到elasticsearch,并且指定index。
启动logstash
cd /usr/local/src/logstash-6.2.2/bin
nohup ./logstash -f ../config/applog.conf &
部署kibana
下载安装包
wget -c https://artifacts.elastic.co/downloads/kibana/kibana-6.2.2-linux-x86_64.tar.gz
解压
tar -zxvf kibana-6.2.2-linux-x86_64.tar.gz
修改配置文件kibana.yml
server.port: 5601
server.host: "0.0.0.0"
elasticsearch.url: "http://192.168.154.6:9200"
启动kibana
cd /usr/local/src/kibana-6.2.2-linux-x86_64/bin
nohup ./kibana &
测试
启动并访问任何一个添加了埋点脚本的页面。
后端信息收集服务
查看后端信息收集服务是否产生了相应的日志内容,例如:
2020-08-21 08:55:21.018 INFO 113045 --- [http-nio-8888-exec-2] com.ltx.log.LogController :测试系统|首页|192.168.154.1
2020-08-21 09:04:11.829 INFO 113045 --- [http-nio-8888-exec-4] com.ltx.log.LogController :测试系统|用户管理页面|192.168.154.1
2020-08-21 09:24:28.105 INFO 113045 --- [http-nio-8888-exec-6] com.ltx.log.LogController :测试系统|首页|192.168.154.1
2020-08-21 09:49:29.822 INFO 113045 --- [http-nio-8888-exec-8] com.ltx.log.LogController :测试系统|首页|192.168.154.1
logstash
查看logstash是否采集、处理并发送了相关内容,例如:
{
"path" => "/usr/local/src/logServer/all.log",
"server" => "测试系统",
"@version" => "1",
"host" => "localhost.localdomain",
"time" => "2020-08-21 09:24:28.105",
"@timestamp" => 2020-08-21T01:24:28.882Z,
"message" => "2020-08-21 09:24:28.105 INFO 113045 --- [http-nio-8888-exec-6] com.ltx.log.LogController :测试系统|首页|192.168.154.1",
"page" => "首页",
"type" => "applog",
"ip" => "192.168.154.1"
}
{
"path" => "/usr/local/src/logServer/all.log",
"server" => "测试系统",
"@version" => "1",
"host" => "localhost.localdomain",
"time" => "2020-08-21 09:49:29.822",
"@timestamp" => 2020-08-21T01:49:29.913Z,
"message" => "2020-08-21 09:49:29.822 INFO 113045 --- [http-nio-8888-exec-8] com.ltx.log.LogController :测试系统|首页|192.168.154.1",
"page" => "首页",
"type" => "applog",
"ip" => "192.168.154.1"
}
elasticsearch
查看elasticsearch是否存在相应的索引及内容,通过浏览器访问:http://192.168.154.6:9200/applog/_search,返回内容示例:
{
"took": 159,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 30,
"max_score": 1.0,
"hits": [
{
"_index": "applog",
"_type": "doc",
"_id": "tf06C3QB3nukNP-iYlC7",
"_score": 1.0,
"_source": {
"page": "角色管理页面",
"ip": "192.168.154.1",
"host": "bogon",
"path": "/usr/local/src/logServer/all.log",
"type": "applog",
"message": "2020-08-20 17:36:49.536 INFO 89319 --- [http-nio-8888-exec-10] com.ltx.log.LogController :测试系统|角色管理页面|192.168.154.1",
"@version": "1",
"@timestamp": "2020-08-20T09:36:49.719Z",
"time": "2020-08-20 17:36:49.536",
"server": "测试系统"
}
},
{
"_index": "applog",
"_type": "doc",
"_id": "5HWdDnQBQPL80Cq1_Wy7",
"_score": 1.0,
"_source": {
"path": "/usr/local/src/logServer/all.log",
"server": "测试系统",
"@version": "1",
"host": "localhost.localdomain",
"time": "2020-08-21 09:24:28.105",
"@timestamp": "2020-08-21T01:24:28.882Z",
"message": "2020-08-21 09:24:28.105 INFO 113045 --- [http-nio-8888-exec-6] com.ltx.log.LogController :测试系统|首页|192.168.154.1",
"page": "首页",
"type": "applog",
"ip": "192.168.154.1"
}
},
{
"_index": "applog",
"_type": "doc",
"_id": "pP0mC3QB3nukNP-in1Au",
"_score": 1.0,
"_source": {
"page": "首页",
"ip": "192.168.154.1",
"host": "bogon",
"path": "/usr/local/src/logServer/all.log",
"type": "applog",
"message": "2020-08-20 17:15:13.510 INFO 89319 --- [http-nio-8888-exec-10] com.ltx.log.LogController :服务A|首页|192.168.154.1",
"@version": "1",
"@timestamp": "2020-08-20T09:15:14.488Z",
"time": "2020-08-20 17:15:13.510",
"server": "服务A"
}
}
]
}
}
kibana
访问http://192.168.154.6:5601/
添加index
点击Management->点击Index Patterns->点击CreateIndexPattern->输入applog->点击NextStep->选I don’t want to use the Time Filter ->点击Create index pattern。
查看数据
点击Discover,选择刚才添加的index,即applog,就可以看到applog下的所有数据。
####图表分析
点击Visualize,点击+,选择VerticalBar,选择刚才添加的applog索引。Y轴不用管,默认是Count。点击X-Axis,Aggregation选择Terms,Field选择server.keyword。点击ApplyChanges,即可看到效果(各系统页面访问量计数柱状图)。同时你还可以添加filter,比如点击Add a filter按钮,选择@timestamp->is between ->From 2020-08-02,To 2020-08-21,就可以统计指定时间段内的数据。同时还可以点击Add sub-buckets,选择Split Series,Sub Aggregation选择Terms,Field选择page.keyword,点击运行(ApplyChanges),就可以看到柱状图在原来的基础上每一个柱子根据不同页面的访问数量分成几段(通过颜色区分)。
结语
好了,今天分享了基于ELK日志分析系统的部署和基础应用。关于ELK还有很多的知识点可以分享,后期有时间再研究研究。如果哪里写的不对,望指正。谢谢大家。