golang web接口压力测试,性能测试(1)

golang 压力测试

前言

压力测试之前,先看下单元测试,主要怕自己忘记,仅供参考

1.普通应用程序 单元+压力测试

(1). 普通单元测试

go test是golang的单元测试命令


package main
import (
   "testing"
   )
func Testfunc (t *testing.T) {
   逻辑
}

go test -v test.go 代表运行test.go中所有的以Testf命名开始的函数
go test -v -run=“func” test.go 代表运行test.go中所有的Testffunc的函数
-run=“正则表达”
-v 代表查看详情
go test是先编译然后运行,所以支持go build相关的参数

(2). 请求http单元测试

package main

import (
	"testing"
	"fmt"
	"io/ioutil"
	"net/http"
	"flag"
	"net/url"
	"io"
	"bytes"
	"encoding/json"
	"github.com/parnurzeal/gorequest"//gorequest需要go get
)

var (
//定义命令行参数,可以go test -arg=
	host *string
	ip *string
	reqUrl string
	sign *string
)

func init()  {
	//解析命令行参数
	host = flag.String("host", "127.0.0.1", "请求域名")
	ip = flag.String("ip", "127.0.0.1", "请求ip")
	fromIp = flag.String("from_ip", "10.78.48.10", "请求来源ip")
	sign = flag.String("sign", "c8abc2d3efa0081478beb66e0542eb62", "请求sign")
	flag.Parse()

}
func TestReq (t *testing.T) {
	send(t, "mock/req.json")
}
//mockFile 代表测试样本数据
func send(t *testing.T, mockFile string)  {
	if mockFile == "" {
		mockFile = "mock/req.json"
	}
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("err =", err)
		}
	}()

	myRequest := url.Values{
	}
	myRequest.Set("sign", *sign)
	myRequest.Set("t", "1554198282793")
	myRequest.Set("syn" , "169dd6fc154")
	myRequest.Set("n" , "1")

	reqUrl = "http://" + *ip + "/req/" + "?" + myRequest.Encode()

	reqBody, err := ioutil.ReadFile(mockFile)

	if err != nil {
		error(err.Error()})
		return
	}
	
	Request := gorequest.New()
	Request.Header =  map[string]string{
		"X-Forwarded-For": *fromIp,
		"Host": *host,
		"Content-type" : "application/gzip",
	}
	
	resp, data, errs := Request.Post(reqUrl).Type("text").Send(string(reqBody)).EndBytes()
	errStr := make([]string, 0)
	for _, err := range errs {
		if err != nil {
			errStr = append(errStr, err.Error())
			return
		}
	}

	if resp.StatusCode != http.StatusOK {
		error([]string{"return status code error",  resp.StatusCode})
		return
	}
}

1:需要go get github.com/parnurzeal/gorequest
2:单元测试go test -v test.go -args -ip=test.com -host=test.com -sign=ccbb608d5c618ff7d55bedc19de4138f

-args后面跟参数列表

(3). 请求http压力测试

package main

import (
	"testing"
	"fmt"
	"io/ioutil"
	"net/http"
	"flag"
	"net/url"
	"io"
	"bytes"
	"encoding/json"
	"github.com/parnurzeal/gorequest"//gorequest需要go get
)

var (
//定义命令行参数,可以go test -arg=
	host *string
	ip *string
	reqUrl string
	sign *string
)

func init()  {
	//解析命令行参数
	host = flag.String("host", "127.0.0.1", "请求域名")
	ip = flag.String("ip", "127.0.0.1", "请求ip")
	fromIp = flag.String("from_ip", "10.78.48.10", "请求来源ip")
	sign = flag.String("sign", "c8abc2d3efa0081478beb66e0542eb62", "请求sign")
	flag.Parse()

}
//压力测试程序
func BenchmarkSend (b *testing.B) {
	t := new(testing.T)
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		send(t, "")
	}
}
//mockFile 代表测试样本数据
func send(t *testing.T, mockFile string)  {
	if mockFile == "" {
		mockFile = "mock/req.json"
	}
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("err =", err)
		}
	}()

	myRequest := url.Values{
	}
	myRequest.Set("sign", *sign)
	myRequest.Set("t", "1554198282793")
	myRequest.Set("syn" , "169dd6fc154")
	myRequest.Set("n" , "1")

	reqUrl = "http://" + *ip + "/req/" + "?" + myRequest.Encode()

	reqBody, err := ioutil.ReadFile(mockFile)

	if err != nil {
		error(err.Error()})
		return
	}
	
	Request := gorequest.New()
	Request.Header =  map[string]string{
		"X-Forwarded-For": *fromIp,
		"Host": *host,
		"Content-type" : "application/gzip",
	}
	
	resp, data, errs := Request.Post(reqUrl).Type("text").Send(string(reqBody)).EndBytes()
	errStr := make([]string, 0)
	for _, err := range errs {
		if err != nil {
			errStr = append(errStr, err.Error())
			return
		}
	}

	if resp.StatusCode != http.StatusOK {
		error([]string{"return status code error",  resp.StatusCode})
		return
	}
}

压力测试:
go test -v -run=“none” -bench=“Send*” -benchtime=10s test.go
如果是带 cpu和内存分析的
go test -v -run=“none” -bench=“Send*” -benchtime=10s -cpuprofile cpu.out -memprofile mem.out test.go
简单的看cpu效果
输出 上面cpu和内存数据 到图片
go tool pprof -png cpu.out > cpu.png
也可以直接进入命令行,help查询相关命令:
go tool pprof cput.out

不过这种http请求压测看内存和trace数据没有什么意义

下面介绍不同过http协议,不运行网络http请求,直接压测函数内部调用http handler函数,我使用的框架是echo

2.web接口压力测试

通过压测函数直接调用内部handler函数

我使用的框架是echo,其他框架应该也差不多,下面代码仅供参考

package main

import (
	"testing"
	"fmt"
	"io/ioutil"
	"net/http"
	"flag"
	"net/url"
	"io"
	"bytes"
	"encoding/json"
	"github.com/parnurzeal/gorequest"//gorequest需要go get
)

var (
//定义命令行参数,可以go test -arg=
	host *string
	ip *string
	reqUrl string
	sign *string
)

func init()  {
	//解析命令行参数
	host = flag.String("host", "127.0.0.1", "请求域名")
	ip = flag.String("ip", "127.0.0.1", "请求ip")
	fromIp = flag.String("from_ip", "10.78.48.10", "请求来源ip")
	sign = flag.String("sign", "c8abc2d3efa0081478beb66e0542eb62", "请求sign")
	flag.Parse()

}
//压力测试程序
func BenchmarkSend (b *testing.B) {
	//构建请求对象
	testData, _ := ioutil.ReadFile("mock/req.json")
	req, _ := http.NewRequest("POST", "/req_url", io.Reader(bytes.NewReader(testData)))
	req.Header.Set("X-Forwarded-For" , "10.78.48.10")

   //new一个response对象
	res := new(http.ResponseWriter)
	//new 一个context的函数
	cont := echo.New().NewContext(req, *res)
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		req.Body = ioutil.NopCloser(io.Reader(bytes.NewReader(testData)))
		//handles包代表http handler的包
		//Handlers.Send代表handles包内部的真正逻辑函数
		handlers.Send.Post(cont)
	}
}

因为是直接调用的内部handler函数,所以CPU消耗和内存都比较真实
如果是带 cpu和内存分析的
go test -v -run=“none” -bench=“Send*” -benchtime=10s -cpuprofile cpu.out -memprofile mem.out test.go
如果要分析携程调用和网络阻塞:
go test -v -run=“none” -bench=“Send*” -benchtime=10s -trace=trace.out test.go
go tool trace -http=“host:port” trace.out
访问http:host:port即可看到

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值