作者:张富春(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. 华为云FusionInsight连续三次获得第一,加速释放数据要素价值

    摘要:近日,IDC发布<中国大数据平台市场研究报告,2021 H1>,华为云FusionInsight智能数据湖已连续三次获得大数据平台市场份额第一. 本文分享自华为云社区<华为云F ...

  2. Git 工具 - 子模块: submodule与subtree的使用

    git日常使用中,基本都是一个项目一个Git仓库的形式,那么当我们的代码中碰到了业务级别的需要复用的代码,我们一般怎么做呢? 比如:某个工作中的项目需要包含并使用另一个项目. 也许是第三方库,或者你独 ...

  3. java并发编程(2):Java多线程-java.util.concurrent高级工具

    高级多线程控制类 Java1.5提供了一个非常高效实用的多线程包:java.util.concurrent, 提供了大量高级工具,可以帮助开发者编写高效.易维护.结构清晰的Java多线程程序. Thr ...

  4. 从 Rancher 学习 K8s - Rancher 的基础使用

    舞台环境 Rancher v2.6.9 K8s v1.24.16 如果你不具备该环境,可以移步 使用 Rancher 安装 K8s 集群 查看.本文适合已经了解了 k8s 基础概念,想使用 ranch ...

  5. sed 流编辑器

    一.简介 非交互式的处理 一行一行的读入处理 占用系统空间少 大文件一般用sed节省内存 语法:语法 sed [选项] '行的定位 动作' 文件... 参数 说明 -e 允许进行多项编辑 -n 静默输 ...

  6. 什么?你居然没有鸭鸭邮箱?@duck.com邮箱注册与使用

    @duck.com 是由专注于隐私的搜索引擎DuckDuckGo提供的面向所有人的匿名邮箱. 注册者可以设置一个自定义前缀,比如 one@duck.com,接着设置接收邮箱(如pete@gmail.c ...

  7. 如何在 Debian 12 上安装 MariaDB

    MariaDB 是一个开源多线程的关系数据库管理系统,是 MySQL 的替代品. MariaDB 是 Debian 中 MySQL 的默认替换方案. 本教程介绍如何在 Debian 12 上安装 Ma ...

  8. 玩转AIGC,5分钟 Serverless 部署 Stable Diffustion 服务

    有没有一种可能,其实你早就在AIGC了?阿里云将提供免费Serverless函数计算产品资源,邀请你,体验一把AIGC级的毕加索.达芬奇.梵高等大师作画的快感.下面请尽情发挥你的想象空间!!双重奖品设 ...

  9. 7、SpringBoot-mybatis-plus引入

    系列导航 springBoot项目打jar包 1.springboot工程新建(单模块) 2.springboot创建多模块工程 3.springboot连接数据库 4.SpringBoot连接数据库 ...

  10. vue中引入其他网站页面

    https://blog.csdn.net/qq_36706878/article/details/102593309