前语

成为一名优异的Android开发,需求一份齐备的常识系统,在这儿,让咱们一同生长为自己所想的那样~。

本文思想导图

欢迎来到 《深化探究 Android 网络优化(三、% y M $ X U网络优化篇)下》~

五、网络恳求质量优化()

1、Http 恳求进程

  • 1)、恳求到达运营商的 DNS 服务器并* 解析* 成对应的 I( , bP 地址。

    • HTTPDNS
  • 2)、根据 IP 地址找到相应的服务器,进行 TCP 三次握手,创立衔接

    • 衔接复用
    • 网络库的衔接办理
  • 3)、发送/接纳数据。

    • 紧缩
    • 加密
  • 4)、封闭衔接。

2、HTTPDNS

问题:DNS 解析慢/被绑架?

运用 HTTPDSN,HTTPDNS 不是运用 DNS 协议,向 DNS 服务器传统的 53 端口发送恳求,而是运用 HTTP 协议向 DSN 服务器的 80 端口发送恳求。

1)、HTTPDNS 优势

  • 1、绕过运营商域名解析的进程,防止 Local DNS4 w J ~ @ * d D ] 的绑架。
  • 2、下降平均拜访时延,供给衔接成功率。
  • 3、HTTPDNi w 3 6 3 h ?S 服务器会添加流量调度、网络拨测/灰度、网络容灾等功能。

2)、HTTPDNS + OKHttp 实践

在 Awesome-WanAndroid 中现已完成了 HTTPDNS 优化,其优化代码如下所示:

// HttpModule-pro s v G O ^ ivideClient:httpDns 优化
builder.dns(OkHttpDns.getInf : is(WanAndroidApp.getAppCo6 A 5 7 ? .mponent! e v u().getContext()));

/**
 * FileName: OkHttpDNS
 * Date: 2020/5/8 16:08
 * Descriptg N ? X y d 7 kion: HttpDns 优化
 * @author JsonChao
 */
pc z p 8 Z Aublic class OkHttpDns implemend L `ts Dns {

    privL % r 0 V 6ate H$ { @ cttpDnsService dnsService;% Y = B 9 ! Y [ Z
    private static OkHttpDns instance = null;

    private OkHttpDns(Context context) {
        dnsService = HttpDns.getService(8 l D 2 _ U Zcontext, "161133");
        // 1、设置预解析的 IP 运用 Https 恳求。
        dnsService.F w 6 H & U +setHTTPSRequestEnabled(true);( . Y R `
        // 2、预先注册要运用到的域名,以便 SDK 提前解析,削减后续解析域名时恳求的时延。
        ArrayList<String> hostLM - 6ist = new ArrayList<>(Arrays.asList("www.wanandroid.com"));
        dnsService.setPreResolveHosts(hostList);
    }

    public static OkHttpDns getIns(Context context) {
        if (instance == null)( 8 Y . y {
            synchronized (OkHttpDU p 8 @ V W 2 vns.class) {
                if (instance == null)p j V {
                    instance = new OkHttpDns(context);
                }
            }
        }
        returJ 1 f _ m hn instance. W n f W D D D ;
    }

    @@ E U 1 h 7 kOverride
    public List<InetAddress> lookup(StringL W p s * * $ hostna! 7 k j . [ i eme) throws UnknownHostException {
        StrI m Z | N Ding ip = dnsServV 7 q X f . E R qice.getIpByHostAsync(hostname);
        LogHelper.i("httpD( q U V 7 Ons: " + ip);
        if(ip !r { 5 c q k= null){
            List<InetAddresU 1 #s> inetAddresses = Arrays.asList(InetAddress.getAllByName(ip));
            return inetAddresses;
        }
        // 3、假如从阿里云 DNS 服务器获取不到 ip 地址,则走运营商域名解析的进程。
        return Dns.SYSTEM.lookup(hostname);
    }
}

重新安装 App,经过 HTTPDNS 获取到 IP 地址 log 如下所示:

2020-05-11 10:41:55.139 4036-4184/json.chao.com.wanandroid I/WanAndroJ N / D Cid-LOG: │ [OkHttpDns.java | 52 | lookup] httpDns: 47.104.74.169
2020-05-11 10:41:55.142 4036-4185/json.chao.com.wanandroid I/Wang # ^ ( f N c )Android-LOG: │ [OkHttpDns.java | 52c + s X | lookup] httpDns: 47.104.74.169

3、网络库的衔接办理

利用 HTTP 协议的 keep-alive,树立衔接后,会先将衔接放入衔接池中,假如有另一个恳求的域名和端口是相同的,就直接运用衔接池中对应的衔接发送和接纳数据。在完成网络库的衔接办理时需求留意以下4点:

  • 1)、同一个衔接仅支撑同) | ^ } / , 9 U一个域名。
  • 2)、后端支撑 HTTP 2.0 需求改造,这儿能够经过在网络渠道的一同接入层将数据转换到 HTTP 1.1 后再转发到对应域名的服务器即可。
  • 3)、当一切恳求都集中在一条衔接中时,在网络拥塞q h q B `时简略呈现 TCP 队首堵塞问题。
  • 4)、在文件下载、视频播映等场景下或许会遇到三方服务器单衔接限速的问题,此时能够禁用 HTTP 2.0。

4、协议版别晋级

HTTP 1.0

TCP 衔接不复用M M _,也便是每主张一个网络恳求都要重新树立衔接,而刚开端衔接都会阅历一个慢启动的进程,可谓是慢上加慢,因而 HTTL 6 ; 7 ! O QP 1.0 功能十分差。

HTTP 1.1

引进了持久衔接,即 TCP 衔接能够复用,但数据通讯有必要按次第来,也便是后面的恳求有必要等前面的恳求完成才能进行。当一切恳求都集中在一条衔接中时,在网络拥塞时简略呈现 TCP 队首堵塞问题。

HTTP 2

  • 二进制协议
  • 多工
  • 服务端与客户端能h J y } 0 w | y够双向实时通讯。

Q; U b C D m eUIC

Google 2013 完成,2018 根据 QUIC 协议的 HTTP 被承以为 HTTP3。

QUIC 简略理解为 HTTP/2.0 + TLS 1% . s.3 +C , * s ] k 4 – UDP。弱网环境下表现好与 TCP。

优势

  • 1)、处理了在衔接复用中 HTTP2 + TCP 存在的队首堵塞问题,
  • 2)、由所以根据 UDP,所以能够灵活操控拥塞协议。例如 Client 端能够直接运用 Google 的 BBR 算法。
  • 3)、衔接迁:因为 UDP 经过相似connection id 的特性,使得客户端网络切换的时分不需求重连,用f f j 9户运用 App 的体会会愈加流畅。

目前的缺陷

  • 1)、NAT 局域网路由、沟通机、防火墙等会禁止 UDP 443 通N { J n , B = D Z行,因而 QUIC 创立衔接成功率只要95%。
  • 2)、运营商针对 UDP 通道不支j z 8撑/支撑缺乏。
  • 3)、运用 UDP 不必定会比 TCP 更快,客户端可一同运用 TCP 和 QUIC 竞速,从而挑选更优链路。

运用场景

  • 1)、实时性
  • 2)、可丢弃
  • 3)) n i、恳求相互依靠
  • 4)、可一同运用 TCP & QUIC

QUIC 加密协议原理

  • 1)、当 Client 与 Server 第一次通讯时,会发送 Inchoate Client Hello 音讯下载 Servel y sr Config(SCFG) 暂存音讯。
  • 2)、SCm e A 8 Z xFG 中包括一个 Diffie-Hellman 同4 ~ f e 2 m f享,下一次 Client 将运用它派生初^ M .始密钥(即 0-RTT 密钥)并利用其加密数据给 Serv5 , + { s – , oer。
  • 3)、之后,Server 将宣布一个新的暂存 Diffie-Hellme { # I V Man 同享,并由此派生出F q E K 1 K y一组 前向安全密钥去进行数据的加密通讯。

5、网络恳求质量监控

1)、接口恳求耗时、成功率、过错码

在 Awesome-WanAndroid 中现已| ~ M运用 OkHttpEventListener 完成了网络恳求的质量监控,其代码如下所示:

// 网络恳求质量监控
builder.eventListenerFactory(OkHttpEventListener.FACTORY);

/**
 * FileName: OkHttpEventListener
 * Date: 2020/5/8[ l ) O n ! l O 4 16:28
 * Description: OkHttL ^ K | vpX - i E 7 B A G 网络恳求质量监控
 * @k $ J X N 5 h Q hauthor quchao
 */
publik $ c * 3c class OkHttpEventListener extends EventListener {

    public static final Factory FACTORY = new Factory() {; q ( / M 1
        @Override
        public EventListener create(Call call) {
            return new OkHttpEventListener();
        }
    };

    OL P E /kHttpEvent okHttpEvent;
    public OkHttpEventListener() {
        super();
        okHttpEvent = new OkHttpEvent();
    }

    @Override
    public void callStart(Call call) {
        super.callStart(call);
        LogHelper.i("okHttp Call Start"{ ( f O P V);
        okHttpEvent.callStartTime = SystD 3 |em.currentTimeMillis();
    }

    /**
     * DNS 解析开端
     *
     * @param call
     * @param domainName
     */
    @Override
    public void dnsStart(Call call, Strin+ ] % Lg domainName) {
        super.dnsStart(call, domainName);
        okHttpEvent.dnsStartTime = System.currentTimeMil} S + 4 I Blis();
    }

    /**
     * DNS 解析完毕
     *
     * @param call
     * @param domainName
     * @param inetAddressLis- F `t
     */
    @Override
    public void dnsEnd(Call call, String domainName, List<InetAddress> inetAddressList) {
        super.dng ]  t b j _sEnd(call, domainName, inetAddressList);
        okHttpEvent.dnsEndTime = System.currentTimeMild k v ` B * 0lis();
    }

    @Override
    public vox L t o Q 1 : ^ Eid connectStart(Call calI g } pl, InetSocketAddress inetSocketAddress, Proxy proxy) {
        s| N / [ r i h 9uper.connectStart(call, ine7 9 ? &tSocketAddress, p & % E 6roxy);
        okHttpEvent.connectStartTime = System.currentTimeMi^ ) #llis();
    }

    @Override
    puP O g K % r Gblf | W Mic void secureConnectStart(Call call) {
        super.secureConn- X $ c 9 KectStart(call);
        okHttpEvent.secureConnectStart; A ] N = System.{ g BcurrentTimeMillis();s & } 2 ( L d |
    }

    @Overri/ r T d `de
    public void secureConni K * $ q [ectEnd(Call call, @Nullable Handshake handshake) {
        super.securex Y # ConnectEnd(call, hanb B [ ) 2 Jdshake);
        okHttpEvent.secureConnectEn0 N { # q f td = System.currentTimeMillis();
    }

    @Override
    public void connectEnd(Call call, InetSocketAddress inetSo/ Q A ] @ 7cketAddress, Proxy proxy, @Nullable PrP F 5 Fot) D rocol protocol) {
        super.connectEnd(call, inetSocketAddrX q ! 6 2 m 0 u Zess, proxy, protocol);
        okHttpEvent.connectEndTime = System.currentTimeMillis();
    }

    @OverF e t cride
    public void connectFailed(Call call, InetSocketAddress inetSocketAddress, Proxy proxy, @Nullable PI I 0 o @rotocol protocol, IOException ioe) {
        supeN r 3r.cp ^ % 9 - T X AonnectFailed(cF 5 w y gall, inetSocketAddress, proxz h / S P C S py, protocol, ioe);
    }

    @Override
    public void connectionl w  F ! 3 ~ QAcquired(CU / S h Z ( ~all call, Connection connection) {
        super.connectionAcquired{ H _ u z h :(call, conne7 m ` S Z L  U Dction);
    }

    @Override
    public void conq ` t . P ` $ a 5nectionReleased(Call call, Connection connection) {
        super.connectionReleased(call, connection);
    }

    @Override
    public void requestHE N f 7 A @ J - !eadersStart(Call call); L r 4 x Q B 0 {
        super.requestHeadersStart(call);
    }

    @Override
    public voi= ] j | , , /d requev d s bstHeadersEnd(Cg D p e r : Oall call, Request request) {
        super.requestHeadersEnd(call, reqG ? {uest);
    }

    @Overrid& S Z k F We
    public void requestBodyStart(Call call) {
        super.requestBodyStart(call);
    }

    @Override
    public void requestBodyEnd(Call call, long byteCount) {
        super.requestBodyEnd(call, byteCount);
    }

    @Override
    public void responseHeadersStart(Call call) {
        super.responseHeadersStart(call);
    }

    @Override
    publ% X ` n (ic void responseHeadersEnd(Call call, Response response) {
        supera y o K.responseHeadersEnd(call, response);
    }

    @Override
    public void responseBodyStart(Call call) {
        super.responseBodyStart(call);
    }

    @Override
    public void responseBodyEnd(Call call, long byteCount) {
        super.responseBodyEnd(call, byteCount);
        //L z m b - 1 * } Y 记载呼应体的巨细
        okHttpEvent.responseBodySize = byteCount;
    }

    @Override
    public void callEnd(Call call) {
        super.callEnd(call);
        okHttpEvent.callEndTime = System.currentTimeMillis();
        // 记载 API 恳求成功
        okHttpEvent.apiSucces| - 0 F s = true;
        LogHelper.i(okHttpES j ` [vent.toString());
    }

    @Override
    public void callFailed(Call call, IOException ioe) {
        LogHelper.i("caV l x ; : D u lllFailed ");
        super.callFailed(call, ioe);
        // 记载 API 恳求失利及原因
        okHttpEvent.s Y [ GapiSuccess = false;
        okHttpEvent.errorReason = Log.getSt_ * BackTraceString(ioe);
        LogHelper.i("reason " + okHttpEvent.errorReason);
        LogHelper.i(okHtt5 t @pEvent.toString());
    }
}

成功 log 如下所示:

2020-05-11 11:00:42.678 6682-6847/json.chao.com.wanandroid D/OkHttp: --> GER $ NT https://www.wanandroid.com/banner/json
2020-05-11 11:00:42.687 6682-6848/json.chao.com.wanandroi. 7 1 ^ }d I/WanAndroid-LOO % Y ! I ^ 8 SG:I s V ┌────` ~ 1 n r p u───────────────────────────────────────────────────────────. 6 @ ` $─────────────────────────────────────────────────
2020-05-11 11:00:42.6, : e88 6682-6848/json.chao.com.wanandroid I/Wana k y  ? o QAndroid-LOG: │ Thread: RxCachedThreadScheduler-3
2020-05-11 11:00:42.688 6682-6848/json.chao.com.wanandroid I/WanAndrI  r Uoid-LOG: ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄+ x - A * 2 + W W
2020-05-11 11:00:42.688 6682-6848/json.chao.com.wanandroid I/WanAndroid-LOG: │ OkHttpEventListener.call, Q lStart  (OkHttpEventListener.java:46)
2020-05-11 11:00:42.688c | % ~ P - 6682-6848/json.chao / Ko.com.wanandroid I/Wp P !anAndroid-LOG: │    LogHelper.i  (LogHelper.java:37)
2020-05-11 11:00:42.688 6682-6848/json.chao.com.wanandroid I/WanAndroid-LOG: ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄P T @ w r x y┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄Z { * c ? n h M y┄┄┄
2020-05-1B p c  `1 11:00:42.688 6682-6848/json.chao.com.wV 7 Aanandroid I/WanAndroid-LOG: │ [OkHttpEventListener.jav K Ta | 46 | callStart] okHttp Call Start
2020-05-11 11:00:42.688 6682-6848/json.chao.com.wanandroid I/WanA/ _ r G c 1ndroid-LOG: └─────────────────────────────────────────────────────────────────────────────────────Q 6 C F R  i R ───────────────────────────
2020-05-11 11:00:43.4; r # - A85 6682-6847/json.cP X * k 6 ,hao.com.wanandroid D/OkHttk $ d x ; Xp: <-- 200 OK https://www.wanandroid.com/banner/json (806ms, unknown-length body)
2020-05-11 11:00:43.496 6682-6847/json.chao.com.wanandroid I/WanAndroid-LOG: ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────H r I y} f T──
2020-05-11 11:00:43.498 6682-6847/json.chao.com.wanandroid I/WanAndroid-LOG: │ Thread: RxCachedThreadScheduler-2
2020-05-11 11:00:43.498 6682-684} c N Z r M R U l7/json.chao.com.wanandroid I/c Y . U j %WanAndroid-LOG: ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄_ n Q e [┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
2020-05-11 11:00:43.498 6682-6847/json.chao.co~ P N . ^ o z S Dm.wanandroid I/WanA6 @ S -ndroid-LOG: │ OkHttpEventListener.callEk c + g 8 8 ind  (OkHttpEventListener.java:162)
2020-05-11 11:00:43z f E = [ C %.498 6682-68n ) z B X ^ } Z47/json.chao.com.wanandroid I/WanAndroid-LOG: │    LogHelper.i  (LogHelper.java:37)
2020-05-z _ S 2 )11 11:B 7 1 8 (00:q E f 43.498 6682-6847/json.chao.com.wanandroid I/WanAndroid-LOG: ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
202F @ H g ] l P0-05-11w x ) R 11:00:43.498 6682-6847/json.chao.c3 L w V ^ ^ 3om.wanandroid I/WanAndI | R W X ! g & .roid-LOG: │ [OkHttpEventListenerd T a E x 7 D.java | 162 | callEnd6  t] NetData: [
2020-05-11 11:00:43.498 6682-6847/json.chao.com.wanandr+ P / y : a # C *oid I/WanAndroid-LOG: │ callTime: 817
2020-05-11 11O ; G } t g ^ 7 t:00:43.498 6682-6847/json.chao.com.wanandroid I/Wav W hnAndroid-LOG: │ d3 i 9 v B J ansPF E % U v qarseTime: 6
2020-05-11 11:00:43.498 6682-6847/json.chao.comY ? M j.wanandroid I/WanAndroid-LOG: │ connectTZ d % y 5ime: 721
2020-05-11 11:00:43.499 6682-6847/json.chao.com.wanandroid I/WanAndroid-LOG: │ sC c S 7 m z J v 8ecureConnectTime: 269
2020-05-11 11:00:43.499 6682-6847/json.chao.com.wanandroid I/WanAndroid-LOG: │ response6 [ b Y  ( S 6BodySize: 975
2020-05-11 11:00:43.499 668_ m G q T j /2-6847/json.chao.com.wL s nanandroid I/WanAndroid-LOG: │ apiSuccess: true
2020-05-11 11:00:43.499 6682-6847/jU E y xson.chao.com.wanandroid I/WanAndroid-LOG: │ ]
2020-05-1A q M 4 O ; h1 11* u I ( & z H e D:00:43.499 62 H 9682-6847/json.chao.com.wanandroid I/WanAndroid-c f C P x l LOG: └F V * c─────! j y─────────────────────────────────────h K # H──────────────────────────────────────# ! G───────────────────────Q H  T W %─────────

2)、根据网络质量来动态设定网络服务的重要参数(超时、并发线程数)

  • 根据用户 2G/3G/4G/WIFI 的网络环境。
  • 根据用户当时网络的 RTT。

6、紧缩

1)、header(HTTP 2.0 头部紧N l Q ~ / = D &缩)

见 深化探究 Android 网络优化(二、网络优化根底篇)下 – 首部紧缩。

2)、URL

不变参数客户端只需上传以此,其它参数均在接入层进行扩展。

3)、body

运用 Protocol Buffers 替代 JSON 序列化

4)、图片

  • 1)、webp
  • 2)、hevc
  • 3)、SharpP
  • 4)、根据 AI 的图片超清化

    • 深度学习 CNN(Convolutional Nt + % B ( 7 reW : I _ G Sural Network,卷积神经网络)。
    • CNN 学习到的是高分辨率图画和低分辨率图画的差。

5)、紧G t ,缩算法

  • 1)、GZIP
  • 2)、Google Brotli
  • 3)、Facebook Z-standard(引荐):经过事务数据样本训练处合适的字典,因而是紧缩率最好的算法,因为各事务线维护字典本钱较大,能够在网络渠道的一同接入层进行紧缩与解压。咱们能够抽样1%的数据来训练字典,而字典的下发与更新由一同接s ) , 1 z Q B l入层C M U y担任。

7、加密

HTTPS 通常需求多耗[ { f ` @费 2 RTT 的洽谈时延。9 1 ; a

1)、HTTPS 优化

1、进步衔接复用率

  • 1)、多个域名共用同一个 HTTP2 衔i N v e j A J接。
  • 2)、长衔接。

2、削减握5 2 ; r ` ; P手次数(TLS 1.3 完成 0 Rr n G ] J m d [ iTT 洽谈)

TLS 1.t z K [ B K _ #2 引进了 SHA-256 哈希算法,摒弃了 SHA-1,对增强数据完好性有着明显优势。

I8 # 0 z QETF(Internet Engineering Task Froce,互联网工程使命组)拟定的 TLS 1.3 是有史以来最安全、杂乱* I p j g Q的 TLS 协议。它具有如下特色:

1)、更T 0 ~ + @ d A w l快的拜访速度

u g y较于 TLS 1.2 及之前的版别,TLS 1.3 的握手不再支撑静态的 RSA 密钥沟通,运用的是带有R t I u q前向安全的 Diffie-Hellman 进行全面握手。因而 TLS 1.3 只需 1-RTT 握手时刻。

2)、更强的安全性

删除了之前版别的不安全a Y 6 ] E的加密算法。

  • 1)、RSA 密钥传输:不支撑前向安全性。
  • 2)、CBC 模式暗码:易受 BEAST 和 Lucky 13 进犯。
  • 3)、RC4 流暗码:在 HTTPS 中运用并不安全。
  • 4)、SHA-1 哈希函{ D : d Mx ? B Q Q:主张以 SHA-2 替代。
  • 5)、恣意 Diffie-Hellman 组:CVE6 g K ^ -2016-0701 漏洞
  • 6)、输出暗码:易受 FREAK 和 LogJam 进犯。

此外,咱们C o (能够在 Google 浏览器设置 TLS 1.@ d o [3。

3、slight-ssl

参阅 TLS 1.3 协议,兼W c J } Z并恳求,优化加密算法,运用 session-ticket 等战略,力求在安全和体会间找到一个平衡点。

在 TLS 中功n ` p . B : , $能开支最大的是 TLS 握手阶段的 RSA 加解密。在 slight-ssl 中又测验如下几种处理计划:

  • 1)、硬件加~ j ` * i ~ R快:T p c g B C S c运用独自的硬件加快卡处理 RSA 加解密。
  • 2)、ECDSA:ECSDSA 最底层的算法和本钱对功能的耗费远低于 RSA,相差5~6倍。
  • 3)、Session Ticket 机制:将 TLS 握手从 2RTT 下降为 1RTT。

4、微信 mmtls 原理

根据 TLS 1.3 草案规范而完成。

相似于 TLS 协议,mmtls 协议也是位于事务层与网络衔接层中心。

mmtls 协议组成图
  • 1)、Handshake、Alert 和 Applic6 B s g ) e |ation Protocol 都是 record 协议的上层协议。
  • 2)、Record 协议包中有字段用于区别Q s – . M p v J器上层协议是上述3种任一协议。
  • 3)、在 mmtls/TLS 中Handshake 子协议担任密钥洽} { ^ E – B f {谈, Record 子协议担任数据对称加密传输。J B j除了功能与功率的要素之外,更利于隔离杂乱性。
Handshake 协议

TLS 1.3 Handshake 协议有如下几类:

  • 1-RTT 密钥洽谈办法

    • 1n & . b-RTT ECDHE
    • 1-RTT PSK(Pre-Shared Key)
  • 0-RTT 密钥洽谈办法

    • 0-RTT PSK
    • 0-RTT ECDH
    • 0-RTT PSK-ECDHE
    • 0-RTT Ep z a 1 z Q 2 gCDH-ECDHE

而 mmtls Handshake 协议有如下几种:

  • 1-RTT ECDHE
  • 1-RTT PSK
  • 0-RTT PSK

1-RTT ECDHE 密a i N | m @ 5 p U钥洽谈原理

ECDH| _ 6 W _ S i 密钥沟通协议需求运用两个算法:

  • 1)、密钥; L c h生成算法 ECDH_GenerP b X ^ P : q Bate_Key:生成公私钥对(ECDH_pub_key、ECDH_pri_key),其间保存私钥,将公钥相互发送给u % q ] i z对方。
  • 2)、密钥洽谈算法 ECDH_compute_key:输入对方公钥与本身F = } @ D W u } 9私钥,核算出通讯两边一同的对称密钥 Key。

可是 1-RTT ECDHE 算法+ C V简略被中心人进犯,中心人能够截获两边的公钥运转 ECDH_Generate_key 生成自己的公. D + @私钥对,然后将公钥发送给某一方。

怎样处理中心人进犯?

中心人进犯发生的本质原因是没有经过端点认证,需求”带认证的y Q ^ j M } ) e密钥洽K W ;谈“。

数据认证的办法?

数据认证有对称与非对称两种办法:

  • 1)、根据 MAC(MessaK S U /ge AutR O N I g nhentication Code,音讯认证码)的对称认证
  • 2)、根据签名/ ` N $ ( & W c m算法的非对称认证。

ECDH 认证密钥洽谈便是 ECDH% o n b 密钥洽谈 + 数字签名算法 ECDSA。} a j J R P :

两边密钥洽谈会对本身宣布的公钥运用签名算法,因为签名算法中的公钥 ECD} L a q G ( 7 J uSA_verify_key 是公开的,中心人没有办法阻止别人获取公钥。

而 mmt? } :ls 仅对 Server 做认证,因为通讯一方签名其洽谈数据就不会被中心人进犯。

在 TLS 中,供给了可选的两边相互认证的才能:

  • Client 经过挑选 CipherSuite 是什么类型来决议是否要对 Server 进行认证。
  • Server 经过是否发送 Certiq m P ,ficateRequest 握手音讯来决议是否要对 Client 进行认证。

1-RTT PSK 密钥洽谈原理

在之前的 ECDH 握手下,Sh , m U _ . Yerver 会下发加密的 PSK{key, ticket{key}},其间:

  • key:用来做对称加密密钥的 key 明文。
  • ticket{key}:用 servo 6 ^er 私密保存的 ticket_key 对 key 进行加密的密文 ticket。

1)、首要,Client 将 ticket{C 0 ? ikey}、Cli| Z ? ! n 3 | rent_Random 发送给 Server。

2W J g)、然后,Server 运用 ticket_key 解密得到 key、Server_Random、Client_Random 核算 M9 % y lAC 来认证。y _ P B _

3)、最终,Server 将 Server_Random、MAC 发送给 Client,Client 同 Server 运用 ticket_key 解密得到 key、Server_Random、Client_Random 去核算 MAC 来验证是否与收到的 MAC 匹配。

0-q B Q e D 9RTT ECDHy { p } i 密钥洽谈原理

要想完成 0-RTT 密钥洽谈,就有必要在洽谈一开端就将事务数据安全地传递到对端。

预先生成一对公私钥(static_svr_pub_6 g c ] 9 ( &key, static_svr_pri_key),并将公钥预置在 Client,私钥持久保存在 Server。

1)、首要,Client 经过 stati$ 9 P c C $ f 6c_svr_pub_key 与 cli_pri_key 生成一个对称密钥SS(Statib H [ : 2 /c Secret),用 SS 衍生的密钥对事务数据加密。

2)、然后,Client
cli_pub_key、Client_Random、SS 加密的 AppData 发送给 Se. z W zrver,Sever 经过 cli_pub_key 和 static_svr_pri_k; i 1 q & rey 算出 SS,解密F @ 6 z @ @ M d事务数据包。

1-RTT PSK 密钥洽谈原理

在进行 1-RTz 1 6 ] ^ n O =T PSK 握手之前,CliY = p H h dent 现已有一个对称加密密钥 key 了,直接运用此 key 与 ticket{key}8 t Y e 一同传递给 Server 即可。

TLS 1.3 为什么要废除 RSA?

  • 1)、2015年发现了 FREAK 进犯,呈现了 RSA 漏洞。
  • 2)、一旦私钥走漏,中心人就能够经过私钥核算出之前一切报文的密钥,破解之前一切的密文。

因而 TLS 1.3 引进了 PFS(po l % ~erfect forward secrecy,前向安全性),即彻底向前保密,一个密钥被破解,并不会影响其它密钥的安全性。

例如 0-RTT ECDH5 s g 5 Y 3 8 密钥洽谈加密依靠了静态 static_svr_pri_key,不符合 PFS,咱们能够运用 0-RTT ECDH-ECDHE 密钥洽谈,即进行 0-RTT ECDH 洽谈的进程中也进行 ECDHE 洽谈。0-RTT PSK 密钥洽谈0 ~ C P 9 $的静态 ticket_key 同理也能够参加 ECDHE 洽谈。

verify_key 怎样下发给客户端?] 9 ,

为防止证书链验证带来的时刻耗费及传输带来的带宽耗费,直接将 verify_Key 内置d K K [ V V K H c客户端即可。

怎样防止签名密钥 sign_key 走漏带来的影响?

因为 mmtls 内置了 verify_key 在客户G t ; w端,必要时及时经过强制晋级客户端的办法来吊销公钥并更新。

为什么要在上述密钥洽谈进程中都要引进 client_random、server_random、sZ 6 ^vr_pub_key 一同做签名?

因为 svr_pri_Key 或许会走漏,一切G b P D s ` _独自运用 svr_pubt R v s O_key 时会有隐患,因为需求引进 client_random、server_random 来保证得到的签名值唯一对应一次握手。

Record 协议

1、认证加密

  • 1)、运用对称密钥进行安全通讯。
  • 2)、加密 + 音讯认证码:Encrypt-then-MAC
  • 3)、TLS 1.3 只运用 AEAD(Authenticated-En# b m A y I y , 6cryption With Addtiona+ V * y * ql data)类算法:Encrypt 与 MAC 都集成在一个算法内部,让有经历的暗码专家在算法内5 v h 2 0 ]部处理安全问题。
  • 4)、mmtls 运用 AES-GCM 这种 AEAD 类算法。

2、密钥扩展

两边运用相同的对称密钥进行加密通讯简略被某些对称密钥算法破解,R , m _ N } b因而,需求对原始对称密钥做扩展变换得到相应的对称加密参? v ) r s { c W Z数。

6 H H ~ [ Y f #钥变长需求运用密钥延时函数(KDF,Key Derivation Fu7 d ? 9 T ?nction),而 TLS 1.3 与 mmtls 都运用了O $ S A Z , Q 4 T HKDF 做密钥扩展。

3、防重放

为处理防重放,咱们能够为衔接上的每一个事务包都添加一个递加的序列号,只要 Server 检查到新收到的数据包的序列号小于等于之前收到的数据包的序列号,就判别为重放包,mmtls 将序列号作为结构 AD H & GES-GCM 算参数 nonce 的一部分,这样就不需求对序列号独自认证。

在 0-RTF ! O 9 3 F T 握手下,第一个事务数据包和握手数据包无法运用上述计划,此时需求客户端在事务框架层去协调支撑防r ) A C ] |重放。

小结

mmtls 的 作业进程 如下所示:

  • 1)、运用 ECDH 做密钥洽谈。
  • 2)、运用 ECDSA 进行签名认证。
  • 3)、运用 AES-GCM 对称加密a 7 d m算法对事务数据进O [ l行加密。
  • 4)、运用 HKDF 进行密钥扩展。
  • 5)、运用的摘要算法为 SHA256。

其优势具有如下4点:

  • 1)、轻量级:去除客户端认证,内置签名公钥,削减验证时网络沟. [ . * b H N M通次数。
  • 2)、安全性:TLS 1.3 引荐安全性最D } V k k w高的根底暗码组件,0-RTT 防重放由服务端、客户端框架层协同处理。
  • 3)、高功能:运用了 0-RTT 握手,优化了 TLS 1.3 中的握手办法和密钥扩展办法。
  • 4)、高可用:服务器添加了过载维护,确保其能在容灾模式下供给安全等级稍低的有损服务。

3)、复用 Session Ticket 会话,节约一个} ! N RTT 耗时。

最终,咱们能够在一同接入层对传输数据二次加密,需求留意二次加密会添加客户端与服务器的处理耗时。

假如手{ p I % # ? I 4 l机设置了代理,TLS 加密的数据能够被解开并被利用,怎样处理) t T H

能够在 客户端锁定根证书,能够一同兼容% R ]老版别与保证证书替换的灵活性。

8、网络容灾机制

  • 1)、备用服务器分流。a q { @ ` ~ |
  • 2)、多次失利后必定时刻内不进行恳求,防止雪崩效应。

9、资K S c本手法优化

  • 1)、CDN 加快,更新后需求记住清理缓存 9 n M B 2 r
  • 2)、进步带宽
  • 3)、动态资源分离
  • 4)、布置跨国的专线、加快点
  • 5)、多 IDC 就进接入
  • 6Q – k)、P2P 技能

六、网络库规划

1、一同的网络中台

在一线互联网公司,都会有一同的网络中台:

  • 担任供给前后台一整套的网络处理计划。
  • 网关用于处理中心网络的通讯,为上层服务供给高质量的双向通讯才能。

2、怎样规划一个优异的一同网络U x d库?

  • 1)、一同 API:一T n c K L 5 J 2同的战略办理、流解析(兼容J= m = P 3 / HSON、XML、Protoco4 E V n @ x o l Buffers)等
  • 2)、全 ; v * A { w局网络操控:一同的网络调度、H t c !流量监控、容灾办理等
  • 3)、高功能:速度、CPU、内存、I/O、失利率、崩溃率、协议兼容性等

3、一同网络库的中心模块有哪些?

  • 1)、DNS 办理
  • 2)、衔接办理
  • 3)、协议处理
  • 4)、并发模型
  • 5)、IO 模型
  • 6)、预衔接
  • 7)、c K T u Z [ S过错兼容处理
  • 8)、数据解析
  • 9)、网络质量监控
  • 10)流量监控
  • 11)、代理 WebView 网络恳求

4、高质量网络库

1)、Chromium 网络库

  • Google 出品,咱们能+ | T t够根据@ v : s w V Chromium 网络库二次开发自己的网络库,4 – d Y % 9 m 4 d 以便享受 Google 后续网络优化的成果,例如 TLw / j F S cS 1.3、QUIC 支撑等等。
  • 跨渠7 ; r O J道。
  • 需求补足 Mars 的 弱网/衔接优化 功能。
  • 自定义协议:改造 TLS,将 RSA 更换为 ECDHE,以进步加解密速度。

2)、微信 Mars

一个跨渠道的 Socket 层处理计划,不支撑完好的 HTTP 协议。

Mh l . n C – Gars 的两个中心模块如下:

  • SDT:网络诊断模块
  • STN:信令传输模块,合适小数据传输。

其间 STN 模块的组成图如下所示:

包包超时

  • 每次读取或发送的距离。
  • 获取 sock snd buf 内未发送的数据。
  • Android:ioctl 读取 SIOCOUTQ。
  • iOS:getsockopt 读取 SO_h n 3 { U B ^ } ANWRITE。

动态超时

根据网络状况,调整其它超时的系数或绝1 * # ! q 7 6对值。

Mars 是怎样进? y { T G i行 衔接优化 的?

y D E F – E 合衔接

每距离几秒启动一个新的衔接,只要有衔接树立成功,则封0 c ? U ! W闭其它衔接。=> 有用进步衔接成功率。

自动重连优化

  • 1)、削减a J ( O ) O n无效等候时刻,添加重试次数。
  • 2)、但 TCP 层的重传距离过大2 . m时,此时断连重连,能够让 TCP 层坚持积极的重连距离,以进步成功率。
  • 3)、当链路存在较大动摇或严重拥塞时,经过更换衔接以获得更好的功能。

网络切换

经过感知网络的状况切换到更好的网络环境下。

Mars 是怎样进行 弱网优化 的?

常规计划

1)、快速重传
  • 减小重传本钱(SACK、FEC)
  • 尽早发现重传(DUP ACK、FACK、RTO、NACK)
2)、HARQ(Hybrid Automatic Repeat reQuest)
  • 3 GPP 规范计划。
  • ] 9 B 8 w C加并发度。
  • 尽量精确防止拥堵(丢包和拥堵的区别)。

进阶计划

Tl X q ( ,CP 丢包的康复办法 Tp W C @ P D H aLP
  • 1、PTO 触发尾包重传。
  • 2、2 ) o尾包的 ACK 带上 SACK 信息。
  • 3、SACK 触发 FACK 快v Y +速重传和康复。
  • 4、防止了 RTO 导致的慢启动和推迟。
发图-有损下载

在弱网下尽量保证下载完好的图片概括显现,进e } 6 T 7 % t C 步用户体会。

发图-有损上传数据

  • 在弱网下尽量保证上传完好的图片概括显现,进步用& G [ 1 b H n ;户体会。
  • 能够下降客户端上传失利率 10% 以上。

有损上传数据的流程,有损下载流程同理

  • 1)d w D s V V、发送渐进式图片(例如 JPG 等)。
  • 2)、服务器接纳数据且回复数据承认包} # = D a @ = $
  • 3)、当数据满足时(50%),回复发送成功承认包。
  • 4)、发送方继续补充数据o u j

    • 网络正常,数据完好。
    • 网络反常,以为已发送成功。
  • 5)、服务器告诉发送者。

发图-4 ` m 5 | I T低本钱重传

将分包转成流式传输。

  • 1)、分包

    • 下降包巨细
    • 添加并发
    • 包头损耗
  • 2)、流式
    承认粒度战略灵活
    A t ~ T @ B – C线程

七、其它优化计划

1、异地多活

一个多机房的整体计划,在V ? = 5多个区域一同存在对等的M ( ~ D 7多个机房,以用户维度区别,多3 = 4 g _机房一同承担全量用户的流量。

在单个机房发送毛病时,毛病机房的流量能够快速地被迁引到可用机房,削减毛病的康复时刻。

2、抗颤动优化

运用一种有战略的重试机制,将网络恳求以是否发送] + Y T到 socket 缓冲H Z E区作为分割,将网络恳求生命周期区别为”恳求开端到发送到 socket 缓冲区“和”现已发送到 socket 缓冲区到r v b g C @ X j x恳求完毕“两个阶段s L d z – (

这样当用户进电梯因为网络颤动的原因网络链接断了,可是数据其完成已恳求到了 socket 缓冲区,运用这种有战略的重试机制,咱们就能够进步客户端的8 = 网络抗颤动才能。

3、SYNC 机制

同步差量数据,达到节约流量,进步通讯功率与恳求成功率。

客户端o & v + g 9 X用户不在线时,SYNC 服务端将差量数据坚持在数据库中。当客户端下次衔接到服务器时,再同步差量数据给用户。

4、高并发流量处理:服务端接入层多级限流

中心思想是保障中心事务在体会可承受范围内做降级非中心功能和事务。从入口到事务接口一共分为四个层级,如下所示:

  • 1)、LVS(几十亿级):多 VIP 多集群。
  • 2)、接入网关(亿级):TCP 限流、中心 RPC 限流。
  • 3)、API 网关(千万级):分级限流算法(对不同恳– T u求量的接口运用不同的战略)

    • W h ^ QPS 限流:简略基数算法,超越这个值直接回绝。
    • 中 QPSd : U S W 限流:令牌桶算法,承受必定的流量并发。
    • 低 QPSO s 4 Z V O 限流:分布式限流,保障限流的精确。7 M I + U
  • 4)、事务接口(n u v 8 F百万级)

    • 返回定制呼应、自定义脚本。
    • 客户端静默、Alert、Toast。

5、Jj T # M ) ^ 7obScheduler9 * M

结合 JobScheduler 来根据实际状况做网络恳求. 比方说 Splash 闪屏广告图片, 咱们能够在衔接到 Wifc y 0 T ` n } 0i 时下载缓存到本地; 新闻类的 App 能够在充电,O l A q L d | 6 u Wifi 状况下做离线1 A V E * n缓存。

6、网络恳求优先级排序

app应该对网络恳求区别优先级尽或许快地展现最有用的信息给用户。(高优先级的服务优先运用长衔接)

马上呈现给用户一些本质的信息是一个比较好的用户体会,相关于让用户等候那些不那么必z { 4 K P Z z @要的信息来说。这能够削减用户不得不等候的时刻,添加AP* 6 cP在慢速网络时的实用性。(低优先级运用短衔接)

7、树立长连通道

3 H C [成原理

将众多恳求放入等候发送行列中,待长连通道树立完毕后再将等候行列中的恳求放在长连通道上依次送出。

关键细节

HTTP 的恳求头键值对中的的键是答应相同和重复的。例如 Set-Cookie/Cookie 字段能够包括多组相同的键名9 T h ] 5 L 称数据。在长连通讯中,假如对 header 中的键值对用不加处理的字典办法保存和传输,就会形( D s k $成数据的丢掉。

8、削减域名和防止重定向。

9、没有恳求的恳求,才是最快的恳求。

七、网络系统– M Y化计划建造

1、线下测试

1)、正承认识

尽或许将问题在上线前暴露出来。

2)、侧重点

  • 1)、恳求有误、多余
  • 2)、网络切换
  • 3)、弱网
  • 4)、无网

2、线上监控

1)、服务端监控

宏观监控维度+ – m ! x 6 F 6

1)、恳求耗* _ a H ! V 7 l O

区别地域、时刻段、版别、机型。

2)、失利率

事务失利与恳求失利。

3)、Top 失利接口、反常接口

以便进行针对性地优化。

微观监控维度

1)、吞吐量(request5 J ? a &s per seco8 Y i y qnd)

RPS/TPS/QPS,每秒的恳求次数,服务器最基} m A v [ D K本的功能目标,RPS 越高就说明服务器的功能越好。

2)、并e : – $发数(concurrency)

反映服务O G } }器的负载才能,即服务器能够一同支撑的客户端数量,越大越好。

3)、呼应时刻(time per request)

反映服务器的处理才能,即快慢程度,呼应o s G时刻越短越好。

4)、操作系统资源

CPU、内存、硬盘和网卡等系统资源。能够利用 top、vmstat 等东西检测相关功能。

优化政策

  • 1)1 L r S、合理利用系统资源,进步服务器} b X的吞吐量和并发数,下降呼应时刻。
  • 2)、选用高功能的 Web 服务器L ( A ^ c [ o,开启长衔接,进步 T& i a b 9 I 2CP 的传输功率。

2! P w)、客户端监控

要完成客户端监控,首要咱们应该要一同网络库,而客户端需求监控的目标首要有如下三类:

  • 1)、时延:一般咱们比较关心每次恳求的 DNS 时刻Y X M $ 4 3 k、建连时刻、首包时刻、总时刻等,会有相似 1 秒快开率、2 秒快开率这些目标。
  • 2)、维度:网络类型、国家、省份、城市、运营商、系统、客户端版别、机$ 6 Q型、恳求域名等,这些维度首要用于剖析问题。
  • 3)、过错:DNS 失利、衔接失利、超时、返回过错码3 N l I 4 ; F p等,Y t * d u会有 DNS 失利率、衔接失利率、网U Z W络拜访的失利率这些目标。

为了运算简略咱们能够抛弃 UV,只核算每一分钟部分维度的 PV。

1、Aspect 插桩 — ArgusAPM

关于 ArgusAPM 的网络监控切面源码剖析能够参阅我之前写的 深化探究编译插桩技能(二、AspectJ) – 运用 AspectJ 打造自己的功能监控框架

缺陷

监控不全面,因为 App 或许不运用系统/OkHttp 网络库,或是直接运用 Nativ. B C e 网络恳求。

2、Native Hook

需求 Hook 的办法有三D 7 d , c V类:

  • 1)、衔接相关:connect
  • 2)、发送数据相关:send 和 sendto。
  • 3)、接纳数据相Y * + p v关:recv 和 recvfrom。

不同版别 Socket 的完成逻辑会有差异,为了兼容性考虑,咱们直接 PLT Hook 内存一切的 so,可是需求扫除去 Socket 函数本身地点的 libc.so。其 PLT 的 Hook 代码如下所示:

hook_plt_method_all_lib("libc.so", "connect", (hook_func) &create_hook);
hook_plt_me% k P 9thod_all_lib("libc. & 1 + K * r H |.so, "send", (hook_func) &a, ` # 2 nmp;send_hook);
hook_plt_method_all_lib("libc.so", "recvfrom"; u ~ A E b Z { $, (hook_func) &re4 7 R G ` Ocvfrom_hook);

下面,咱们运用 PLTQ ] u # 4 Hook 来获取网络恳求信息。

项目地址

其成功 log 如下所示:

2020-05-21 15:10:37.328 27507-27507/com.dodola.socket E/HOOOOOOOOK: JNI_OnLoadV l { k 1 $ V  o
2020-05-21 15:10:37.328 27507-27507/com.dodola.R 4 ;socket E/HOOOOn 1 H  ; m $ SOOOOK: enableSocketHook
2020-05-21 15:10:37.415 27507-27507/com.dodola.socket E/HOOOOOOOOK: ho: D ; ] 0 B U bok_plt_method
2020-05-21 15:10:58.484 27507-27677/com.dodola.socket E/HOOOOOOOOK: socket_con@ * m M r J ; S znect_hook sa_family: 10
2020-05-21 15:10:58.d I O 6 # g495 27507-276! ( d s ?77/com.dodola.sK ! bocket E/HOOOOOOOOK: stack:com.dodola.socket.SocketHook.getStack(SocketHook.java:13)
libcore.io.Linux.c) 5 2onnect(Native Method)
libcore.io.BlockGuardOs.connect(BlockGuardOs.javX ] C | x ^ -a:126)
libcore.io.IoBridge.connectErrno(Ie 0 | o $ 5oBridge.jB | ! ] J 2 Z Zava:152)
libB B Z Q |core.Y { ; bio.IoBridge.connect(IoBridge.java:130)
java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:129)
java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:356)
java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketO w b { vImpl.java:18q D { O x U / 8 2)
java.net.SocksSocketImpl.connect(SocksSocketI0 z % R ) Smpl.java:357)
java.net.Socket.connect(Socket.java:616)
com.a} 2 V q p * t % zndroid.okhtt# L T 4p.internal.Platform.connd : xectSocket(Platform.java:145)
com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:141)
com.android.okhttp.internal.io.RealConnection.8 o k | 5connect(RealConnection.java:112)
com.android.okhttp.internal.http.StreamAllocation.finJ V R k } P 9dConnection(StreamAllocatioo c 0 w 5 Vn.java:184)
com.android.okhttp.internal.http.Strea` m B ? 4 w
2020-05-21 15:10:58.495 27507-27677/com.dodola.socket E/HOOOOOOOOK: AF_INET6 ipv6 IP===>14.215.177.39:443
2020-05-21 15:10:58.495 275l ) g g p g07-27677/com.dodola.socket E/HOOOOOOOOK: socket_connect_hook sa_family: 1
2020-05-21 15:10:58.495 27507-27677/com.dodola.socket E/HOOOOOOOOK: Ignore local socket connect
2020-05-21 1R - E P 9 1 C X o5:10:58.523 27507-27677/com.dodola.socket E/HOOOOOOOOK: socket_connect_hook sa_family: 1
2020-05-21 15:10:58.523 27507-V } _ F [ f _ p2767B C 8 F z * n [7/com.dodola.socket E/HOOOOOOOOK: Ignore local socket connect
2020-05-21 15:10:58.806 27507-27677/com.B p o # [ T Edodola.socket E/HOOOOOOOOK: ret = _ B O ; S vspond:<!DOCTYPE html>
<!--STATUS OK--><hy & S 7tml> <head><meta http-equiv=content-type content=text/html;c[ ` } uharset=utf-8><meta http-equiv=X-UA-CompatibleX N o d ) D 7 v _ cont_ o _ ^ent=IE=Edge><{ + &;meta content=always name=referrer><link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3Ka z |/r/www/cache/bdorzl 3 [ ?/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc&~ n S o 5 P ) O ?gt; <* K I P Q W  odiv id=wrapp_ { 8 = 4 ^er> <div id=head> <div class=h: G L read_wrapper> <div class=s_form> <div class=s_form_wrapper> <v q % Z Gdiv id=a z H c & w ( Alr D h 5 v .g> &le o 1t;img hidefocus=true src=//www.baidu.com/ic &   ! n Xmg/bd_+ N n % . y ` logo1.png width=270 heiga & Z - ) ht=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <a q } 3 V p Sinput type=hidden name=f value=8> <input type=hidden naI ; Q s Q Eme=rsv_bp value=1s E + : M ! n p> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input ir ~ E Bd=kw name=wd class=s_ipt value maxlength=255 a3 u ; 8  z s ) 9utocomp1 J 1 m {letY } ze=off autofocus=aua A e n ) :tofocus></span><span class="bg s_btn_wr"><input t- v r | 9 iype=submit id=sX O * W [ o `u value=百度一下 class="bg s_btn" autofocus></span> <e ` ? */form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=https://www.hao123.com name=l s Ltj_trhao123 class=mnav>h; A ] Z : oao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图<H } / % q m #/a> <a href=http://v.baidu.com name=tj_trvideo clad . E 8ss=mnav>视频</a> &_ { 5 I z W 5 5lt;a href=http://tieba.baidu.com name=tj_trtiebL 4 H W la class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.e ) 9 q ! ] hgif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d7 f 7 R1 name=tj_login cl: J N -ass=lb>登录</a> &S I p A jlt;/noscript> <N } E c U D /script>document.write('<a hr0 ~ v  6 w 6 e{ H ; a 5 j E . yf=1 / a n ; k d a j"http://www.baidu.com/bd| K # 2 ? X [ y }orz/login.gif?login&tpl=mn&aQ ( O y : T % ~ Hmp;u='+ encodeURIComponent(Z A W *window.location.href+ (window.locV y z G Z 5 Cation.search === "" ? "?" :l N N b K k G x "&")+ "bdorz_come=1")+ '" nb , j b C K iame="tj_login" clasb 7 : S D & -s="lb">登录&le C K Mt;/a>');
<d 8 P 4 @ P 0 R;/script> <a href=//www.bQ B N qaidu.com/more/ name=tj_briicon class=bri>更多产品</a> </div>D @ g `; </div> </div> i . q; <div id=ft| % - ? 9 ^Con> <div id=ftConw> <p id=lh&gP  R ( 0t; <a href=http:/0 X % ? Q & k 1/home.baidu.com>关于百度</a> <a href! ~ w=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>2017 Baidu <a href=http://ww_ + [ L R 6 )w.baidu.com/duty/>运用百度前必读</a>  <a href=http[ S 6 t A Q://jianyi.baidu.com/ class=cp-feedback>定见反应<[ 2 i { # 1 8 %/; { ` =a>~ Y 2 c G 3 京ICP证030173号  <img src=//www.baidu.com/img: @ R y ~ =/gs.go k i } n , 1if> </p> </div> </diH A C Z G c v 8v> </div> </body> </html>

此外,咱们也能够运用爱奇艺供给的 android_plt_hook 来完成 PLT Hook。

缺陷

接管了系统的 Local Socket,需求在代码中添加过滤条件。

3)、接入层监控

为什么要做接入层监控?

  • 1)、服务端更简略做到秒级的实时上报 z = N
  • 2)、仅靠客户端的监控数据g n ? 5 o并不彻底牢靠。

监控维度

服务的入口和出口流量、服务端的处理时延、过错率等。

4)、监控报警

  • 1)、秒级或许分钟等级的实时监控只要拜访量(PV)、过错率等几个维度:最快速度发现问题。
  • 2)、小时或许天等级的监控能够监控8 i f }全部的维v h V : d度:更好地定位出问题的区域。

监控的一同怎样完成精确的自动化报警呢?

  • 1)、根据规: 5 ~ Q P U则,例如失利率与历史数据比较暴涨、流量暴跌等。
  • 2)、根据时刻序列算法或许神经网络的智能化报警,运用者不需求录入任何规则,只需有满足长的历史数据,就能够完成自动报警。

通常是两种结合运用。

3、反常监控系统搭建

1)、服务器防刷

超限回绝拜访。

2)、% H S $客户端

  • 1)、大文件预警
  • 2)、反常兜底战略:例如客户端超越5次衔接失利,则设置更长的重试时刻。

3)、单点问题清查& 2 ! F [ m t L 2

假如用户反应 App 耗费的流量过多,或后台耗费流量较多,` g D – t H咱们都能够详细地剖析网络# O 0 + $恳求日志、以及下发指令检查详细时刻段的流量、客户端线上监控 + 系q 0 M N统化计划建造 来完成单点问题的清查。

八、网络优化常见问题

1、在网络方面你们做了哪些监控,树立了哪些目标?

留意:表现演进的进程。

网络优化及监控咱们刚开端并没有去做,因而咱们在 APP 的初期并没有留意到网络的问题,并且咱们通常e M M N / – p k 是在 WIFI 场景下进行开发,所以并没有留意到网络方面的问题。

当 APP 增大后,用户增多,逐1 1 D U s } g步由用户反应 界面打不开或界面显现慢,也有用户反应咱们 APP 耗费的流量比较多。在咱们承受到这些反应的时分,咱们没有数据支撑,无法判别用户反应是不是正% u C ^ D ;确的。一同,咱们也不知道线上用户实在的$ @ G体会是怎样的。所以,咱们就 树立了线上的网络监控,首要分为 质量监控与流量监控

1)、质量监控

首要,最重要的是接口的恳求成功率与每步的耗时,比方 DNS 的解析时刻、树立衔接的时刻、接口失利的原因,然后在合适的时刻点上报给服务器。

2)、流量监控

首要,咱们获取到了精准的流量耗费状况,并且在 APM 后台,能够下发指令获取用户在详细时刻段的流量耗费状况。 => 引出亮点 => 前后台流量获取计划。
关于目标 => 网络监控。

2、怎样有用地下降用户的流量耗费?

留意:结合实际事例

1)、数据:缓存、增量更新(这一步削减了十V ; Y分多的流量耗费)

首要,咱们处理了项目当中展现数据相关的接口,一同,对时效性没那么强的接口做了数据的缓存,也便是一段时刻内的重复恳求直接走缓存,而不走网络恳求,从而防止流量糟蹋。关于一些数据的更新,例如省市区域、配置信息、离e b { c 2 r线包等信息,咱们 加上版别号的概念,以完成每次更新只传递变化的数据,即完成了增量更新 => 亮点:离线包增量p b 2 Z 7更新完成原理与关键细节。

2)、上传:紧缩

然后,咱们在上传流量这方面也做了处理,z e p A A G ] 7 J比方针对 POST 恳求,咱们对 Body 做了 GZip 紧缩,而关于图片的发送,有必要要经过紧缩,它能够在保证清晰度的前提下极大地削减其体积。

3)、图片:缩略图、web= F _ A ( K K B Qp

关于图片展现,咱们采用了不同场景展现不同图片的战略,比方在列表展现界面,咱们只展现了缩略图,而到用户显现m X z大图的时分,咱们才去展现原图。 => 引出 webp 的运用战略。

3、用户反应耗费流量多这种问题怎样排查?2 5 .

首要,部分用户遇到流量耗费多的状况是肯定会存在的,因为线上用户十分多,每个人遇到的状况肯定是不相同的,比方有些用户他的操作路径比较怪异,或许会引发一些反常状况,因而有些用户或许会耗费比较多的流量。

1)、精准获取流量的才能

咱们在客户端能够精确q地获取到流量的耗费,这样就给咱们排查用户的流量耗费供给了根据,咱们就知道用户的流量耗费是不是很多。

2)、一切恳/ – r 求巨细及次数2 g = } K * n |的监控

此外,经过网络恳求质量的监控,咱k % M – ! b : Q们知道了用户一切网络恳求的次数与巨细,经过巨细和次数排查,咱们就能知道用户在运用, I _ H进程中遇到了哪些 bug 或许是执行了一些反常的逻辑导致重复下载,处于不断重试的进程之中。

3)、自动预警的才能

在客户端,咱们发现了相似的问题之后,咱们还需求装备自动预警的才能,及时地告诉开发同学进行扫除w C S m验证,经过以上手法,咱们对待用户的反应就能愈加高效的处理1 R p [ $,因为咱们有了用户一切的网络恳求数据。

4、系统怎样知道当时 WiFi 有问题?

假如一个 WY 3 $ – B g C –iF( . y ; ( K i #i 发送过数据包,可是没有收到任何的 ACK 回包,这个时分就能够初步判别当时的 WiFi 是有问题的。

九、总结M g b m v }

网络优化能够说是移动端功能优化范畴中水最深的范畴之C Q } @一,要想做好网络优化有必要具备十分扎实的技能功底与全链路思想。总所周知,关于一] 3 @ ( /个工程师/ M 1 [ X 6 %的技能评级往往是以他最深化的那一两个范畴为基准,而不是核算其技y L h能栈的平均值。因而,主张咱们能找准一两个点,例如 网络、内存、NDK、Flutter,对其进行深化挖掘,以打造本身的技能壁垒。而笔者后续也会利用晚上的时刻继续深化 网络协议与安全 的范畴,开端继续不断地深化挖掘。

公众号

我的公B s r = = 9 x E众号 JsonChao 注册啦,欢迎重视~

参阅链接:


  • 1、慕课网之Top团队大牛带你玩转Android功能剖析与优化 第八章 App网络优化
  • 2、极客时刻之Android开发高手课 网络优化
  • 3、《Android移动功能实战》第三R U b }章 网络
  • 5、极客时刻之Web 协议详解与抓包实战
  • 5、geektime-geekbang/geektimV , z ` se-webprotocol
  • 6、wanandroid 网络优化
  • 7、chrome TLS1.3 设置
  • 8、美团点评移动网络优化实践
  • 9、蘑菇街 App Chromium 网络栈实践
  • 10、微h O | 5 L e L [信Mars — 移动互联网下的高质量网络衔接探究.pdf
  • 11、Mars — 微信跨渠j x y # q p : W道跨事务根底组件
  • 12、阿里无线 11.11:手机淘宝移动端接入网关根底架构演进之路
  • 13、3 e D Y b贾岛:蚂蚁金服亿级并发下的移动端到端网络接入架构解析
  • 14、携程 App 的网络功能优化实践
  • 15、百度App网络深度优化系列《一》DNS优化
  • 16V v p、goo8 = R I f S x 1 [gle/brotli
  • 17、facebook/zstd
  • 18、看得「深」、看得「2 h 0清」—— 深度学习在图画超清化的运用
  • 19、^ , o qTLS1i e e $ h.3 VS TLS1.2,让你k p T 5 *理解TLS1.3的强壮
  • 20、根据TLS1.3的微信安全通讯协议mmtls介绍
  • 21、Facebook是怎样大A [ e C ! ,幅进步TLS衔接功率的?
  • 22、SSL Pinning Practice
  • 23、8 Z r ^ 5 ` rP2P怎样将视频直播带宽5 + o H ; A下降75%?
  • 2z 5 W 4 24、BBR: Congestion-Based Coe u 9ngestion Control
  • 25、QUIC在手机微博中U Q p的运用实践.pdf
  • 26、Hook Socket Sample
  • 27、RFC 目录

Contanct Me

● 微信:

欢迎重视我的微信:bcce5360

● 微信群:

因为微信群人数过多,费事咱们想进微信群的朋友们,加我微信拉你进群。q # K

O + ) : e QQ群:

2千人QQ群,Awesome-Y p { $ iAndroid学习沟通群,QQ群号:959936182, 欢迎咱们参加~

About me

  • Email: chao.qu521@gmail.com

  • Blog: jsonchao.git% N x R F _ Khub.io/

  • 掘金: juejin.im/user/5a3ba9…

很感谢您阅览这篇文章,希望k J V ^ |您能将它共享给您的朋友或技能群,这对我意义严重。

希望咱们能成为朋友,在 Github、掘金上一同共享常识。

本文运用 mdnice 排版