做的比较简约的网站,wordpress评论机器人,河南工程学院网站建设,优质服务的网页归档要使用OkHttp#xff0c;一定要知道它的透明压缩#xff0c;否则死都不知道怎么死的#xff1b;或者活也不知道为什么活的不舒坦。反正不是好事。什么叫透明压缩呢#xff1f;OkHttp在发送请求的时候#xff0c;会自动加入gzip请求头Accept-Encoding:gzip。所以#xff0… 要使用OkHttp一定要知道它的透明压缩否则死都不知道怎么死的或者活也不知道为什么活的不舒坦。反正不是好事。什么叫透明压缩呢OkHttp在发送请求的时候会自动加入gzip请求头Accept-Encoding:gzip。所以当返回的数据带有gzip响应头时Content-EncodinggzipOkHttp会自动帮我们解压数据。Accept-Encoding和Content-Encoding是一对请求头分别对应着请求和返回为什么要进行压缩呢因为它能大幅减少传输的容量。像一些CPU资源占用不高的服务比如Kafka我们就可以开启gzip压缩加快信息的流转。这个压缩比有多高呢可以看下下面实实在在的截图对于普通的xml或者json数据可以由9MB压缩到350KB左右压缩比足足达到了26。它让系统性能飞起来SpringCloud微服务体系现在有非常多的公司在用。即使是一些传统企业一些大数据量的toB企业也想尝一尝螃蟹。对于一个简单的SpringBoot服务我们只需要在yml文件中配置上相应的压缩就可以了。这样我们就打通了浏览器到Web服务的这一环。这种压缩方式对于大数据量的服务来说是救命式的具体配置如下。server:port: 8082compression:enabled: truemin-response-size: 1024mime-types: [text/html,text/xml,application/xml,application/json,application/octet-stream]
它所对应的Spring配置类是org.springframework.boot.web.server.Compression。但是不要高兴太早。由于是分布式环境这里面调用链就会长一些。即使是在内网动辄十几MB的网络传输也会耗费可观的时间。如上图一个请求从浏览器到达真正的服务节点可能要经过很多环节。nginx转发请求到微服务网关zuulzuul转发到具体的微服务A微服务A通过Feign接口调用微服务B如果我们的数据大多数是由微服务B提供的那么上面的任何一个环节传输效率慢都会影响请求的性能。所以我们需要开启Feign接口的gzip压缩。使用OkHttp的透明代理是最简单的方式。首先在项目中引入feign的jar包。dependencygroupIdio.github.openfeign/groupIdartifactIdfeign-okhttp/artifactId
/dependency
其次在yml文件中启用OkHttp作为feign的客户端请求工具包。稳妥起见我们同时屏蔽了httpclient这个东西太重太老了。feign:httpclient:enabled: falseokhttp:enabled: true
到此为止我们就可以享受OkHttp的透明代理带来的便捷性了。假如你的应用数据包大调用链长这种方式甚至会给你的服务带来数秒的性能提升。xjjdog就曾经靠调整几个参数就让一个蜗牛系统飞了起来。大家惊呼原来B端也可以C一下。OkHttp是如何实现透明压缩的OkHttp对于透明压缩的处理是通过拦截器来做的。具体的类就是okhttp3.internal.http.BridgeInterceptor。具体代码如下当判断没有Accept-Encoding头的时候就自行加入一个。// If we add an Accept-Encoding: gzip header field were responsible for also decompressing
// the transfer stream.
boolean transparentGzip false;
if (userRequest.header(Accept-Encoding) null userRequest.header(Range) null) {transparentGzip true;requestBuilder.header(Accept-Encoding, gzip);
}
最关键的代码在下面。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)));
}
可以看到if语句里有三个条件。程序没有设置Accept-Encoding启用了透明压缩服务端有Content-Encoding头并启用了gzip压缩有数据包只有同时满足这三个条件OkHttp的透明压缩才会起作用帮我们自动解压。它挖的坑有点深可惜的是上面的关键代码只有if没有else也就是当其中的任何一个条件不满足后端的数据包将原封不动的返回。2、3两个条件是没有什么问题的原样返回后端数据并没有什么损害问题就出在第一个条件里。如果你在代码中使用了下面的代码Request.Builder builder chain.request().newBuilder().addHeader(Accept, application/json).addHeader(Accept-Encoding, gzip);
也就是手动设置了Accept-Encoding头信息。这很常见因为这体现了程序员思维的严谨。正是这种严谨造成了问题。假如你的后端应用刚开始是没有开启gzip压缩的这时候两者相安无事但如果你的后端应用突然有一天开启了gzip压缩你的这段代码将全部over。原因就是服务端gzip数据包会原样返回你需要手动处理gzip数据包。所以不加是好事加了反而会坏事除非你想自己处理gzip数据。由于OkHttp在Android上应用也非常广泛如果你不知道这个细节造成的后果就是灾难性的。客户端更新慢只能老老实实回退服务端了。智能的背后总有些肉眼不可见的细节。就像是xjjdog纯情的背后总有一份羞涩。只有深入了解你才会知道它的美。
往期推荐
JDK15正式发布新增功能预览2020-09-17 漫画什么是红黑树整合版2020-09-15 字符串操作的12个小技巧2020-09-10 URL 去重的 6 种方案(附详细代码)2020-09-09 关注下方二维码收获更多干货