作者:张富春(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

两个页面都正常。

http 中使用 gzip 输出内容时,如何预先压缩前一半页面?的更多相关文章

  1. 更改数据库字符集编码引起的问题、textarea标签输出内容时不能顶格(左对齐)输出

    用svn拉下来的项目,部署好的Oracle数据库(gbk编码),用tomcat部署好并发布项目,当访问相关网页时,出现乱码.于是把Oracle的字符编码改成utf8,tomcat也改成UTF-8,重新 ...

  2. textarea标签输出内容时不能顶格(左对齐)输出

    我用textarea输出文本内容的时候出现下面的问题:文本内容在action里测试没有问题(文本内容前面没有空格),但是在jsp页面textare标签中输出文本内容时,文本内容前面却出现一些多余的空格 ...

  3. C# Winform 中webBrowser显示html内容时禁止错误提示的方法

    在winform中有一个控件可以显示html的内容,该控件就是webbrowser,设置它的DocumenText属性为HTML的内容即可. 在使用WebBrowser做UI的时候,我们有时不希望里面 ...

  4. 如何获取SQL中Print语句输出内容

    SqlConnection cn = new SqlConnection("server=my\\my2005;database=rdwhdata2005;user id=zjh;passw ...

  5. 微信中关闭网页输入内容时的安全提示 [干掉 “防盗号或诈骗,请不要输入QQ密码”]

    未设置之前: 需要把域名加入白名单 设置方法:微信公共平台后台-->公众号设置--->功能设置--->填写业务域名即可.

  6. 【记录】尝试用android-logging-log4j去实现log输出内容到sd卡中的文件的功能

    [背景] 折腾: [记录]给Android中添加log日志输出到文件 期间,已经试了: [记录]尝试用android中microlog4android实现log输出到文件的功能 但是不好用. 然后就是 ...

  7. Shell 命令行 从日志文件中根据将符合内容的日志输出到另一个文件

    Shell 命令行 从日志文件中根据将符合内容的日志输出到另一个文件 前面我写了一篇博文Shell 从日志文件中选择时间段内的日志输出到另一个文件,利用循环实现了我想要实现的内容. 但是用这个脚本的同 ...

  8. 【转】JAVA输出内容打印到TXT以及不同系统中如何换行

    JAVA输出内容打印到TXT以及不同系统中如何换行 http://xiyang.09.blog.163.com/blog/static/59827615201172552755293/ 2011-08 ...

  9. 【转载】Eclipse:Android开发中如何查看System.out.println的输出内容

    Android开发中在代码中通过System.out.println的输出内容不知道去哪了,在console视图中看不到.而通过Log.i之类的要在Logcat视图中看到,夹杂了太多的其它App及底层 ...

  10. rev---将文件中的每行内容以字符为单位反序输出

    rev命令将文件中的每行内容以字符为单位反序输出,即第一个字符最后输出,最后一个字符最先输出,依次类推.

随机推荐

  1. 线下Meetup:在数智化转型背景下,火山引擎VeDI的大数据技术揭秘

     更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群   近日,联合火山引擎开发者社区,火山引擎数智平台(VeDI)<数智化转型背景下的火山引擎大数据技术揭秘& ...

  2. 多领域应用落地,火山引擎ByteHouse加速云数仓升级

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群   近日,火山引擎数智平台VeDI直播活动「超话数据」在线举办,来自火山引擎的产品及解决方案专家分享了以ByteH ...

  3. MongoDB 占用CPU资源过高

    情况如下 db.currentOp() 发现有全表扫描 将 Collscan 对应的 Collection 建索引 db.Table1.createIndex({"DataTime" ...

  4. .NetCore 接口请求耗时记录

    通过日志,记录每个接口请求的耗时情况 结合  <logger name="*" level="Trace" writeTo="tracefile ...

  5. Redis 数据一致性

    概述 当我们在使用缓存时,如果发生数据变更,那么你需要同时操作缓存和数据库,而它们两个又分属不同的系统,因此无法做到同时操作成功或失败,因此在并发读写下很可能出现缓存与数据库数据不一致的情况 理论上可 ...

  6. 文心一言 VS 讯飞星火 VS chatgpt (180)-- 算法导论13.4 3题

    三.用go语言,在练习13.3-2 中,将关键字 41.38.31.12.19.8 连续插入一棵初始的空树中,从而得到一棵红黑树.请给出从该树中连续删除关键字 8.12.19.31.38.41 后的红 ...

  7. 海外加速,让你拥有和 Steam 一样的高速下载

    Hello 各位亲爱的观众老爷们,好久不见呀. 暗影界的大门开了,育碧的限时原价结束了,美末 2 都拿年度游戏奖了,你们有猜到二狗子现在哪里么?听了不要吓一跳,二狗子刚刚抵达夜之城了!什么,你问二狗子 ...

  8. SD 信用模拟检查增强

    一.业务流程中需要进行信用模拟检查,但逻辑梳理较为复杂,因此借用交货单创建时信用检查逻辑.但是当交货单信用检查通过时,不创建交货单,因此需要对BAPI:BAPI_OUTB_DELIVERY_CREAT ...

  9. 【QT】tr()的作用

    函数 tr() 全名是 QObject::tr() ,被它处理的 字符串可以 使用工具提取出来翻译成其他语言, 也就是做国际化使用. 只要记住,Qt 的最佳实践:如果你想让你的程序国际化的话,那么,所 ...

  10. latex · markdown | 如何写矩阵和大公式

    1 \left[\begin{array}{c} a & b \\ c & d \end{array}\right] 效果: \[\left[\begin{array}{c} a &a ...