开源测试工具 重写 goreplay-es 插件,支持连接 es6.x

少年 · 2020年02月24日 · 最后由 少年 回复于 2020年03月17日 · 3387 次阅读

gor 原来的 es 插件用的是比较旧的源了,最新也只是支持 es 5.x 版本,使用 --output-http-elasticsearch 的时候,如果连接 es6.x 以上的版本,数据是传不过来的。

鉴于我司的 elk 是 6.x 版本以及 gor 的 es 插件久无更新的情况下,那就还是自己动手改写一下。(新换的这个插件源,到 es 7.x 的连接方式都支持,我只适配了 6.x 版本)

项目源代码: shaonian-goreplay 【欢迎来 star ~】

新写的 gor 已经打包好成镜像了,同时把 INPUT OUTPUT 都暴露了出来,可以直接用 docker 的方式运行,可以单独去监听某个 docker 容器上暴露出的端口所经过的流量,不用在服务器的本地来跑。

goreplay-es6.x 镜像: docker pull shaonian/gor:6.x

具体的 Dockerfile:

FROM ubuntu:18.04
ADD goreplay /go/
WORKDIR /go
RUN mkdir logs
RUN mkdir records
USER root
ENV INPUT="--input-raw :5000"
ENV OUTPUT="--output-stdout"
CMD ./goreplay ${INPUT} ${OUTPUT}

这里的环境变量可以直接通过腾讯云容器服务的环境变量来配置:

想要监听哪个容器服务,就并行挂载在同个实例下面,设置好想要监听的 docker 容器暴露出端口,然后 goreplay 对应的日志就有内容输出了:

当然这样看日志太低效率了,可以使用 goreplay + kibana + es 的方式,将数据分隔呈现到 kibana 上。

本地演示了一下,直接用 docker-compose 的方式启动 kibana + es(6.x)版本:

goreplay 的 yml 文件可以这样写:

goreplay:
    image: shaonian/gor:6.x
    network_mode: host
    environment:
      INPUT: "--input-raw :5000"
      # OUTPUT: "--output-stdout"
      OUTPUT: "--output-stdout --output-http localhost:5000 --output-http-track-response --output-http-elasticsearch http://localhost:9200"

然后启动任意一个后端项目,暴露端口出 5000 即可开始监听。这里的 index 不需要提前设置,会自动以 gor-2020-01-01 这种方式来创建和更新。

然后观察一下效果:

如果是在腾讯云上面部署,使用 --output-http-elasticsearch 的时候,在同一个集群下可以通过 集群名 + 容器名 + 端口 的方式传递到 elk 中。

如果 elk 跟想要监听的容器不在同一个集群里面,可以通过 nginx 反向代理加密的方式,或者升级到 es 7.x 版本,可以免费使用数据加密传输的功能。

PS:技术交流 QQ 群 552643038

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 12 条回复 时间 点赞

大家直接 fork 了你。。。

恒温 回复

hhhhh

@ShaoNianyr 请教个问题,刚接触 gor、
--input-raw 监控 5000 端口情况下,
--output-http 又回放到 5000 端口,此情况应用程序和 ES 都会进入无脑循环阶段,一条简单的请求,ES 会增加重复数据几百几千次。

以上问题实测,分支:go-es-6x

回访地址改成 openrestry(虽然回放失败)但 ES 和应用程序此时正常接收到 1 条请求消息 但拿不到 response

少年 #10 · 2020年03月10日 Author
xp.abc 回复

会无限循环回放的,比如你起个后端程序 INPUT OUTPUT 都写 localhost:5000,就会出现这种情况。Docker 容器测试过没有问题,镜像是 shaonian/gor:6.x

少年 回复

感谢回复

采用 gor 监控流量并发送给 ES,出于两个目的(1、流量收集【测试团队进行整体回归时】,2、流量监控【开发集成环境快速定位接口与入出参数】)

第一个目的基本已经达到了、第二个目的还剩下些疑问:
假设不回放,不增加--output-http 是没办法触发数据发送至 ES、(代码层面我没细看,但看了文档没发现此方面描述)
回放的话、现在拿不到 response,则无法很好判断此次请求是否 success

(:зゝ∠)

xp.abc 回复

对的,你这个问题问得很好,es 插件一定是要回放才可以使用,所以有弊端,刚好我最近也做完了这个的改良,我给你的建议是直接保存成 log 的形式,然后用传统 elk 框架, filebeat + logstash + es 来自己清洗组合数据,再对接 kibana 或者 grafana,就可以作出一个实时监控的数据大屏了。

少年 回复

多谢 , 节省了我继续踩坑的时间 (:зゝ∠)

xp.abc 回复

嗯,多加个 --input-raw-track-response ,你的日志里面就会直接追踪 INPUT 请求的响应,不是 OUTPUT 回放的响应。接下来就是组合日志的事情了。

少年 回复

(:зゝ∠)

脑袋一热,想着是否可在--input-raw-track-response plugins 编写下丢 ES 的代码

但又想想 ELK 全家桶是否更简单点。。。。。

少年 回复

(:зゝ∠) 刚撸了下 input-raw 代码
目测在 listener.go -> func dispatchMessage 新增管道丢数据到 ES 插件看看是否可行

tag v1.0.0

func (t *Listener) dispatchMessage(message *TCPMessage) {
    // If already dispatched
    if _, ok := t.messages[message.ID()]; !ok {
        return
    }

    t.deleteMessage(message)

    if !message.complete {
        if !message.IsIncoming {
            delete(t.respAliases, message.Ack)
            delete(t.respWithoutReq, message.Ack)
        }

        return
    }

    if message.IsIncoming {
        // If there were response before request
        // log.Println("Looking for Response: ", t.respWithoutReq, message.ResponseAck)
        if t.trackResponse {
            if respID, ok := t.respWithoutReq[message.ResponseAck]; ok {
                if resp, rok := t.messages[respID]; rok {
                    // if resp.AssocMessage == nil {
                    // log.Println("FOUND RESPONSE")
                    resp.setAssocMessage(message)
                    message.setAssocMessage(resp)

                    if resp.complete {
                        defer t.dispatchMessage(resp)
                    }
                    // }
                }
            }

            if resp, ok := t.messages[message.ResponseID]; ok {
                resp.setAssocMessage(message)
            }
        }
    } else {
        if message.AssocMessage == nil {
            if responseRequest, ok := t.respAliases[message.Ack]; ok {
                message.setAssocMessage(responseRequest)
                responseRequest.setAssocMessage(message)
            }
        }

        delete(t.respAliases, message.Ack)
        delete(t.respWithoutReq, message.Ack)

        // Do not track responses which have no associated requests
        if message.AssocMessage == nil {
            // log.Println("Can't dispatch resp", message.Seq, message.Ack, string(message.Bytes()))
            return
        }
    }

    t.messagesChan <- message
    //TODO 
    //此处不清楚 es chan 是多少,或者自己搞一个 _(:зゝ∠)_
    t.esChan <- message 
}
少年 #11 · 2020年03月10日 Author
xp.abc 回复

用 logstash 好,插件多,而且你也不止监控 gor 的日志吧,做起来了 nginx 这些日志可以一块来的

少年 基于 goreplay 日志清洗组合和可视化方案 中提及了此贴 03月17日 18:00
xp.abc 回复

你的问题解决了吗,我的 demo 做出来分享了,希望对你有用。 https://testerhome.com/topics/22559

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册