作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!
- cnblogs博客
- zhihu
- Github
- 公众号:一本正经的瞎扯
接上一篇:http 中使用 gzip 输出内容时,如何预先压缩前一半页面?
经过实测,对线上一个输出 html 的服务进行了改造,通过预先压缩页面前半部分
的方法,此接口的性能提升了 20%.
对比项 | 无 gzip 压缩 | gzip 压缩+前半部分预压缩 |
---|---|---|
输出字节数 | 4399 | 2246 |
每核 qps | 14052.63 | 16924.75 |
具体的写法如下:
1.获取改造后的库
go get github.com/ahfuzhang/compress@v1.17.2
2.在 go.mod 中修改:
replace (github.com/klauspost/compress => github.com/ahfuzhang/compress v1.17.2)require (github.com/klauspost/compress v1.16.3 github.com/valyala/bytebufferpool v1.0.0github.com/valyala/fasthttp v1.50.0)
3.代码:
package mainimport ("bytes"_ "embed""fmt""log""os""github.com/klauspost/compress/gzip""github.com/valyala/bytebufferpool""github.com/valyala/fasthttp")//go:embed raw.htmlvar html string//go:embed raw.jsvar js stringfunc testGzipedHttp() { topHalf, digest := gzip.GetGzipedData([]byte(html)) // cache 页面的前一半, digest 是这些内容的 crc32 的校验和requestHandler := func(ctx *fasthttp.RequestCtx) {ctx.Response.Header.Add("Content-Type", "text/plain")ctx.Response.Header.Add("Content-Encoding", "gzip")switch string(ctx.Request.URI().RequestURI()) {case "/1": // direct outputw, _ := gzip.NewWriterLevel(ctx, gzip.BestCompression)w.Write([]byte(html))w.Write([]byte(js))w.Close()case "/2":w := gzip.GetWriter(ctx) // 使用对象池 w.WriteHeader() // 写 gzip 的头部信息,10 字节 w.WriteGzipedData([]byte(html), topHalf, digest) // 当这个缓存是第一次输出的时候,可以传入 digest 值,这样可以少算一次 crc32 // 当不是第一次输出的时候, 第三个参数 digest 填 0 w.Write([]byte(js)) gzip.PutWriter(w) // 必须调用,写入尾部信息,并放回对象池}}s := &fasthttp.Server{Handler: requestHandler,}if err := s.ListenAndServe(":8080"); err != nil {log.Fatalf("error in ListenAndServe: %v", err)}}func main() {testGzipedHttp()}
希望对你有用 😃
这个 case 已经分享到 fasthttp github, 希望未来能够集成这个能力进去:https://github.com/valyala/fasthttp/issues/1631