Interviewer: Shrimp, I miss you so much. You haven’t come to interview me for a long time.

Shrimp: Emmmmmmm, this is not afraid of being hit by you.

Interviewer: OK, it seems to be prepared, so today we talk about how to do network optimization.

Shrimp: I was careless, did not flash. Old man, if you don’t tell me about martial arts, I’ll tell you about rat tail.

How do you optimize a network request?

I believe you may be asked this question in the interview. What I’m going to do today is talk about some simple optimization techniques that I know can help you get some basic grades in the interview process.

Let’s start with the simplest, the easiest thing for you to understand.

DNS optimization

DNS is a typical application layer protocol. As for why layer 2 can check layer 3 IP, DNS is an abbreviation of Domain Name System, so you can consider whether it is a service.

When an Http request initiates a Tcp connection, it generates a DNS, so why don’t we cache the Host’s IP through a HashMap, and then the next time we initiate a Tcp connection, we can use the IP directly in memory, Without having to go through the Dns service again.

At this time you will certainly ask me, god, you this is not to engage me, this can how to change ah?

If your network layer uses OkHttp, OkHttp is encapsulated with this in mind. It provides an internal Dns interface that can be passed from the outside to the Client when it is constructed.

class HttpDns : Dns {

    private val cacheHost = hashMapOf<String, InetAddress>()
    
    override fun lookup(hostname: String): MutableList<InetAddress> {
        if(cacheHost.containsKey(hostname)) { cacheHost[hostname]? .apply {return mutableListOf(this)}}return try{ InetAddress.getAllByName(hostname)? .first()? .apply { cacheHost[hostname] =this
            }
            mutableListOf(*InetAddress.getAllByName(hostname))
        } catch (e: NullPointerException) {
            val unknownHostException =
                UnknownHostException("Broken system behaviour for dns lookup of $hostname")
            unknownHostException.initCause(e)
            throw unknownHostException
        }
    }
}
Copy the code

LocalDns can not be trusted, often there will be some operators will do some strange Dns interception, resulting in the request received by the operator is cached (in order to save traffic), so Ali Tencent and other external output of HttpDns services. This service can help you find the real and accurate Ip of Host, but this service is charged.

If you’re an IOS developer, you should be aware of the SNI(Server Name Indication) problem, where multiple Https certificates correspond to one IP.

CacheControl

Http requests introduced CacheControl in phase 1.1, which allows the back end to directly control the caching policy for the requested content. So what’s a simpler way to optimize a network than caching?

In HTTP, there are two fields that Control the caching switch: Pragma and cache-control.

Here is a brief introduction to some cache parameters using images.

If I’m being irresponsible, all you need to do is start CacheControl, which the native network libraries already support. You can also add a unified CacheControl for network requests by adding the OkHttp interceptor. Of course, if you have customized requirements, you must develop your own. You can refer to this warehouse for details.

The HTTP protocol specification defines the ETag as the entity value of the requested variable. Another way to put it is that an ETag is a token that can be associated with a Web resource. A typical Web resource can be a Web page, but it can also be a JSON or XML document. ETag:” 50b1C1d4F775C61 :df3″ The client query update format looks like this: if-none-match: W/” 50B1C1D4F775C61 :df3″ Returns the status 304 and does not return if the ETag has not changed, the same as last-modified. Testing Etag is useful primarily for breakpoint downloads.

As long as you’re using CacheControl, you can use ETag, and if you’re not transferring data if the data content hasn’t changed, you can also optimize your Api requests a little bit.

Http 1.0-1.1-1..x-2.0

All of the following information comes from the differences between web HTTP1.0, HTTP1.1, and HTTP2.0

Of course we can also have the backend upgrade the interface protocol version, this can significantly improve your request response performance.

  1. PersistentConnection. HTTP 1.1 supports PersistentConnection and Pipelining processing of requests. Multiple HTTP requests and responses can be transmitted over a SINGLE TCP connection, reducing the consumption and latency of establishing and closing connections. Connection: keep-alive is enabled by default in HTTP1.1, to some extent compensating for HTTP1.0’s requirement to create a Connection on every request.

  2. Header compression, as mentioned above, uses encoder to reduce the size of the header that needs to be transmitted. Each side of the communication cache a header fields table. Not only avoids duplicate header transfers, but also reduces the size of transfers needed.

  3. With the new Binary Format, http1.x parsing is text-based. There are natural defects in format parsing based on text protocol. There are various forms of text, so there must be many scenarios to consider robustness. Unlike binary, only combinations of 0 and 1 are recognized. Based on this consideration of HTTP2.0 protocol resolution decided to use binary format, convenient and robust implementation.

  4. MultiPlexing, or connection sharing, means that each request is used as a connection sharing mechanism. A request corresponds to an ID. In this way, a connection can have multiple requests, and the requests of each connection can be randomly mixed together. The receiver can assign the request to different server requests according to the ID of the request.

What’s the difference between multiplexing in HTTP2.0 and long-link multiplexing in Http1.x?

HTTP/1.* A request-response, establish a connection, use up close; A connection is established for each request;

HTTP/1.1 Pipeling solution is a number of requests queued serialization of a single thread processing, the following request to wait for the return of the previous request to get the opportunity to execute, once there is a request timeout, the subsequent request can only be blocked, there is no way, also known as line blocking;

Multiple HTTP/2 requests can be concurrently executed on a single connection. If a request task is time-consuming, the normal execution of other connections will not be affected.

Ok, the next to start really into the cow force of things, you must have thought I was a water force, copy paste.

GRPC( A high-performance, open-source universal RPC framework)

I don’t know if you have heard of a city weird talk, byte network library optimization is more powerful more powerful, the network base using Webview underlying Chromium network library, in the case of weak network for API optimization what, bara bara…..

Cronet is the encapsulation of Chromium network engine for different operating systems, which implements protocols of mobile application layer, presentation layer and session layer, and supports protocol standards such as HTTP1/2, SPDY, QUIC, WebSocket, FTP, DNS and TLS. Supports Android, IOS, Chrome OS, Fuchsia, and some Linux, MacOS, and Windows desktop operating systems. Brotli data compression, pre-connection, DNS cache, session reuse and other policy optimization and TCP Fast open system optimization are implemented. This article is based on the Chromium 75 version.

Byte uses Chrome’s Cronet network library (by the way, cronet supports both ios, Android, and the front end). Because of the GRPC protocol, protobuf format is used to transmit the content directly, so it is not only optimized at the network layer, but also reduced serializable time because the stream can be converted directly to entity classes.

Protocol Buffers is a language-independent, platform-independent, extensible method of serializing structured data for use with communication protocols, data stores, and so on.

Protocol Buffers is a flexible, efficient, automated method of serializing structured data – comparable to XML, but smaller (3 to 10 times), faster (20 to 100 times) and simpler than XML.

You can define the structure of the data and then use specially generated source code to easily write and read the structure in various data streams in various languages. You can even update data structures without breaking deployed programs compiled from older data structures.

But normal network frameworks use Retrofit+Okhttp, and everyone is used to it, so I’m going to go out of my way to guess that byte actually Bridges cronet with Okhttp. So this is basically a seamless bridge to existing network libraries.

Upgrade QUIC from GRRC

QUIC (Quick UDP Internet Connection) is a low-latency Internet transport layer protocol based on UDP developed by Google. In November 2016, the International Internet Engineering Task Force (IETF) held the first QUIC working group meeting, which received extensive attention from the industry. This also means that QUIC has begun its standardization process to become the next generation transport layer protocol

The entire QUIC protocol (Http3.0 protocol) was written by Google, so it’s only natural that Google’s Cronet itself supports this. I actually checked the protocol supported by OKHttp before, and it is still only in the 2.0 phase, mainly because the current Connection is too well written, and Tcp needs to be directly replaced with Udp, so the 3.0 protocol support has not been updated.

So if you want to do the corresponding optimization from the protocol layer, then OkHttp should bring you endless wait.

What else can I do?

That’s about all I can think of in terms of optimization, but let’s think about revisiting the topic from a monitoring perspective. There is a complex link between the client request originating and the gateway receiving it. Simply put, there are so many interceptors passing through OKhttp. But when an online user gives feedback about how the interface is being generated so slowly, and we start using the back-end gateway as the starting point for requests, it becomes difficult to locate the real problem.

Network monitoring based on OkHttp

Can we consider monitoring the entire API from start to finish, so that we can easily monitor the actual status of an API from start to finish? Let’s simply split the nodes of a request. I’m gonna steal it.

OkHttp3: Events

With the EventListener provided by OKHttp, we can monitor a request to the last node, and then report the log data, so that we can actually have a reason to say something during the subsequent quarrel, you are really slow.

conclusion

This article is basically for your interview, but it’s also a simple summary of my Android network optimization. In fact, there are some contents that can be expanded in the middle, which need you to touch, and finally put a piece of Mr. Ma’s town building.