使用go进行单台机器压测

目录

自助压测系统的局限

为什么不使用Java

基于go的简单实现


自助压测系统的局限

公司已经有基于集群实现的自助压测系统,自助压测系统压的是整个集群, 不方便对单台进行压测,有时候只压某一台即可定位问题。

为什么不使用Java

压测需要模拟多线程并发,在 JVM 中线程上下文的切换是很慢的使用操作系统的 threads 的最大能力一般在万级别,主要消耗是在上下文切换的延迟。

Java 只允许数千级别的 threads。

Goroutines是一种由 Go 运行时系统管理的“极轻量级线程”。使用 Goroutines 可以创建异步并行的项目,执行这些并行任务要比执行对应的串行任务快很多。

Goroutines 通常在初始化时仅需要分配 2KB 的栈空间,而线程通常需要占用 1MB。因此,Goroutines 远比线程要更轻量级。

新建的一个 Goroutine 实际只占用 4KB 的栈空间。一个栈只占用 4KB,1GB 的内存可以创建 250 万个 Goroutine。

总结一句话:go可以通过有限的资源实现很大的并发。

基于go的简单实现

  1. 通过命令行传参控制并发数
  2. 基于go的http.Client发送http json请求
  3. 支持传cookie
  4. 通过sync.WaitGroup等待所有Goroutines执行完毕
  5. 解析response,判断错误code

下载安装go,并通过go version判断安装成功

wget https://dl.google.com/go/go1.13.linux-amd64.tar.gz

sudo tar -C /usr/local -xzf go1.13.linux-amd64.tar.gz

export PATH=$PATH:/usr/local/go/bin

source ~/.profile

go version

代码实现 ,通过 go build main.go 编译后,执行命令并通过-P=线程数 传参: ./main -P=999

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"strings"
	"sync"
	"time"
)

var count int

 
var urlStr = "http://mall.bilibili.com/mall-c/cart/all?build=0&operationType=0"
 

func makeTimestamp() int64 {
	return time.Now().UnixNano() / int64(time.Millisecond)
}

func main() {
	a := makeTimestamp()
	callRemote()
	b := makeTimestamp()
	fmt.Printf("cost = %d ", b-a)
}

func callRemote() {
	flag.IntVar(&count, "P", 10, "default value")
	flag.Parse()
	fmt.Println("finally count = ", count)
	var wg sync.WaitGroup
	wg.Add(count)

	jar, _ := cookiejar.New(nil)
	str := "{\"shopId\":2233}"
	http.DefaultTransport.(*http.Transport).ResponseHeaderTimeout = time.Minute * 30
	var cookies []*http.Cookie
	var cookie = &http.Cookie{
		Name:  "SESSDATA",
		Value: "28cd1772%2C1632572281%2C68d45%2A31",
	}
	cookies = append(cookies, cookie)
	u, _ := url.Parse(urlStr)
	jar.SetCookies(u, cookies)
	client := &http.Client{
		Jar: jar,
	}
	for i := 0; i < count; i++ {
		go invokeRemote(client, str, wg.Done)
	}
	wg.Wait()
}

func invokeRemote(client *http.Client, str string, done func()) {
	defer done()
	req, _ := http.NewRequest("POST", urlStr, strings.NewReader(str))
	req.Header.Add("Content-Type", "application/json")
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
	}
	if resp == nil {
		// handle error
		return
	}
	if resp.Body == nil {
		// handle error
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		// handle error
		return
	}
	result := string(body)
	var code = getCode(result)
	if code != 0 {
		fmt.Println("error happend ", code)
	}
}

type Message struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

func getCode(jsonStr string) int {
	var message Message
	if err := json.Unmarshal([]byte(jsonStr), &message); err == nil {
		return message.Code
	}
	return -99
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值