http 中使用 gzip 输出内容时,如何预先压缩前一半页面?
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!
背景是这样:要输出一个很大的动态页面,不开 gzip 压缩会使得流量很大;开了 gzip 压缩又会导致 cpu 升高。
这个页面的前半部分一般不会变化,变化的是后半部分。
因此,能不能把页面的前半部分预先压缩好,输出的时候只压缩后半部分?
目前已经实现了,具体如下:
1.我修改了github.com/klauspost/compress
这个项目,增加了WriteGzipedData()
这样的方法,即数据流中的某个片段是已经压缩好的内容,便不会消耗 cpu 进行压缩。
可以获取这部分代码:go get github.com/ahfuzhang/compress@v1.17.1
2.在自己项目的 go.mod 中,增加 replace:
replace ( github.com/klauspost/compress => github.com/ahfuzhang/compress v1.17.1 ) require ( github.com/klauspost/compress v1.16.3 github.com/valyala/bytebufferpool v1.0.0 github.com/valyala/fasthttp v1.50.0 )
3.http服务的代码如下:
package main import ( "bytes" _ "embed" "fmt" "gzip_part/stringsutil" "log" "os" "github.com/klauspost/compress/gzip" "github.com/valyala/bytebufferpool" "github.com/valyala/fasthttp" ) //go:embed raw.html var html string //go:embed raw.js var js string func getGziped(b []byte) []byte { // 用于预先压缩某个片段 buf := bytebufferpool.Get() buf.Reset() w, _ := gzip.NewWriterLevel(buf, gzip.BestCompression) w.Write(nil) w.Flush() headLen := buf.Len() w.Write(b) w.Flush() out := make([]byte, buf.Len()-headLen) copy(out, buf.B[headLen:]) w.Close() bytebufferpool.Put(buf) return out } func testGzipedHttp() { topHalf := getGziped([]byte(html)) // cache 页面的前一半 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 output w, _ := gzip.NewWriterLevel(ctx, gzip.BestCompression) w.Write([]byte(html)) w.Write([]byte(js)) w.Close() case "/2": w, _ := gzip.NewWriterLevel(ctx, gzip.BestCompression) w.WriteGzipedData([]byte(html), topHalf) w.Write([]byte(js)) w.Close() } } s := &fasthttp.Server{ Handler: requestHandler, } if err := s.ListenAndServe(":8080"); err != nil { log.Fatalf("error in ListenAndServe: %v", err) } } func main() { testGzipedHttp() }
测试如下:
curl -G "http://127.0.0.1:8080/1" -v --compressed curl -G "http://127.0.0.1:8080/2" -v --compressed
两个页面都正常。
分类:
golang
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库