作者:張富春(ahfuzhang),轉載時請註明作者和引用鏈接,謝謝! cnblogs博客 zhihu Github 公眾號:一本正經的瞎扯 接上一篇:http 中使用 gzip 輸出內容時,如何預先壓縮前一半頁面? 經過實測,對線上一個輸出 html 的服務進行了改造,通過預先壓縮頁面前半部分的方 ...
作者:張富春(ahfuzhang),轉載時請註明作者和引用鏈接,謝謝!
接上一篇:http 中使用 gzip 輸出內容時,如何預先壓縮前一半頁面?
經過實測,對線上一個輸出 html 的服務進行了改造,通過預先壓縮頁面前半部分
的方法,此介面的性能提升了 20%.
對比項 | 無 gzip 壓縮 | gzip 壓縮+前半部分預壓縮 |
---|---|---|
輸出位元組數 | 4399 | 2246 |
每核 qps | 14052.63 | 16924.75 |
具體的寫法如下:
1.獲取改造後的庫
go get github.com/ahfuzhang/[email protected]
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.0
github.com/valyala/fasthttp v1.50.0
)
3.代碼:
package main
import (
"bytes"
_ "embed"
"fmt"
"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 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 output
w, _ := 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()
}
希望對你有用