测试开发如何玩转ELK?

2022-09-20 15:41:00 浏览数 (1)

大家好,我是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安装地址,每个服务都需要配置。
代码语言:javascript复制
<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架构的调整,可能配套的数据加工方案也需要整合。

这一篇就聊到这里,往期推荐:

直播回访:构建可落地的企业级压测体系

CC简介:

测试实干派,目前在近70人测试团队担任质量委员会负责人,曾就职于一线互联网公司,在知名App上发布过测试专栏,付费订阅人数10000

0 人点赞