Original: Taste of Little Sister (wechat official ID: XjjDog), welcome to share, please reserve the source.

To use OkHttp, you must know its transparent compression, otherwise you won’t know how to die; Or live do not know why live not comfortable.

Not in a good way.

What is transparent compression? OkHttp automatically adds the accept-encoding :gzip request header when sending a request. So, when the returned data has a gzip response header content-Encoding =gzip, OkHttp automatically decompresses the data for us. (Accept-encoding and Content-Encoding are a pair of request headers, corresponding to request and return, respectively.)

Why compress? Because it can dramatically reduce the capacity of transmission. For low-CPU services like Kafka, you can turn on gzip compression to speed up the flow of information.

How high is this compression ratio? Take a look at the actual screenshot below, for ordinaryxmlorjson, data can be obtained from9MBCompressed into350KBLeft and right, the compression ratio is fully achieved26.

It makes system performance fly

SpringCloud microservices is now being used by a lot of companies. Even some traditional enterprises, some big data toB enterprises, also want to have a taste of crab.

For a simple SpringBoot service, we just need to configure the corresponding compression in the YML file. This completes the browser-to-Web service loop. This kind of compression, for the large amount of data services, is life-saving!

The configuration is as follows.

server:
  port: 8082
  compression:
    enabled: true
    min-response-size: 1024
    mime-types: ["text/html"."text/xml"."application/xml"."application/json"."application/octet-stream"]
Copy the code

It corresponds to the Spring configuration class is org.springframework.boot.web.server.Com pression.

But don’t count your chickens before they hatch. Because you’re in a distributed environment, the call chain is longer. Even on the Intranet, network transmission of more than 10 MB can take considerable time.

As shown above, a request from the browser to the actual service node may go through many steps.

  • Nginx forwards the request to the microservices gateway zuul
  • Zuul forwards to specific microservice A
  • Microservice A invokes microservice B through the Feign interface

If most of our data is supplied by microservice B, then any of the above links will be slow to transfer and will affect the performance of the request.

Therefore, we need to enable gzip compression for the Feign interface. Using OkHttp’s transparent proxy is the easiest way.

First, introduce Feign’s JAR package into the project.

dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-okhttp</artifactId>
</dependency>
Copy the code

Second, enable OkHttp in the YML file as Feign’s client request toolkit. To be on the safe side, we’ve also blocked HttpClient, which is too heavy and too old.

feign:
  httpclient:
    enabled: false
  okhttp:
    enabled: true
Copy the code

At this point, we can enjoy the convenience of OkHttp’s transparent proxy.

If your application has large data packets and long call chains, this approach may even add a few seconds to the performance of your service. Xjjdog once made a snail system fly by tweaking a few parameters. We exclaim: the original B end can also C once.

How does OkHttp implement transparent compression?

OkHttp handles transparent compression through interceptors. Concrete classes that okhttp3. Internal. HTTP. BridgeInterceptor.

If there is no accept-encoding header, add one.

// 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");
}
Copy the code

The most critical code is below.

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)));
}
Copy the code

You can see that in the if statement, there are three conditions.

  • Program is not setAccept-EncodingTo enable transparent compression
  • The server hasContent-EncodingHeader with gzip compression enabled
  • Have a packet

OkHttp’s transparent compression works only if all three conditions are met, helping us unpack automatically.

It dug a little deeper

Unfortunately, the above key code, only if, no else, that is, if any of the conditions are not met, the back end of the packet will return unchanged.

Conditions 2 and 3 are fine. There is no harm in returning the back-end data as is. The problem is in the first condition.

If you use the following code in your code:

Request.Builder builder = chain.request()
                .newBuilder()
                .addHeader("Accept"."application/json")
                .addHeader("Accept-Encoding"."gzip");
Copy the code

That is, the accept-encoding header is set manually. This is common, because it shows the rigor of the programmer’s thinking.

It is this rigour that causes problems.

If your back-end application does not start with Gzip compression enabled, the two are fine. But if your back-end application suddenly turns on gzip compression one day, your code will all be over.

The reason is that the server gzip package is returned as is, and you need to manually process the Gzip package.

So, it’s a good thing not to add, and a bad thing to add, unless you want to process gzip data yourself.

Since OkHttp is also widely available on Android, the consequences of not knowing this detail can be disastrous. Client update is slow, can only honestly back to the server.

There are always some invisible details behind intelligence. Just like behind xJjdog’s pure love, there is always a shyness. You will not know its beauty until you know more about it.

Xjjdog is a public account that doesn’t allow programmers to get sidetracked. Focus on infrastructure and Linux. Ten years architecture, ten billion daily flow, and you discuss the world of high concurrency, give you a different taste.