作者:张富春(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. A/B 实验避坑指南:为什么不建议开 AABB 实验

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 本文将针对日常开设 A/B 实验过程中一个不太合理的使用方法--AABB 实验进行详细的解释,告诉大家为什么不建议 ...

  2. Solon Aop 特色开发(6)新鲜货提取器,提取Bean的函数进行定制开发

    Solon,更小.更快.更自由!本系列专门介绍Solon Aop方面的特色: <Solon Aop 特色开发(1)注入或手动获取配置> <Solon Aop 特色开发(2)注入或手动 ...

  3. gunicorn 高性能wsgi服务器

    参考: https://zhuanlan.zhihu.com/p/102716258 Gunicorn是什么 Gunicorn Green Unicorn 是一个 UNIX 下的 WSGI HTTP ...

  4. 神经网络优化篇:详解指数加权平均的偏差修正(Bias correction in exponentially weighted averages)

    指数加权平均的偏差修正 \({{v}_{t}}=\beta {{v}_{t-1}}+(1-\beta ){{\theta }_{t}}\) 在上一个博客中,这个(红色)曲线对应\(\beta\)的值为 ...

  5. 【JAVA基础】批处理脚本

    update ifp_project set is_self_run = 'N' where is_self_run is null; update ifp_invoice_header set is ...

  6. 2024-01-17:lc的30. 串联所有单词的子串

    2024-01-17:用go语言,给定一个字符串 s 和一个字符串数组 words. words 中所有字符串 长度相同. s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接 ...

  7. SpringBoot Serverless 实战 | 监控调试

    SpringBoot 是基于 Java Spring 框架的套件,它预装了 Spring 的一系列组件,让开发者只需要很少的配置就可以创建独立运行的应用程序.在云原生的世界,有大量的平台可以运行 Sp ...

  8. vue学习笔记 十七、父子组件 ---> 子组件传值

    系列导航 vue学习笔记 一.环境搭建 vue学习笔记 二.环境搭建+项目创建 vue学习笔记 三.文件和目录结构 vue学习笔记 四.定义组件(组件基本结构) vue学习笔记 五.创建子组件实例 v ...

  9. 用C#实现最小二乘法(用OxyPlot绘图)✨

    最小二乘法介绍 最小二乘法(Least Squares Method)是一种常见的数学优化技术,广泛应用于数据拟合.回归分析和参数估计等领域.其目标是通过最小化残差平方和来找到一组参数,使得模型预测值 ...

  10. js - 异步加载图片到 dom

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...