美文网首页
工作中用 GO: web 性能优化之 gzip

工作中用 GO: web 性能优化之 gzip

作者: daydaygo | 来源:发表于2024-12-01 13:57 被阅读0次

写在前面

最近遇到一个业务场景, 用户在第一次使用时会上传大量数据, 未优化前历史2年的数据需要20分钟, 和FE一起沟通后, 选择使用gzip压缩优化, 将时间压缩到5分钟内, 实测下来gzip能达到 3-10倍的压缩率

Go中使用gzip

以 hertz 框架为例, 使用 cwgo 脚手架初始化项目, 默认开启 gzip 中间件

func registerMiddleware(h *server.Hertz) {
    // gzip
    if conf.GetConf().Hertz.EnableGzip {
        h.Use(gzip.Gzip(gzip.DefaultCompression))
    }
}

社区提供的使用示例: gzip/gzip_test.go at main · hertz-contrib/gzip

func TestDecompressGzip(t *testing.T) {
    buf := &bytes.Buffer{}
    gz := compress.AcquireStacklessGzipWriter(buf, gzip.DefaultCompression)
    if _, err := gz.Write([]byte(testResponse)); err != nil {
        gz.Close()
        t.Fatal(err)
    }
    gz.Close()
    router := route.NewEngine(config.NewOptions([]config.Option{}))
    router.Use(Gzip(DefaultCompression, WithDecompressFn(DefaultDecompressHandle)))
    router.POST("/", func(ctx context.Context, c *app.RequestContext) {
        if v := c.Request.Header.Get("Content-Encoding"); v != "" {
            t.Errorf("unexpected `Content-Encoding`: %s header", v)
        }
        if v := c.Request.Header.Get("Content-Length"); v != "" {
            t.Errorf("unexpected `Content-Length`: %s header", v)
        }
        data := c.GetRawData()
        c.Data(200, "text/plain", data)
    })
    request := ut.PerformRequest(router, consts.MethodPost, "/", &ut.Body{Body: buf, Len: buf.Len()}, ut.Header{
        Key: "Content-Encoding", Value: "gzip",
    })
    w := request.Result()
    assert.Equal(t, http.StatusOK, w.StatusCode())
    assert.Equal(t, "", w.Header.Get("Content-Encoding"))
    assert.Equal(t, "", w.Header.Get("Vary"))
    assert.Equal(t, testResponse, string(w.Body()))
    assert.Equal(t, "18", w.Header.Get("Content-Length"))
}

最佳实践

  1. FE上传数据: json = jsonDecode(utf8.decode(GZipCodec().decode(params)));
  2. BE接收时是2 进制数据, 使用 debug + base64Encode 保存了一份, 方便后续调试
  3. 使用上面的 DefaultDecompressHandle, 发现获取的数据和步骤 2 中一样
  4. 和FE联调, 获取到了所有中间步骤的数据
flutter: postUseGzip params:
{metaInfo: {timezone: Asia/Shanghai}...}

flutter: postUseGzip jsonData:
{"metaInfo":{"timezone":"Asia/Shanghai"}...}

flutter: postUseGzip utf8List: [123, 34, 109, 101, 116, ...]

flutter: postUseGzip gzip: [31, 139, 8, 0, 0, 0, 0, 0, 0, ...]
  1. Go 中对 gzip 数据进行处理
func DataGzip(ctx context.Context, c *app.RequestContext) {
    b := c.Request.Body()
    g, err := gzip.NewReader(bytes.NewBuffer(b))
    if err != nil {
        hutil.RespErr(c, err)
        return
    }
    data, err := io.ReadAll(g) // 获取原始 json 数据
    if err != nil {
        hutil.RespErr(c, err)
        return
    }
    hlog.CtxInfof(ctx, fmt.Sprintf("gzip data: %s", string(data)))

        // do something...
    hutil.RespData(c, res)
}
  1. 和 FE 联调, FE 反馈请求无返回, 实测发现是步骤 2 中的 DefaultDecompressHandle 引起的, 会导致 response 使用 gzip 压缩后返回, 导致 FE 请求库无法解析导致的

写在最后

  • 了解web gzip 的原理和框架处理的机制, 可以少走很多弯路
  • debug 过程中保留所有中间步骤并使用 testcase 进行验证, 其实快很多

相关文章

  • web开发中的压缩、range范围请求

    压缩 Web服务器处理HTTP压缩之gzip、deflate压缩 【Web优化】Yslow优化法则(四)启用Gzi...

  • vue性能优化详解(三)

    前端路漫漫,优化无极限。本文主要从Web 技术方向讲述vue性能优化。 1.开启 gzip 压缩 即GNUzip,...

  • 前端性能优化

    js性能小贴士——优化循环 前端网页与js性能优化 我总结的js性能优化的小知识 提高 web 应用性能之 Jav...

  • 前端性能 优化 大全

    js性能小贴士——优化循环 前端网页与js性能优化 我总结的js性能优化的小知识 提高 web 应用性能之 Jav...

  • [性能优化]HTTP篇

    参考文章:Vue 项目性能优化 — 实践指南(网上最全 / 详细) 开启 gzip 压缩 gzip 是 GNUzi...

  • 前端性能优化之——gzip

    注: 文章摘自 juan26 - 思否 压缩方式 前端压缩的方式很多,依赖java的有ant工具,前端自己打包压缩...

  • nginx 启用 gzip压缩

    做为如今性能最好,使用最广泛的web服务器nginx来说。本身将具有gzip压缩的功能 什么是GZIP GZIP是...

  • WEB性能优化

    WEB性能优化

  • Apache2.4开启GZIP功能

    HTTP协议上的GZIP编码是一种用来改进WEB应用程序性能的技术。大流量的WEB站点常常使用GZIP压缩技术来让...

  • react项目 性能优化 首页优化 加载优化

    react项目 性能优化 首页优化 懒加载 按需加载 要做哪些事情 一. nginx 开启 gzip, 在 ng...

网友评论

      本文标题:工作中用 GO: web 性能优化之 gzip

      本文链接:https://www.haomeiwen.com/subject/enhjsjtx.html