微信号:Hi-Linux

介绍:分享Linux/Unix相关的技术文章、教程和工具.欢迎大家参与技术交流和分享,有相关技术问题请留言!

终极Web应用性能和压力测试工具Gor

2016-05-19 00:08 Mike


什么是Gor

项目地址:https://github.com/buger/gor

官方描述

Gor is a simple http traffic replication tool written in Go.
Its main goal is to replay traffic from production servers to staging and dev environments.

简单点说就是一个http流量复制器,Gor是用Golang写的一个HTTP实时流量复制工具。只需要在LB或者Varnish入口服务器上执行一个进程,就可以把生产环境的流量复制到任何地方,比如Staging 环境、Dev环境。完美解决了HTTP层实时流量复制和压力测试的问题。

Gor的功能

Gor支持流量的放大和缩小、频率限制,这样不需要搭建和生产环境一致的服务器集群也可以正确测试。Gor还支持根据正则表达式过滤流量,这意味着可以单独测试某个API服务。还可以修改HTTP请求头,比如替换User-Agent, 或者增加某些HTTPHeader。

Gor还可以把请求记录到文件,以备回放和分析。Gor支持和ElasticSearch集成,将流量存入ES进行实时分析。

Gor的架构

非http协议的流量复制

对于不是基于http协议的流量复制,可以使用流量复制工具TCPCopy, TCPCopy支持tcp协议流量的复制、转发、拦截,非常棒的工具。

TCPCopy项目地址:https://github.com/session-replay-tools/tcpcopy

Gor安装

二进制版本

官方预编译版本使用比较简单,开箱即用。

通过以下地址下载最新版本

https://github.com/buger/gor/releases

Linux

$ wget https://github.com/buger/gor/releases/download/v0.12.1/gor_0.12.1_x64.tar.gz
$ tar xzvf gor_0.12.1_x64.tar.gz
$ cp gor /usr/local/bin

Mac

$ wget https://github.com/buger/gor/releases/download/v0.12.1/gor_0.12.1_mac.tar.gz
$ tar xzvf gor_0.12.1_mac.tar.gz

编译安装

搭建标准的Go语言环境,可参考http://golang.org/doc/code.html。并设置$GOPATH环境变量

获取源代码

$ go get github.com/buger/gor

编译

$ cd $GOPATH/src/github.com/buger/gor
$ go build

编译完成会产生一个gor二进制文件。

Gor配置参数

$ gor --help

  -cpuprofile string
        write cpu profile to file
  -debug verbose
        打开debug模式,显示所有接口的流量 
  -http-allow-header value
        用一个正则表达式来匹配http头部,如果请求的头部没有匹配上,则被拒绝 
         gor --input-raw :8080 --output-http staging.com --http-allow-header api-version:^v1 (default [])
  -http-allow-method value
        类似于一个白名单机制来允许通过的http请求方法,除此之外的方法都被拒绝.
        gor --input-raw :8080 --output-http staging.com --http-allow-method GET --http-allow-method OPTIONS (default [])
  -http-allow-url value
        一个正则表达式用来匹配url, 用来过滤完全匹配的的url,在此之外的都被过滤掉 
         gor --input-raw :8080 --output-http staging.com --http-allow-url ^www. (default [])
  -http-disallow-header value
        用一个正则表达式来匹配http头部,匹配到的请求会被拒绝掉
         gor --input-raw :8080 --output-http staging.com --http-disallow-header "User-Agent: Replayed by Gor" (default [])
  -http-disallow-url value
        用一个正则表达式来匹配url,如果请求匹配上了,则会被拒绝
         gor --input-raw :8080 --output-http staging.com --http-disallow-url ^www. (default [])
  -http-header-limiter value
        读取请求,基于FNV32-1A散列来拒绝一定比例的特殊请求 
         gor --input-raw :8080 --output-http staging.com --http-header-imiter user-id:25% (default [])
  -http-original-host
        在--output-http的输出中,通常gor会使用取代请求的http头,所以应该禁用该选项,保留原始的主机头
  -http-param-limiter value
        Takes a fraction of requests, consistently taking or rejecting a request based on the FNV32-1A hash of a specific GET param:
         gor --input-raw :8080 --output-http staging.com --http-param-limiter user_id:25% (default [])
  -http-rewrite-url value
        Rewrite the request url based on a mapping:
        gor --input-raw :8080 --output-http staging.com --http-rewrite-url /v1/user/([^\/]+)/ping:/v2/user/$1/ping (default [])
  -http-set-header value
        Inject additional headers to http reqest:
        gor --input-raw :8080 --output-http staging.com --http-set-header 'User-Agent: Gor' (default [])
  -http-set-param value
        Set request url param, if param already exists it will be overwritten:
        gor --input-raw :8080 --output-http staging.com --http-set-param api_key=1 (default [])
  -input-dummy value
        Used for testing outputs. Emits 'Get /' request every 1s (default [])
  -input-file value
        从一个文件中读取请求
        gor --input-file ./requests.gor --output-http staging.com (default [])
  -input-http value
        从一个http接口读取请求
        # Listen for http on 9000
        gor --input-http :9000 --output-http staging.com (default [])
  -input-raw value
        Capture traffic from given port (use RAW sockets and require *sudo* access):
        # Capture traffic from 8080 port
        gor --input-raw :8080 --output-http staging.com (default [])
  -input-tcp value
       用来在多个gor之间流转流量
        # Receive requests from other Gor instances on 28020 port, and redirect output to staging
        gor --input-tcp :28020 --output-http staging.com (default [])
  -memprofile string
        write memory profile to this file
  -middleware string
        Used for modifying traffic using external command
  -output-dummy value
        用来测试输入,打印出接收的数据. (default [])
  -output-file value
        把进入的请求写入一个文件中
        gor --input-raw :80 --output-file ./requests.gor (default [])
  -output-http value
        转发进入的请求到一个http地址上
        # Redirect all incoming requests to staging.com address 
        gor --input-raw :80 --output-http http://staging.com (default [])
  -output-http-elasticsearch string
        把请求和响应状态发送到ElasticSearch:
        gor --input-raw :8080 --output-http staging.com --output-http-elasticsearch 'es_host:api_port/index_name'
  -output-http-redirects int
        设置多少次重定向被允许
  -output-http-stats
        每5秒钟输出一次输出队列的状态 
  -output-http-timeout duration
       指定http的request/response超时时间,默认是5秒
  -output-http-workers int
        gor默认是动态的扩展工作者数量,你也可以指定固定数量的工作者
  -output-tcp value
        用来在多个gor之间流转流量
        # Listen for requests on 80 port and forward them to other Gor instance on 28020 port
        gor --input-raw :80 --output-tcp replay.local:28020 (default [])
  -output-tcp-stats
        每5秒钟报告一次tcp输出队列的状态
  -split-output true
        By default each output gets same traffic. If set to true it splits traffic equally among all outputs.
  -stats
        打开输出队列的状态
  -verbose
        Turn on more verbose output

Gor常用命令

简单的HTTP流量复制

$ gor --input-raw :80 --output-http "http://staging.com"

HTTP流量复制频率控制(获取每秒超过10个请求)

$ gor --input-tcp :28020 --output-http "http://staging.com|10"

HTTP流量复制缩小

$ gor --input-raw :80 --output-tcp "replay.local:28020|10%"

HTTP流量记录到本地文件

$ gor --input-raw :80 --output-file requests.gor

HTTP流量回放和压测

$ gor --input-file "requests.gor|200%" --output-http "staging.com"

HTTP流量过滤复制

$ gor --input-raw :8080 --output-http staging.com --output-http-url-regexp ^www.

自定义一些流量复制的参数

$ gor --input-raw :80 --output-http 192.168.2.6:8000 --http-allow-method POST --http-set-header 'User-Agent: Gor' -output-http-workers=1 -http-allow-url test.php

将流量复制两份到不同的测试服务

$ gor --input-tcp :28020 --output-http "http://staging.com"  --output-http "http://dev.com"

将流量像负载均衡一样分配到不同的服务器

$ gor --input-tcp :28020 --output-http "http://staging.com"  --output-http "http://dev.com" --split-output true

测试实例

预发布系统压力测试

预发布系统主要由预发布服务器和Gor流量复制工具组成,为了查看和分析测试效果,还可以接入各种监控分析系统。
部署搭建预发布服务,预发布服务使用的数据库,消息队列,缓存等等需要生成环境隔离,避免对生产环境造成影响;同时,预发布环境使用的数据尽量保证和生成环境一致,以保证测试效果。
将线上的五台Api服务器的流量复制到了一台preview(预发布)服务器

  • 在Api服务器上启动Gor Listener,复制80端口的流量,转发到预发布服务器的28020端口
$ sudo gor --input-raw :80 --output-tcp preview:28020
  • 在预发布服务器上启动Gor Replayer, 监听28020端口,同时将请求转发到预发布服务器
$ sudo gor --input-tcp preview:28020 --output-http http://staging.com
  • 也可以将listener和replayer合二为一
$ sudo gor --input-tcp preview:28020 --output-http http://staging.com

注: gor使用listener捕捉请求的时候需要sudo权限

  • 测试总结

极少的情况下Gor会有少量的丢包问题出现,但是不影响测试效果。
建议将Gor的listener和replayer分开,减少对生成环境性能的影响。
部署搭建预发布服务,预发布服务使用的数据库,消息队列,缓存等等需要生成环境隔离,避免对生产环境造成影响;同时,预发布环境使用的数据尽量保证和生成环境一致,以保证测试效果。
由于预发布环境和生成环境的数据无法做到实时的同步,所以要注意区分哪些错误是有程序的bug,哪些是由数据不一致导致的。
预发布系统能够一站解决回归测试、abtest和压力测试,然而还是会有局限性:对于比较复杂的业务逻辑,并不能直观的表现出来,需要后台对数据进行进一步的分析比较后才能判断。

参考文档

http://www.google.com
https://github.com/buger/gor
https://blog.eood.cn/web-performance-testing-gor
http://my.oschina.net/guol/blog/675294
http://xuyaoqiang.com/2016/05/02/prevew-api-based-on-gor/
https://github.com/buger/gor/blob/master/ELASTICSEARCH.md

 
运维之美 更多文章 CentOS6下升级OpenSSH至7.1 开启ControlPersist来大幅度提升SSH的连接速度 利用n和nvm管理Node的版本 Docker下使用daocloud/阿里云镜像加速 利用ControlPersist特性自动登陆SSH服务器
猜您喜欢 几种线程池的实现算法分析 实验楼施工队求才公告及本周课程更新 你选择自由和快乐,还是所谓的“成功” 软件测试学习怎么学? CSS 伪类 :target 的黑科技