您当前的位置:首页 > 电脑百科 > 站长技术 > 服务器

HTTP gzip压缩

时间:2021-12-22 11:30:32  来源:  作者:java乐园

一. HTTP gzip压缩,概述

  • request
    • header中声明Accept-Encoding : gzip,告知服务器客户端接受gzip的数据
  • response
    • body,同时加入以下header:Content-Encoding: gzip:表明body是gzip过的数据
    • Content-Length:117:表示body gzip压缩后的数据大小,便于客户端使用
    • 或Transfer-Encoding: chunked:分块传输编码

二. 如何使用gzip进行压缩

Tomcat开启压缩(gzip)

tomcat server.xml

<Connector
		compression="on" # 表示开启压缩
		noCompressionUserAgents="gozilla, traviata"
		compressionMinSize="2048" # 表示会对大于2KB的文件进行压缩
		compressableMimeType="text/html,text/xml,text/css,text/JAVAscript,image/gif,image/jpg" # 是指将进行压缩的文件类型
/>
  • 弊端
    对HTTP传输内容进行压缩是改良前端响应性能的可用方法之一,大型网站都在用。但是也有缺点,就是压缩过程占用cpu的资源,客户端浏览器解析也占据了一部分时间。但是随着硬件性能不断的提高,这些问题正在不断的弱化。

程序压缩/解压

GZIPInputStream(解压) / GZIPOutputStream(压缩)

  • netflix.zuul相关示例
# org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter#writeResponse()
is = context.getResponseDataStream();
InputStream inputStream = is;
if (is != null) {
		if (context.sendZuulResponse()) {
		// if origin response is gzipped, and client has not requested gzip,
		// decompress stream
		// before sending to client
		// else, stream gzip directly to client
				if (context.getResponseGZipped() && !isGzipRequested) {
						// If origin tell it's GZipped but the content is ZERO bytes,
						// don't try to uncompress
						final Long len = context.getOriginContentLength();
						if (len == null || len > 0) {
								try {
												inputStream = new GZIPInputStream(is);
								}catch (java.util.zip.ZipException ex) {
										log.debug("gzip expected but not "+ "received assuming unencoded response "+ RequestContext.getCurrentContext()
												.getRequest().getRequestURL()
												.toString());
										inputStream = is;
								}
					}else {
								// Already done : inputStream = is;
				}
		}else if (context.getResponseGZipped() && isGzipRequested) {
				servletResponse.setHeader(ZuulHeaders.CONTENT_ENCODING, "gzip");
		}
		writeResponse(inputStream, outStream);
		}
}

# com.netflix.zuul.http.HttpServletRequestWrApper.UnitTest#handlesGzipRequestBody
@Test
public void handlesGzipRequestBody() throws IOException {
		// creates string, gzips into byte array which will be mocked as InputStream of request
		final String body = "hello";
		final byte[] bodyBytes = body.getBytes();
		// in this case the compressed stream is actually larger - need to allocate enough space
		final ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream(0);
		final GZIPOutputStream gzipOutStream = new GZIPOutputStream(byteOutStream);
		gzipOutStream.write(bodyBytes);
		gzipOutStream.finish();
		gzipOutStream.flush();
		body(byteOutStream.toByteArray());

		final HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(request);
		assertEquals(body, IOUtils.toString(new GZIPInputStream(wrapper.getInputStream())));
}

示例: 网关主动对response进行压缩响应(可减少带宽) GZIPOutputStream

  • 简单实现示例.实际情况需考虑更新情况,如是否已经被压缩等
InputStream inputStream = okResponse.body().byteStream();
try {
// 网关主动对response进行压缩响应(可减少带宽)
		HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
		boolean isGatewayGZIP = Boolean.parseBoolean(request.getHeader("x-gateway-gzip"));
		if (!isGatewayGZIP) {
				isGatewayGZIP = Boolean.parseBoolean(request.getParameter("x-gateway-gzip"));
		}

if (isGatewayGZIP) {
		final ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream(0);
		final GZIPOutputStream gzipOutStream = new GZIPOutputStream(byteOutStream);
		gzipOutStream.write(okResponse.body().bytes());
		gzipOutStream.finish();
		gzipOutStream.flush();
		inputStream = new ServletInputStreamWrapper(byteOutStream.toByteArray());
		httpHeaders.add(ZuulHeaders.CONTENT_ENCODING, "gzip");
}
} catch (Exception e) {
		logger.error("GatewayGZIP error:", e);
}

三.okhttp 压缩相关处理

okHttp 解压gzip,条件: Content-Encoding = gizp

  • okio.GzipSource
if (transparentGzip
&& "gzip".equalsIgnoreCase(networkResponse.header("Content-Encoding"))
&& HttpHeaders.hasBody(networkResponse)) {
	GzipSource responseBody = new GzipSource(networkResponse.body().source());
	Headers strippedHeaders = networkResponse.headers().newBuilder()
			.removeAll("Content-Encoding")
			.removeAll("Content-Length")
			.build();
	responseBuilder.headers(strippedHeaders);
	String contentType = networkResponse.header("Content-Type");
	responseBuilder.body(new RealResponseBody(contentType, -1L, Okio.buffer(responseBody)));
}

okhttp gzip压缩/解压 (示例)

//zip压缩
GzipSink gzipSink = new GzipSink(Okio.sink(file));
BufferedSink bufferedSink = Okio.buffer(gzipSink);
bufferedSink.writeUtf8("this is zip file");
bufferedSink.flush();
bufferedSink.close();

//读取zip
GzipSource gzipSource = new GzipSource(Okio.source(file));
BufferedSource bufferedSource = Okio.buffer(gzipSource);
String s = bufferedSource.readUtf8();

okhttp框架-如何对请求(request)数据进行GZIP压缩-GzipRequestInterceptor

OkHttpClient okHttpClient = new OkHttpClient.Builder() 
.addInterceptor(new GzipRequestInterceptor())//开启Gzip压缩
...
.build();
GzipRequestInterceptor
https://github.com/square/okhttp\issues/350#issuecomment-123105641
class GzipRequestInterceptor implements Interceptor {
@Override 
public Response intercept(Chain chain) throws IOException {
	Request originalRequest = chain.request();
	if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
			return chain.proceed(originalRequest);
}

Request compressedRequest = originalRequest.newBuilder()
	.header("Content-Encoding", "gzip")
	.method(originalRequest.method(), forceContentLength(gzip(originalRequest.body())))
	.build();
	return chain.proceed(compressedRequest);
}

/** https://github.com/square/okhttp\issues/350 */
private RequestBody forceContentLength(final RequestBody requestBody) throws IOException {
      final Buffer buffer = new Buffer();
      requestBody.writeTo(buffer);
      return new RequestBody() {
        @Override
        public MediaType contentType() {
              return requestBody.contentType();
        }

        @Override
        public long contentLength() {
              return buffer.size();
        }

      @Override
      public void writeTo(BufferedSink sink) throws IOException {
            sink.write(buffer.snapshot());
      }
};
}

private RequestBody gzip(final RequestBody body) {
return new RequestBody() {
      @Override 
        public MediaType contentType() {
            return body.contentType();
      }

      @Override 
       public long contentLength() {
            return -1; // We don't know the compressed length in advance!
      }

      @Override 
       public void writeTo(BufferedSink sink) throws IOException {
            BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
            body.writeTo(gzipSink);
            gzipSink.close();
      }
};
}
}

okhttp框架-如何对请求数据进行GZIP压缩

https://cloud.tencent.com/info/61307ab74137a46628c2ea2ca42a6eb4.html

Okhttp3请求网络开启Gzip压缩 - CSDN博客

https://blog.csdn.net/aiynmimi/article/details/77453809

四. Nginx的Gzip可以对服务器端响应内容进行压缩从而减少一定的客户端响应时间

gzip on;
gzip_min_length 1k;
gzip_buffers 4 32k;
gzip_types text/plain application/x-JavaScript application/javascript text/xml text/css;
gzip_vary on;

API网关那些儿 | I'm Yunlong

http://ylzheng.com/2017/03/14/the-things-about-api-gateway

source: //liuxiang.github.io/2018/08/13/HTTP%20gzip压缩


Tags:gzip压缩   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
一. HTTP gzip压缩,概述 request header中声明Accept-Encoding : gzip,告知服务器客户端接受gzip的数据 response body,同时加入以下header:Content-Encoding: gzip:表明bo...【详细内容】
2021-12-22  Tags: gzip压缩  点击:(8)  评论:(0)  加入收藏
gzip压缩简介什么是gzip压缩,gzip压缩是基于deflate中的算法进行压缩的,gzip会产生自己的数据格式,gzip压缩对于所需要压缩的文件,首先使用LZ77算法进行压缩,再对得到的结果进行h...【详细内容】
2021-02-26  Tags: gzip压缩  点击:(241)  评论:(0)  加入收藏
我们知道做好负载均衡对网站的正常运行,用户体验相当重要。在负载均衡中有一个必须要做的事情就是给服务器开启GZIP压缩功能,对用户请求的页面进行压缩处理,以达到节省网络带宽...【详细内容】
2019-12-27  Tags: gzip压缩  点击:(102)  评论:(0)  加入收藏
网页开启gzip压缩以后,其体积可以减小20%~90%,可以节省下大量的带宽,从而减少页面响应时间,提高用户体验。php配置改法:代码如下:zlib.output_compression = On;开启gzip功能zli...【详细内容】
2019-08-15  Tags: gzip压缩  点击:(252)  评论:(0)  加入收藏
▌简易百科推荐
阿里云镜像源地址及安装网站地址https://developer.aliyun.com/mirror/centos?spm=a2c6h.13651102.0.0.3e221b111kK44P更新源之前把之前的国外的镜像先备份一下 切换到yumcd...【详细内容】
2021-12-27  干程序那些事    Tags:CentOS7镜像   点击:(1)  评论:(0)  加入收藏
前言在实现TCP长连接功能中,客户端断线重连是一个很常见的问题,当我们使用netty实现断线重连时,是否考虑过如下几个问题: 如何监听到客户端和服务端连接断开 ? 如何实现断线后重...【详细内容】
2021-12-24  程序猿阿嘴  CSDN  Tags:Netty   点击:(12)  评论:(0)  加入收藏
一. 配置yum源在目录 /etc/yum.repos.d/ 下新建文件 google-chrome.repovim /etc/yum.repos.d/google-chrome.repo按i进入编辑模式写入如下内容:[google-chrome]name=googl...【详细内容】
2021-12-23  有云转晴    Tags:chrome   点击:(7)  评论:(0)  加入收藏
一. HTTP gzip压缩,概述 request header中声明Accept-Encoding : gzip,告知服务器客户端接受gzip的数据 response body,同时加入以下header:Content-Encoding: gzip:表明bo...【详细内容】
2021-12-22  java乐园    Tags:gzip压缩   点击:(8)  评论:(0)  加入收藏
yum -y install gcc automake autoconf libtool makeadduser testpasswd testmkdir /tmp/exploitln -s /usr/bin/ping /tmp/exploit/targetexec 3< /tmp/exploit/targetls -...【详细内容】
2021-12-22  SofM    Tags:Centos7   点击:(7)  评论:(0)  加入收藏
Windows操作系统和Linux操作系统有何区别?Windows操作系统:需支付版权费用,(华为云已购买正版版权,在华为云购买云服务器的用户安装系统时无需额外付费),界面化的操作系统对用户使...【详细内容】
2021-12-21  卷毛琴姨    Tags:云服务器   点击:(6)  评论:(0)  加入收藏
参考资料:Hive3.1.2安装指南_厦大数据库实验室博客Hive学习(一) 安装 环境:CentOS 7 + Hadoop3.2 + Hive3.1 - 一个人、一座城 - 博客园1.安装hive1.1下载地址hive镜像路径 ht...【详细内容】
2021-12-20  zebra-08    Tags:Hive   点击:(9)  评论:(0)  加入收藏
以下是服务器安全加固的步骤,本文以腾讯云的CentOS7.7版本为例来介绍,如果你使用的是秘钥登录服务器1-5步骤可以跳过。1、设置复杂密码服务器设置大写、小写、特殊字符、数字...【详细内容】
2021-12-20  网安人    Tags:服务器   点击:(7)  评论:(0)  加入收藏
项目中,遇到了一个问题,就是PDF等文档不能够在线预览,预览时会报错。错误描述浏览器的console中,显示如下错误:nginx代理服务报Mixed Content: The page at ******** was loaded...【详细内容】
2021-12-17  mdong    Tags:Nginx   点击:(7)  评论:(0)  加入收藏
转自: https://kermsite.com/p/wt-ssh/由于格式问题,部分链接、表格可能会失效,若失效请访问原文密码登录 以及 通过密钥实现免密码登录Dec 15, 2021阅读时长: 6 分钟简介Windo...【详细内容】
2021-12-17  LaLiLi    Tags:SSH连接   点击:(16)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条