以下文章来源于测试架构师影响力 ,作者cctester
大家好,我是CC,这是第106篇原创。 在之前的文章中,关于性能测试分析这块,我贴了一张图,推荐大家可以基于ELK进行日志数据分析;在微服务架构下,ELK是最常用的日志采集存储组件。但不少同学只是听过,对于具体是什么,怎么用比较迷茫;这一篇我从测试开发的使用维度来介绍下ELK。
关于技术类原创文章,CC会全程搭建一遍环境,所以这篇文章写了好几天,希望尽可能多的读者能够上手,但也不会枯燥的只讲步骤,思考点一定是帖子的核心。
一.ELK是什么?
1.ELK是三个开源软件的缩写,分别表示:Elasticsearch(数据存储), Logstash(收集数据), Kibana(数据展示), 取第一个字母组合成ELK。
2.新增了一个FileBeat,它是一个轻量级的日志收集处理工具(Agent),Filebeat占用资源少,适合于在各个服务器上搜集日志后再传输给Logstash,所以也有很多人用EFLK,这套逻辑本身跟ELK是一致的。
二.部署安装方式:
使用docker的方式安装最方便,直接docker pull 相应的组件即可,版本号下图红色框子示意。服务器建议最低入门配置4c8g,这个配置也就是让你做实验的,Elasticsearch本身比较消耗资源;下图是我安装的版本,供大家参考。(下文出现es均表示Elasticsearch的缩写)
elk分布式日志收集数据逻辑展示:
1.logstash是用来收集业务日志
- 在应用端配置logback.xml,下面部分将日志指向logstash安装地址,每个服务都需要配置。
<appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<!-- logstash的服务器地址和通信端口 -->
<destination>实际安装logstash的ip:5043</destination>
<!-- encoder is required -->
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<!-- 在elasticsearch的index中追加applicationName字段 -->
<customFields>{"applicationName":"${applicationName}"}</customFields>
</encoder>
</appender>
- 在logstash容器中,一般在logstash.yml需要指定es的地址以及存储日志的索引名字,我定义成flow-*,*在匹配的时候可以代替时间戳,注意下面截图的红色部分。
2.收集的日志存储在elastcisearch中
安装完es后,可以通过如下命令去测试
curl http://127.0.0.1:9200
3.kibana用来提取展示,一般在kibana.yml文件中去配置es的地址。
代码语言:javascript复制#Default Kibana configuration for docker target
server.name: kibana
server.host: "0"
elasticsearch.hosts: ["http://127.0.0.1:9200"]
xpack.monitoring.ui.container.elasticsearch.enabled: true
kibana默认安装访问页面是部署ip:5601
通过索引查找区导入命名的索引,比如我导入flow-*
在discover中选择对应的索引就可以看到相关日志
以上是对ELK结构的理解以及安装部署步骤。
三.测试开发如何使用ELK数据?
1.可以收集哪些数据?这是我这边的日志返回JSON
代码语言:javascript复制{ "_index": "flow-2022.04.28", "_type": "_doc", "_id": "1WwmcIAB9ApEV9PdyRPE", "_version": 1, "_score": null, "_source": { "X-Span-Export": "true", "host": "192.168.91.170", "traceId": "9ade5fd312946ece", "thread_name": "http-nio-7000-exec-8", "message": "error test1", "X-B3-SpanId": "9ade5fd312946ece", "port": 47516, "spanId": "9ade5fd312946ece", "@timestamp": "2022-04-28T12:30:31.757Z", "logger_name": "net.tclass.controller.AopLogController", "level_value": 40000, "appName": "testelk", "X-B3-TraceId": "9ade5fd312946ece", "@version": 1, "level": "ERROR", "spanExportable": "true"
}, "fields": { "@timestamp": [ "2022-04-28T12:30:31.757Z"
]
}, "sort": [ 1651149031757
]
}
返回的信息很多,时间点,报错原因,类方法,追踪id等,总之只要开发定义出来的,都可以获取到。这是我demo里aop的记录:
代码语言:javascript复制// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 记录下请求内容
logger.info("URL : " request.getRequestURL().toString());
logger.info("HTTP方法 : " request.getMethod());
logger.info("IP地址 : " request.getRemoteAddr());
logger.info("类的方法 : " joinPoint.getSignature().getDeclaringTypeName() "." joinPoint.getSignature().getName());
logger.info("参数 : " request.getQueryString());
2.需要知道这些数据可以做什么?
- 业务日志报错归类
- 业务日志实时报警
- 用户数据访问分析
- 性能测试模型构建
- ........
很多,只要你能想到的基本都可以做到。当你能获取到数据,怎么加工数据就是八仙过海,各显神通了。我说一个测试容易上手的方案,通过阅读上文可以知道,数据都是存储在es里的,通过Python连接es做查询接口就比较简单了,而Python对于es也有相应的类库做支持。放一部分代码如下:
代码语言:javascript复制from elasticsearch7 import Elasticsearch
class ElasticObj:
def __init__(self, index_name, ip, index_type=None):
"""
初始化,连接ES
:param index_name:
:param index_type:
:param ip:
"""
self.index_name = index_name
self.index_type = index_type
self.es = Elasticsearch([ip])
def get_data_by_body(self, body):
"""
根据 body 查询条件来查询
:param body:
:return:
"""
try:
search_result = self.es.search(index=self.index_name,
body = body)
return search_result["hits"]["hits"]
except Exception as e:
raise e
关于怎么取数在body中定义,比如一段时间内的ERROR日志数据
代码语言:javascript复制body = {
"query": {
"bool": {
"must": {
"match": {
"level": "ERROR"
}
},
"filter": {
"range": {
"@timestamp": {
"gte": start_time,
"lte": end_time
}
}
}
}
}
}
当你能够获取到这些数据时,自然就可以对数据进行整理,后面大家按照需求自行实现即可。
四.ELK架构的拓展
关于ELK介绍的官方用法在实战中是存在明显弊端的,容易出现问题,比如:
1.较大日志数据处理容易形成性能瓶颈。
2.logstash出问题会导致不可用。
尤其是对于日志要求比较高的公司,都会对ELK进行一定的架构拓展,这个也不是非常复杂,主要通过如下两个方式:
- es集群化
- 日志消息异步
es集群需要多一些硬件资源支持,异步用MQ或者Kafaka均可,这样的话可以一来可以解耦,二来可以多一道存储,安全性也提高了。基于此,我补充一个架构图,这是一个相对完善的方案,可以根据实际情况使用。如果进行ELK架构的调整,可能配套的数据加工方案也需要整合。
这一篇就聊到这里