我试图在go中对http客户端进行压力测试。
一开始,我只是尝试运行10个并发请求10次迭代。
这是我的客户代码:
// stress.go
package main
import (
"fmt"
"io/ioutil"
"net/http"
"time"
)
func MakeRequest(url string, ch chan<- string) {
start := time.Now()
resp, _ := http.Get(url)
secs := time.Since(start).Seconds()
body, _ := ioutil.ReadAll(resp.Body)
ch <- fmt.Sprintf("%.2f elapsed with response length: %d %s", secs, len(body), url)
}
func main() {
start := time.Now()
goroutines := 10
iterations := 10
ch := make(chan string)
url := "http://localhost:8000"
for i := 0; i < iterations; i++ {
for j := 0; j < goroutines; j++ {
go MakeRequest(url, ch)
}
}
for i := 0; i < goroutines*iterations; i++ {
fmt.Println(<-ch)
}
fmt.Printf("%.2fs elapsed\n", time.Since(start).Seconds())
}
对于迭代和goroutine的这种组合,它工作得很好。但是,当goroutine和迭代次数超过某个级别时,在我的例子中,对于单个迭代,当goroutine的次数超过634时,我收到这个错误:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x48 pc=0x11eb9f0]
goroutine 7099 [running]:
main.MakeRequest(0x1271897, 0x15, 0xc420074120)
stress.go:16 +0xa0
created by main.main
stress.go:28 +0xb2
根据this,可以轻松创建10000个goroutine。我在我的案子里做错了什么?如何测试客户机在给定迭代次数下并发发出的get或post请求的最大数量?
最佳答案
您正在丢弃http.get和ioutil.readall中的错误,所以您得到一个nil指针解引用并不奇怪;如果这不是一个有效的假设,您假设返回值是好的。服务器可能返回错误,因为您已超过服务器的最大吞吐量。
您也没有在10次迭代中测试10个goroutine,而是在测试100个goroutine;并且在读完请求体之后,也没有关闭它们。最后,您可以获得多少吞吐量将取决于服务器、服务器有多少可用资源以及客户端有多少可用资源;以及两者之间的竞争,由于您正在访问本地主机,客户机和服务器正在争夺相同的系统资源。
任何语言都没有静态性能特性;它取决于运行它的上下文。
关于multithreading - Go-尝试创建超过一定数量的goroutine时出现段错误问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46386186/