一. 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
<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(压缩)
- ne相关示例
# org.springframework.cloud.ne.filters.post.SendResponseFilter#writeResponse() is = con(); inputStream inputStream = is; if (is != null) { if ()) { // if origin response is gzipped, and client has not requested gzip, // decompress stream // before sending to client // else, stream gzip directly to client if () && !isGzipRequested) { // If origin tell it's GZipped but the content is ZERO bytes, // don't try to uncompress final Long len = con(); if (len == null || len > 0) { try { inputStream = new GZIPInputStream(is); }catch ex) { log.debug("gzip expected but not "+ "received assuming unencoded response "+ Reque() .getRequest().getRequestURL() .toString()); inputStream = is; } }else { // Already done : inputStream = is; } }else if () && isGzipRequested) { , "gzip"); } writeResponse(inputStream, outStream); } } # com.ne.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); gzi(bodyBytes); gzi(); gzi(); body()); final HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(request); assertEquals(body, IOU(new GZIPInputStream()))); }
示例: 网关主动对response进行压缩响应(可减少带宽) GZIPOutputStream
- 简单实现示例.实际情况需考虑更新情况,如是否已经被压缩等
InputStream inputStream = okRe().byteStream(); try { // 网关主动对response进行压缩响应(可减少带宽) HttpServletRequest request = Reque().getRequest(); Boolean isGatewayGZIP = Boolean.parseBoolean("x-gateway-gzip")); if (!isGatewayGZIP) { isGatewayGZIP = Boolean.parseBoolean("x-gateway-gzip")); } if (isGatewayGZIP) { final ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream(0); final GZIPOutputStream gzipOutStream = new GZIPOutputStream(byteOutStream); gzi(okRe().bytes()); gzi(); gzi(); inputStream = new ServletInputStreamWrapper()); , "gzip"); } } catch (Exception e) { logger.error("GatewayGZIP error:", e); }
三.okhttp 压缩相关处理
okHttp 解压gzip,条件: Content-Encoding = gizp
- okio.GzipSource
if (transparentGzip && "gzip".equalsIgnoreCase("Content-Encoding")) && H(networkResponse)) { GzipSource responseBody = new GzipSource(networkRe().source()); Headers strippedHeaders = ne().newBuilder() .removeAll("Content-Encoding") .removeAll("Content-Length") .build(); re(strippedHeaders); String contentType = ne("Content-Type"); re(new RealResponseBody(contentType, -1L, Okio.buffer(responseBody))); }
okhttp gzip压缩/解压 (示例)
//zip压缩 GzipSink gzipSink = new GzipSink(file)); BufferedSink bufferedSink = Okio.buffer(gzipSink); bu("this is zip file"); bu(); bu(); //读取zip GzipSource gzipSource = new GzipSource(file)); BufferedSource bufferedSource = Okio.buffer(gzipSource); String s = bu();
okhttp框架-如何对请求(request)数据进行GZIP压缩-GzipRequestInterceptor
OkHttpClient okHttpClient = new OkH() .addInterceptor(new GzipRequestInterceptor())//开启Gzip压缩 ... .build(); GzipRequestInterceptor \\issues/350#issuecomment-123105641 class GzipRequestInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request originalRequest = c(); if () == null || originalReque("Content-Encoding") != null) { return c(originalRequest); } Request compressedRequest = originalReque() .header("Content-Encoding", "gzip") .method(), forceContentLength(gzip()))) .build(); return c(compressedRequest); } /** \\issues/350 */ private RequestBody forceContentLength(final RequestBody requestBody) throws IOException { final Buffer buffer = new Buffer(); reque(buffer); return new RequestBody() { @Override public MediaType contentType() { return reque(); } @Override public long contentLength() { return bu(); } @Override public void writeTo(BufferedSink sink) throws IOException { ()); } }; } 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); gzi(); } }; } }
okhttp框架-如何对请求数据进行GZIP压缩
Okhttp3请求网络开启Gzip压缩 - CSDN博客
四. 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
source: 压缩