OkHttp透明压缩,收获性能10倍,外加故障一枚

要使用OkHttp,一定要知道它的透明压缩,否则死都不知道怎么死的;或者活也不知道为什么活的不舒坦。

反正不是好事。

什么叫透明压缩呢?OkHttp在发送请求的时候,会自动加入gzip请求头Accept-Encoding:gzip。所以,当返回的数据带有gzip响应头时Content-Encoding=gzip,OkHttp会自动帮我们解压数据。(Accept-EncodingContent-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转发请求到微服务网关zuul

  • zuul转发到具体的微服务A

  • 微服务A通过Feign接口调用微服务B

如果我们的数据,大多数是由微服务B提供的,那么上面的任何一个环节传输效率慢,都会影响请求的性能。

所以,我们需要开启Feign接口的gzip压缩。使用OkHttp的透明代理是最简单的方式。

首先,在项目中引入feign的jar包。

dependency><groupId>io.github.openfeign</groupId><artifactId>feign-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 we're 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数据。

由于OkHttpAndroid上应用也非常广泛,如果你不知道这个细节,造成的后果就是灾难性的。客户端更新慢,只能老老实实回退服务端了。

智能的背后,总有些肉眼不可见的细节。就像是xjjdog纯情的背后,总有一份羞涩。只有深入了解,你才会知道它的美。


往期推荐

JDK15正式发布,新增功能预览!

2020-09-17

漫画:什么是红黑树?(整合版)

2020-09-15

字符串操作的12个小技巧!

2020-09-10

URL 去重的 6 种方案!(附详细代码)

2020-09-09

关注下方二维码,收获更多干货!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/545840.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

块元素、行内块和内联元素_如何删除内联块元素之间的空间?

块元素、行内块和内联元素Introduction: 介绍&#xff1a; This question has become rather popular. How does one remove whitespaces between the inline-block elements? The interesting thing is there are numerous solutions to this but not all of them are easy …

Spring--quartz中cronExpression 的配置方法

Spring--quartz中cronExpression Java代码 字段 允许值 允许的特殊字符 秒 0-59 , - * / 分 0-59 , - * / 小时 0-23 , - * / 日期 1-31 , - * ? / L W C 月份 1-12 或者 JAN-DEC , - * /…

C语言图形库——EasyX基本贴图

在C语言的学习过程中&#xff0c;接触最多的就是黑乎乎的DOS窗口&#xff0c;这也是在消磨学习者的兴趣&#xff0c;学到最后可能还不知道C语言到底能做什么&#xff0c;难道就是输入输出数据吗&#xff1f;当然不是&#xff0c;C的用处很广泛&#xff0c;这里不做讨论。我们能…

一气之下,手撸了一个抖音去水印的工具!

百因必有果说一下我为什么要做个抖音视频去水印工具&#xff0c;其实是因为我的沙雕女友&#xff0c;她居然刚我~有天晚上她在抖音看见一个非常具有 教育意义 的视频&#xff0c;“男人疼媳妇就该承包全部家务活”&#xff0c;然后它就想把视频下载下来&#xff0c;分享到她的姐…

css 隐藏元素 显示元素_使用CSS打印时如何隐藏元素?

css 隐藏元素 显示元素Introduction: 介绍&#xff1a; We have come across many challenges while developing a website or web page and every challenge comes with new learnings. It is a trait of a good developer who develops or creates websites or web pages by…

Java新特性:数据类型可以扔掉了?

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;在很久很久以前&#xff0c;我们写代码时要慎重的考虑变量的数据类型&#xff0c;比如下面这些&#xff1a;枚举&#xff1a…

Spyder:Python中机器学习的强大武器

So, first of all, you would need to install Anaconda distribution which can be downloaded from the link https://www.anaconda.com/download/ (for Windows users only). 因此&#xff0c;首先&#xff0c;您需要安装Anaconda发行版 &#xff0c;可以从链接https://www.…

对内存重叠的深入认识

内存重叠&#xff1a;拷贝的目的地址在源地址范围内。所谓内存重叠就是拷贝的目的地址和源地址有重叠。在函数strcpy和函数memcpy都没有对内存重叠做处理的&#xff0c;使用这两个函数的时候只有程序员自己保证源地址和目标地址不重叠&#xff0c;或者使用memmove函数进行内存拷…

Android特效 五种Toast具体解释

Toast是Android中用来显示显示信息的一种机制&#xff0c;和Dialog不一样的是&#xff0c;Toast是没有焦点的&#xff0c;并且Toast显示的时间有限&#xff0c;过一定的时间就会自己主动消失。 1.默认效果: 代码:Toast.makeText(getApplicationContext(), "默认Toast样式&…

为什么阿里巴巴禁止使用BigDecimal的equals方法做等值比较?

△一个对Coding有着独特追求的人△作者 l Hollis来源 l Hollis&#xff08;ID&#xff1a;hollischuang&#xff09;BigDecimal&#xff0c;相信对于很多人来说都不陌生&#xff0c;很多人都知道他的用法&#xff0c;这是一种java.math包中提供的一种可以用来进行精确运算的类型…

动图演示:手撸堆栈的两种实现方法!

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;正式开始之前&#xff0c;先和各位朋友聊聊公众号后期的一些打算&#xff0c;后面的文章计划写一些关于数据结构和算法的内容…

多图带你彻底理解Java中的21种锁!

作者 | 悟空聊架构来源 | 悟空聊架构&#xff08;ID&#xff1a;PassJava666&#xff09;本篇主要内容如下&#xff1a;本篇主要内容本篇文章已收纳到我的Java在线文档、 Github我的SpringCloud实战项目持续更新中帮你总结好的锁&#xff1a;序号锁名称应用1乐观锁CAS2悲观锁sy…

杨辉三角——数组解决

杨辉三角如图下所示&#xff0c;每一行的第一个数和最后一个数都为1&#xff0c;每一行中间的数&#xff08;出去第一个和最后一个&#xff09;a等于上一行与其相同列数的数b与数b前面的数之和。例&#xff1a; 第3行第2列的数是3&#xff0c;它就等于第2行第2列的数&#xff…

VS生成的exe文件如何在其他电脑上运行

在VS编译器上编写的程序都会生成一个exe文件&#xff0c;有时候写了一个很装逼的程序想在别人电脑炫耀一下&#xff0c;奈何将这个exe文件拷贝过去并不能运行&#xff0c;直接宣告装逼失败。为此将介绍一下如何将生成的exe文件在其他电脑上运行&#xff0c;步骤如下&#xff1a…

netty websocket 简单消息推送demo

2019独角兽企业重金招聘Python工程师标准>>> 今天心情很不好&#xff01;&#xff01;&#xff01; 原因保密。 这篇是基于"netty与websocket通信demo"。 错误想法&#xff1a;大量客户请求&#xff0c;共用一个worker&#xff0c;来实现推送。 正确作法&…

给 JDK 官方提了一个 Bug,结果...

图 by&#xff1a;石头北京-望京关于作者&#xff1a;程序猿石头(ID: tangleithu)&#xff0c;现任阿里巴巴技术专家&#xff0c;清华学渣&#xff0c;前大疆后端 Leader。背景分享一下之前踩的一个坑&#xff0c;背景是这样的&#xff1a;我们的项目依赖于一个外部服务&#x…

解决exe文件在别人电脑上运行缺失文件情况

这里就以vs2013为例&#xff1a;编译后生成的exe文件拷贝到别人电脑上运行是会弹出一个窗口说缺失MSVCR120.dll和MSVCR120D.dll这两个文件。&#xff08;其他vs版本的编译器在所提示的缺失文件按下述方法也可解决&#xff09;下面就介绍一种方法解决。 1、在VS2013软件中找到MS…

32张图带你彻底搞懂事务和锁!

作者 | 悟空聊架构来源 | 悟空聊架构&#xff08;ID&#xff1a;PassJava666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;PassJava&#xff09;本篇主要内容如下&#xff1a;本篇主要内容一、事务1.1 什么是事务为单个工作单元而执行的一系列操作。如查询、修改数…

分布式映射与集中式映射_K映射上的表达式映射和组包围

分布式映射与集中式映射In the previous article (Karnaugh Map 2, 3 and 4- variable) we have already discussed the designing of K-Map and various forms in which they are represented based on either they are being mapped for minterm or maxterm. 在上一篇文章( 卡…

JDK 竟然是这样实现栈的?

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;前面的文章《动图演示&#xff1a;手撸堆栈的两种实现方法&#xff01;》我们用数组和链表来实现了自定义的栈结构&#xff…