Go - 在用于负载测试的高性能 http 客户端中,我如何 block/ignore 所有 cookie?

Go - In a high performance http client for load testing, how can I block/ignore all cookies?

我正在为我的公司创建工具来对我们的系统进行负载测试。我目前有用 Python 编写的工具,但我正在探索使用 Go 的选项,希望提高效率和性能,因为我们需要同时生成数百万用户(每个盒子有数千个,有很多盒子),每一点都很重要。我的用户主要对我们的系统进行 http 调用,我需要一个非常轻量级和高效的 http 客户端。

对于我们的 Python 工具,以前的员工有一些功能手动处理和重用套接字并完全忽略 cookie。虽然我是 Go 的新手,但到目前为止我已经比较了多个 Go 网络实现并且我对 CPU 和网络使用感到满意所以我认为我不需要手动管理套接字,但 RAM 使用率比我们的 Python 解决方案高出数倍。我怀疑这是由于这些 Go 实现自动维护和管理 cookie,因为其他更高级别的 Python 库做了同样的事情。我正在寻找让我的 http 客户端 disable/block/ignore 所有 cookie 来解决我的问题或排除 cookie 是我的内存膨胀罪魁祸首的方法。

我使用了一个简单的 net/http Get() 调用,fasthttp 创建了一个客户端,每个主机重用不同数量的连接(1000+),并创建了一个 net/http.Client 有和没有自定义 Transport。我已经使用 pprof 来记忆每个档案。在不覆盖 cookie 的情况下,我的 http.Client 流程似乎内存膨胀最少,而 fasthttp 最多。我试图浏览他们所有的文档并搜索 SO 和网络,但找不到任何明确忽略或阻止 cookie 的内容。我发现最接近请求和响应的是 fasthttp 的 DelAllCookies(),但调用它们对内存使用没有明显影响。我研究了 net/http/cookiejar 来为 net/http.Client 设置自定义 jar 和策略,但这看起来更像是一种存储和使用 cookie 数据的方式,我不想这样做,我也不想这样做找不到设置策略以完全忽略 cookie 的方法。

// fasthttp implementation
var httpClient *fasthttp.Client

func init() {
    httpClient = &fasthttp.Client{
        MaxConnsPerHost: 1000,
    }
}

func fastHTTPClient(method string, uri string) (string, time.Duration) {

    req := fasthttp.AcquireRequest()
    req.Header.SetMethod(method)
    req.SetRequestURI(uri)

    resp := fasthttp.AcquireResponse()

    startTime := time.Now()
    err := httpClient.DoTimeout(req, resp, targetDuration)
    elapsed := time.Since(startTime)

    if err != nil {
        log.Panicln(err)

        body := string(resp.Body())
        req.Header.DelAllCookies()
        resp.Header.DelAllCookies()
        fasthttp.ReleaseRequest(req)
        fasthttp.ReleaseResponse(resp)
        return body, elapsed
    }

    body := string(resp.Body())
    req.Header.DelAllCookies()
    resp.Header.DelAllCookies()
    fasthttp.ReleaseRequest(req)
    fasthttp.ReleaseResponse(resp)
    return body, elapsed
}

// net/http implementation
var tr = &http.Transport{}
var client = &http.Client{Transport: tr}

func netGet(method string, uri string) (string, time.Duration) {

    startTime := time.Now()
    resp, err := client.Get(uri)
    elapsed := time.Since(startTime)

    if err != nil {
        log.Panic(err)

        body, err2 := ioutil.ReadAll(resp.Body)
        resp.Body.Close()

        if err2 != nil {
            log.Panic(err)
        }

        return string(body), elapsed
    }

    body, err := ioutil.ReadAll(resp.Body)
    resp.Body.Close()

    if err != nil {
        log.Panicln(err)
    }

    return string(body), elapsed
}

同样,这些功能正常工作,但是当我 运行 数千个同时使用 boomer 时,我最终使用了数 GB 的 RAM,而我们的 Python 套接字实现使用了 1-1.5 GB .我怎样才能 block/ignore cookie 或以其他方式确定 cookie 不会占用我所有的内存?

Fasthttp 将始终将完整响应加载到内存中。因此,如果您的响应体很大并且想要限制内存使用,它可能不是您的最佳解决方案。

Fasthttp 还通过将缓冲区保留在内存中并重新使用它而不是花费 CPU 周期让垃圾收集器收集这些缓冲区来将内存使用量换成 CPU 使用量。

使用多个 GB 的内存似乎很多。在这种情况下,您是在查看 RSS 还是虚拟内存?

Cookie 只是响应中包含的 header。您无法阻止服务器返回 header。你只能接受它并在内存中读取它。尽管浏览器可以禁用本地 cookie,但它仍然不能阻止服务器返回带有 set-cookie header.

的 header

关于Fasthttp,看了一点源码,发现用了很多sync。 Pool是为了提高性能,但我没有发现它的目的是为了节省内存。它的目的只是快。

如果你很看重内存,建议直接包在http/net上或者找别的包,不要用fasthttp,不适合做压力测试