偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

攜程弱網(wǎng)識別技術(shù)探索

人工智能 新聞
攜程目前已經(jīng)針對弱網(wǎng)場景推出了一系列優(yōu)化策略,部分策略已經(jīng)取得非常不錯的收益,后續(xù)我們會繼續(xù)推進,也會持續(xù)分享輸出。

網(wǎng)絡(luò)優(yōu)化一直是移動互聯(lián)網(wǎng)時代的熱議話題,弱網(wǎng)識別作為弱網(wǎng)優(yōu)化的第一步,受到的關(guān)注和討論也是最多的。本文從設(shè)計、開發(fā)、落地詳盡的分享了攜程在弱網(wǎng)識別方面的實踐經(jīng)驗,如果你也有類似需求,這篇文章會是一個不錯的實操指南。

一、背景

二、技術(shù)方案

2.1 數(shù)據(jù)采集

2.2 數(shù)據(jù)處理

2.3 結(jié)果輸出

三、落地效果

四、未來展望

一、背景

自從2010年攜程推出”無線戰(zhàn)略“,并發(fā)布移動端APP以來,無線研發(fā)團隊對于客戶端網(wǎng)絡(luò)性能的優(yōu)化就一直沒有停止過。經(jīng)過這十幾年持續(xù)不斷的優(yōu)化,目前攜程的端到端網(wǎng)絡(luò)性能已經(jīng)處于一個相當不錯的水平,大盤數(shù)據(jù)趨于穩(wěn)定,優(yōu)化也隨之進入 ”深水區(qū)“,提升難度巨大。

結(jié)合線上的一系列客訴反饋,我們發(fā)現(xiàn)即使大盤的數(shù)據(jù)再優(yōu)秀,用戶網(wǎng)絡(luò)表現(xiàn)不佳的個例case仍然層出不窮,排查后大部分被我們歸因到"弱網(wǎng)”。這部分“弱網(wǎng)”長尾數(shù)據(jù)相比大盤均值仍有巨大的提升空間,如果可以針對性優(yōu)化的話,對于提升整體用戶體驗和減少客訴都有非常明確的價值。

既然要優(yōu)化“弱網(wǎng)”,那第一步一定是建立相應(yīng)的“弱網(wǎng)識別模型”,準確識別出弱網(wǎng)場景,本文即探討攜程在弱網(wǎng)識別方面的技術(shù)探索,包含技術(shù)選型細節(jié)和關(guān)鍵的路徑思考,歡迎溝通交流。

二、技術(shù)方案

圖片

攜程弱網(wǎng)識別模型的整個工作流程由數(shù)據(jù)采集、數(shù)據(jù)處理、結(jié)果輸出三部分組成,接下來我們順著流程來逐個剖析相關(guān)細節(jié)。

2.1 數(shù)據(jù)采集

2.1.1 可以客觀反映網(wǎng)絡(luò)質(zhì)量的指標有哪些

說到可以客觀反映網(wǎng)絡(luò)質(zhì)量的指標,業(yè)內(nèi)定義清晰且獲得公認的有如下這些:

  • HttpRTT:Http請求一次網(wǎng)絡(luò)往返的耗時,具體口徑是客戶端從開始發(fā)送RequestHeader到收到ResponseHeader第一個字節(jié)的時間差
  • TransportRTT:網(wǎng)絡(luò)通道上一次數(shù)據(jù)往返的耗時,具體口徑是客戶端從開始發(fā)送數(shù)據(jù)到收到服務(wù)端返回數(shù)據(jù)第一個字節(jié)的時間差,要減去服務(wù)處理的耗時
  • ThroughPut:網(wǎng)絡(luò)吞吐量,是指定位時間內(nèi)網(wǎng)絡(luò)通道上下行的數(shù)據(jù)量,具體口徑是單位位時間內(nèi)上行或者下行的數(shù)據(jù)量除以單位時間,由于上行數(shù)據(jù)量受到業(yè)務(wù)因素的影響較大,我們一般僅關(guān)注下行
  • BandwidthDelayProduct:帶寬時延乘積,顧名思義是指網(wǎng)絡(luò)帶寬乘以網(wǎng)絡(luò)時延的結(jié)果,即當前網(wǎng)絡(luò)通道里正在傳輸?shù)臄?shù)據(jù)總量,是一個復(fù)合指標,可以客觀反映當前網(wǎng)絡(luò)承載數(shù)據(jù)的能力,計算方式是 ThroughPut * TransportRTT
  • SignalStrength:信號強度,移動互聯(lián)網(wǎng)時代,設(shè)備依靠Wifi或者蜂窩數(shù)據(jù)接入互聯(lián)網(wǎng),信號強度會影響用戶的網(wǎng)絡(luò)表現(xiàn)
  • NetworkSuccessRate:網(wǎng)絡(luò)成功率,剔除業(yè)務(wù)影響的純網(wǎng)絡(luò)行為成功率,與網(wǎng)絡(luò)質(zhì)量呈正相關(guān),包含建聯(lián)成功率、傳輸成功率等

2.1.2 攜程選擇了哪些指標作為模型輸入?為什么

對于網(wǎng)絡(luò)質(zhì)量識別,業(yè)內(nèi)做的比較早的是Google的NQE(Network Quality Estimator),國內(nèi)大多數(shù)網(wǎng)絡(luò)質(zhì)量識別方案也都參考了Google NQE,NQE中識別模型的輸入主要是HttpRTT、TransportRTT、DownstreamThroughput這三個指標。

對于HttpRTT、TransportRTT,在應(yīng)用層和傳輸層都有很多方式可以采集到,且口徑清晰,所以這兩個指標被我們納入采集范圍。

對于DownstreamThroughput,我們實踐過程中發(fā)現(xiàn),該指標受到用戶行為的影響很大,當用戶集中操作大量發(fā)送網(wǎng)絡(luò)請求的時候,該指標就偏高,當用戶停止操作閱讀數(shù)據(jù)時,該指標就會偏低甚至長時間得不到更新,考慮到指標的波動性,我們不將此指標納入采集范圍。

既然DownstreamThroughput被排除在外,那由他參與計算的BandwidthDelayProduct也被我們排除。

SignalStrength信號強度由于iOS無法準確獲取,考慮到多端一致性,也被我們Pass。

NetworkSuccessRate網(wǎng)絡(luò)成功率這個指標,可能很少被其他方案提及到,我們提出這個指標并將他納入采集范圍的主要原因是,基于RTT的網(wǎng)絡(luò)識別模型,在遇到網(wǎng)絡(luò)波動導(dǎo)致的用戶大面積請求失敗時,無法獲取到有效的RTT值,導(dǎo)致識別的準確性和實時性都收到影響,引入網(wǎng)絡(luò)成功率可以很好的彌補這個缺陷,最終線上生產(chǎn)環(huán)境驗證也證明了該指標的必要性。

最終,攜程的網(wǎng)絡(luò)質(zhì)量識別模型采集HttpRTT、TransportRTT、NetworkSuccessRate作為輸入指標。

2.1.3 輸入的網(wǎng)絡(luò)指標如何采集

攜程的網(wǎng)絡(luò)請求,主要有Tcp代理通道、Quic代理通道、Http通道三種網(wǎng)絡(luò)通道。對于上述提到了三個輸入指標,我們從如下網(wǎng)絡(luò)行為中進行數(shù)據(jù)采集:

  • TransportRTT:通道心跳耗時、Tcp通道建聯(lián)耗時、Http通道建聯(lián)耗時(Tips:建聯(lián)耗時不涉及業(yè)務(wù)處理,近似于純網(wǎng)絡(luò)傳輸耗時,所以我們把他作為TransportRTT;Quic建聯(lián)約等于Tls握手耗時,且存在0RTT等特性干擾,所以不采用)
  • HttpRTT:標準Http請求的responseHeader開始接收時間減去RequestHeader的開始發(fā)送時間、自定義網(wǎng)絡(luò)通道請求的開始接收時間減去開始發(fā)送時間
  • NetworkSuccessRate:Tcp建聯(lián)成功狀態(tài)、Quic建聯(lián)成功狀態(tài)、心跳成功狀態(tài)、Http請求是否完整接收到Response

對于自定義的Tcp、Quic代理通道,按照上述口徑在網(wǎng)絡(luò)通道相關(guān)狀態(tài)回調(diào)內(nèi)統(tǒng)計數(shù)據(jù)即可,自定義實現(xiàn)參考價值不大,這里就不過多贅述。

對于標準的Http請求,我們可以通過獲取系統(tǒng)網(wǎng)絡(luò)框架返回的Metric信息或者監(jiān)聽請求的狀態(tài)流轉(zhuǎn)來獲取網(wǎng)絡(luò)指標。

對于iOS,iOS 10之后NSURLSession支持通過NSURLSessionTaskDelegate的協(xié)議方法URLSession:task:didFinishCollectingMetrics:獲取到請求的Metric信息,詳細信息見附錄1,單次請求的Metric定義如下圖:

圖片

  • TransportRTT = connectEnd - connectStart - secureConnectionEnd + secureConnectionStart;建聯(lián)耗時要減去Tls的耗時,連接復(fù)用時,相關(guān)字段為空值,不納入計算
  • HttpRTT = responseStart - requestStart
  • NetworkSuccessStatus = responseEnd 且沒有傳輸錯誤;網(wǎng)絡(luò)成功率只關(guān)心傳輸是否成功,不需要關(guān)注Response的http狀態(tài)碼

對于Android,系統(tǒng)網(wǎng)絡(luò)框架OkHttp支持添加EventListener來獲取Http請求的狀態(tài)流轉(zhuǎn)信息,可以在各狀態(tài)回調(diào)內(nèi)記錄時間戳來計算RTT,詳細信息見附錄2,單次請求的Events定義如下圖:

圖片

  • TransportRTT = connectEnd - connectStart - secureConnectEnd + secureConnectStart
  • HttpRTT = responseHeadersStart - requestHeadersStart
  • NetworkSuccessStatus = responseBodyEnd 且沒有傳輸錯誤

依照上述方法收集到網(wǎng)絡(luò)數(shù)據(jù)后,我們把數(shù)據(jù)封裝成對應(yīng)的結(jié)構(gòu)體,注入識別模型,攜程對于網(wǎng)絡(luò)數(shù)據(jù)結(jié)構(gòu)體的定義如下,方便大家參考:

typedef enum : int64_t {    


    NQEMetricsSourceTypeInvalid = 0,              // 0
    NQEMetricsSourceTypeTcpConnect = 1 << 0,      // 1
    NQEMetricsSourceTypeQuicConnect = 1 << 1,     // 2
    NQEMetricsSourceTypeHttpRequest = 1 << 2,     // 4
    NQEMetricsSourceTypeQuicRequest = 1 << 3,     // 8
    NQEMetricsSourceTypeHeartBeat = 1 << 4,       // 16
    ......
} NQEMetricsSourceType;


struct NQEMetrics {


    // 本次采集到的數(shù)據(jù)來源,可以是多個枚舉值的或值
    // 例如一次沒有連接復(fù)用http請求,source = TcpConnect|HttpRequest,同時存在transportRTT和httpRTT     NQEMetricsSourceType source;
    // 本次數(shù)據(jù)的成功狀態(tài),用作成功率計算
    bool isSuccessed;
    // httpRTT,可為空
    double httpRTTInSec;
    // transportRTT,可為空
    double transportRTTInSec;
    // 數(shù)據(jù)采集時間
    double occurrenceTimeInSec;
};

2.2 數(shù)據(jù)處理

2.2.1 數(shù)據(jù)過濾和滑動窗口

網(wǎng)絡(luò)數(shù)據(jù)采集后,注入到識別模型內(nèi),需要一個數(shù)據(jù)結(jié)構(gòu)來承載,我們采用的是隊列。

進入隊列前,我們需要先進行數(shù)據(jù)過濾,篩選掉一些無效的數(shù)據(jù),目前采用的篩選策略有如下這些:

  • 單條NQEMetrics數(shù)據(jù),在isSuccessed=true的情況下,httpRTT、transportRTT至少有一條不為空,否則為無效數(shù)據(jù)
  • RTT必須大于最小閾值,用來過濾一些類似LocalHost請求的臟數(shù)據(jù),目前采用的閾值為10ms
  • RTT必須小于最大閾值,用來過濾前后臺切換進程掛起導(dǎo)致的RTT數(shù)值偏大,目前采用的閾值為5mins

數(shù)據(jù)過濾后加入隊列,為了實時性和結(jié)果準確性,我們處理數(shù)據(jù)時,會根據(jù)兩個限制邏輯來確定一個具體的滑動窗口,只讓窗口內(nèi)的數(shù)據(jù)參與計算,具體窗口限制邏輯如下:

  • 最小數(shù)量限制,當窗口內(nèi)數(shù)據(jù)過少時,會放大單條數(shù)據(jù)的影響,導(dǎo)致結(jié)果毛刺增多,所以我們限制最小計算窗口的數(shù)據(jù)條數(shù)為5
  • 最大時間限制,為了數(shù)據(jù)實時性的考慮,比較舊的數(shù)據(jù)不參與計算,目前采用的閾值為5mins

每次計算網(wǎng)絡(luò)質(zhì)量時,可以根據(jù)這兩個限制來確定計算窗口,窗口外的數(shù)據(jù)可以實時清理出隊列,減少內(nèi)存占用。

上文提到的各種閾值設(shè)置,均可通過配置系統(tǒng)更新。

2.2.2 動態(tài)權(quán)重計算

弱網(wǎng)識別模型的原理簡單來說就是將窗口內(nèi)的一組數(shù)據(jù)經(jīng)過一系列處理后,得出一個最終值,再用這個最終值與對應(yīng)的弱網(wǎng)閾值比較來得出是否是弱網(wǎng)。

出于實時性的考慮,我們希望距離當前時間越近的數(shù)據(jù)權(quán)重越高,所以要用到動態(tài)權(quán)重的算法,這里我們比較推薦的是”半衰期動態(tài)權(quán)重“和”反正切動態(tài)權(quán)重“兩種算法。

半衰期動態(tài)權(quán)重

半衰期顧名思義,即每經(jīng)過一個固定的時間,權(quán)重降低為之前的一半。這里衰減幅度和周期都是可以自定義的,計算公式如下:

  • 每秒衰減因子 = pow(衰減幅度, 1.0 / 衰減周期);衰減幅度為浮點型,取值范圍 0~1,衰減周期為整形,單位為秒
  • 動態(tài)權(quán)重 = pow(每秒衰減因子, abs(now - 數(shù)據(jù)采集時間))

以衰減幅度為0.5,衰減周期為60秒為例,對應(yīng)的函數(shù)曲線如下:

圖片

橫坐標為數(shù)據(jù)采集時間距今的時間差,縱坐標為權(quán)重,從圖上可以清晰看到,隨著時間差增大,權(quán)重無限趨近于0。

半衰期動態(tài)權(quán)重也是Google NQE采用的權(quán)重計算方案,Google采用的周期是每60秒降低50%,相關(guān)代碼詳見附錄3,部分核心代碼如下:

double GetWeightMultiplierPerSecond(
    const std::map<std::string, std::string>& params) {
  // Default value of the half life (in seconds) for computing time weighted
  // percentiles. Every half life, the weight of all observations reduces by
  // half. Lowering the half life would reduce the weight of older values
  // faster.
  int half_life_seconds = 60;
  int32_t variations_value = 0;
  auto it = params.find("HalfLifeSeconds");
  if (it != params.end() && base::StringToInt(it->second, &variations_value) &&
      variations_value >= 1) {
    half_life_seconds = variations_value;
  }
  DCHECK_GT(half_life_seconds, 0);
  return pow(0.5, 1.0 / half_life_seconds);
}


void ObservationBuffer::ComputeWeightedObservations(
    const base::TimeTicks& begin_timestamp,
    int32_t current_signal_strength,
    std::vector<WeightedObservation>* weighted_observations,
    double* total_weight) const {


    base::TimeDelta time_since_sample_taken = now - observation.timestamp();
    double time_weight =
        pow(weight_multiplier_per_second_, time_since_sample_taken.InSeconds());
…
}

反正切動態(tài)權(quán)重

y=arctan(x)反正切函數(shù)在第一象限的取值范圍為0~Pi/2,我們將arctan(x)取反,向上平移Pi/2,然后除以Pi/2,函數(shù)曲線即可在第一象限隨著x增大y的取值從1趨近于0。我們還可以使用一個斜率系數(shù)來控制權(quán)重降低的趨勢快慢,公式推導(dǎo)過程如下:

動態(tài)權(quán)重 = (Pi / 2  - arctan(abs(now - 數(shù)據(jù)采集時間) * 斜率系數(shù))) / (Pi / 2) = 1 - arctan(abs(now - 數(shù)據(jù)采集時間) * 斜率系數(shù))  / Pi * 2;斜率系數(shù)為浮點型,取值范圍為0~1,系數(shù)越小,權(quán)重降低的越緩慢。

以斜率系數(shù)為1/20為例,對應(yīng)的函數(shù)曲線如下:

圖片

和前文的半衰期動態(tài)權(quán)重相同,橫坐標為數(shù)據(jù)采集時間距今的時間差,縱坐標為權(quán)重,隨著時間差增大,權(quán)重趨近于0,兩種動態(tài)權(quán)重算法效果類似。

反正切動態(tài)權(quán)重的實現(xiàn)代碼如下:

static double _nqe_getWeight(double targetTime) {
    ……
    double interval = now - targetTime;
    /// 曲率系數(shù),數(shù)值越小權(quán)重降低的越緩慢
    double rate = 20.0 / 1;
    return 1.0 - atan(interval * rate) / M_PI_2;
}

從上圖的代碼實現(xiàn)可以看出,反正切相關(guān)的代碼實現(xiàn)要簡單很多,但是由于存在推導(dǎo)過程,所以理解起來比較困難,代碼維護成本較高(數(shù)學(xué)功底對于程序員來說也是非常重要的),大家可以酌情自行選擇。

攜程最終采用的也是半衰期動態(tài)權(quán)重的方案,出于實時性考慮,最終線上驗證后采用的衰減幅度為0.3,衰減幅度為60秒,供參考。

2.2.3 RTT指標加權(quán)中值計算

在確定了單條數(shù)據(jù)的權(quán)重之后,對于RTT的數(shù)值計算,我們第一個想到的是加權(quán)平均,但是加權(quán)平均很容易收到高權(quán)重臟數(shù)據(jù)的影響,準確性堪憂,所以我們改用了“加權(quán)中值”。

加權(quán)中值的計算方式是,將窗口內(nèi)的數(shù)據(jù)按照數(shù)值大小升序排列,然后從頭遍歷數(shù)據(jù),累加權(quán)重大于等于總權(quán)重的一半時,停止遍歷,當前遍歷到的數(shù)值即為最終的加權(quán)中值。

NQE對于TransportRTT和HttpRTT處理,也是使用的這種方式,相關(guān)代碼詳見附錄4,部分核心代碼如下:

std::optional<int32_t> ObservationBuffer::GetPercentile(
    base::TimeTicks begin_timestamp,
    int32_t current_signal_strength,
    int percentile,
    size_t* observations_count) const {


……
  // 此處的percentile值為50,即取中值
  double desired_weight = percentile / 100.0 * total_weight;
  double cumulative_weight_seen_so_far = 0.0;
  for (const auto& weighted_observation : weighted_observations) {
    cumulative_weight_seen_so_far += weighted_observation.weight;
    if (cumulative_weight_seen_so_far >= desired_weight)
      return weighted_observation.value;
  }
  // Computation may reach here due to floating point errors. This may happen
  // if |percentile| was 100 (or close to 100), and |desired_weight| was
  // slightly larger than |total_weight| (due to floating point errors).
  // In this case, we return the highest |value| among all observations.
  // This is same as value of the last observation in the sorted vector.
  return weighted_observations.at(weighted_observations.size() - 1).value;
}

2.2.4 成功率指標加權(quán)平均計算

對于成功率,我們的NQEMetrics結(jié)構(gòu)體內(nèi)定義了單次成功狀態(tài)isSuccessed,單條數(shù)據(jù)的加權(quán)成功率為 (NQEMetrics.isSuccessed ? 1 : 0) * weight,整體的加權(quán)成功率為加權(quán)成功率總和除以總權(quán)重。

相關(guān)代碼實現(xiàn)如下:

extern double _calculateSuccessRateByWeight(const vector<CTNQEMetrics> &metrics, uint64_t types, const shared_ptr<NQEConfig> config) {
    ……
    uint64_t totalValidCount = 0;
    double totalWeights = 0.0;
    double totalSuccessRate = 0.0;


    for (const auto& m : metrics) {
        /// 過濾需要的數(shù)據(jù)
        if ((m.source & types) == 0) {
            continue;
        }
        /// 累計總權(quán)重和總成功率
        totalValidCount++;
        totalWeights += m.weight;
        totalSuccessRate += (m.isSuccessed ? 1 : 0) * m.weight;
    }


    /// 數(shù)據(jù)不足
    if (totalValidCount < config->minValidWindowSize) {
        return NQE_INVALID_RATE_VALUE;
    }
    if (totalWeights <= 0.0) {
        return NQE_INVALID_RATE_VALUE;
    }


    return totalSuccessRate / totalWeights;
}

2.2.5 引入成功率趨勢提高實時性

網(wǎng)絡(luò)質(zhì)量識別不僅需要準確,實時性也非常重要,在網(wǎng)絡(luò)質(zhì)量切換時模型識別的時間越短越好。前文已經(jīng)提到了TransportRTT、HttpRTT、NetworkSuccessRate三個核心指標的計算,但是在線上實際驗證的過程中,我們發(fā)現(xiàn)在網(wǎng)絡(luò)完全不可用成功率跌0后,識別模型對于網(wǎng)絡(luò)狀態(tài)的恢復(fù)感知很慢,原因是成功率的攀升需要較長的時間。

針對這個極端的case,我們引入了一個“成功率趨勢”的新指標,來優(yōu)化模型的實時性,在成功率未達閾值當時有明顯趨勢時,提前切換網(wǎng)絡(luò)質(zhì)量狀態(tài)。成功率趨勢是指一段時間內(nèi)成功率連續(xù)上升或者下降的幅度,浮點類型,取值范圍-1 ~ +1。

成功率趨勢初始值為0,計算方式如下:

1)在每次更新成功率時,計算更新前后成功率的差值

如果差值為正,則成功率向好

  • 如果當前成功率趨勢值為正,則向好趨勢持續(xù),成功率趨勢加上當前差值
  • 如果當前成功率趨勢值為負,則成功率趨勢由壞轉(zhuǎn)好,成功率趨勢重置為當前差值

如果差值為負,則成功率向壞

  • 如果當前成功率趨勢值為正,則成功率趨勢由好轉(zhuǎn)壞,成功率趨勢重置為當前差值
  • 如果當前成功率趨勢值為負,則向壞趨勢持續(xù),成功率趨勢加上當前差值(負值)

2)當然還需要過濾一些毛刺數(shù)據(jù),避免趨勢變化過頻

具體代碼實現(xiàn)如下:

void NQE::_updateSuccessRateTrend() {
    auto oldRate;
    auto newRate;


    if (oldRate < 0 || newRate < 0) {
        _successRateContinuousDiff = 0;
        return;
    }
    auto diff = newRate - oldRate;
    /// 數(shù)據(jù)錯誤,不做處理
    if (abs(diff) > 1) {
        _successRateContinuousDiff = 0;
        return;
    }
    /// diff小于0.01,作為毛刺處理,不影響趨勢變化
    if (abs(diff) < 0.01) {
        _successRateContinuousDiff += diff;
        return;
    }
    /// 計算連續(xù)diff
    if (diff > 0 && _successRateContinuousDiff > 0) {
        _successRateContinuousDiff += diff;
    } else if (diff < 0 && _successRateContinuousDiff < 0) {
        _successRateContinuousDiff += diff;
    } else {
        _successRateContinuousDiff = diff;
    }
}

在網(wǎng)絡(luò)成功率和成功率趨勢的加持下,我們的識別模型實時性大幅度提升。我們控制相同請求頻率和請求數(shù)據(jù)量,線下模擬弱網(wǎng)切換進行測試,測試結(jié)果如下:

  • 單RTT識別模型,網(wǎng)絡(luò)質(zhì)量切換后識別較慢,且存在連續(xù)切換場景識別不出弱網(wǎng)的情況
  • RTT+成功率模型,切換識別速度較單RTT模型提升約50%,成功率跌0后的Bad切Good識別明顯較慢
  • RTT+成功率+成功率趨勢模型,切換識別速度較單RTT模型提升約70%,Bad切Good識別速度明顯提升

所以,最終攜程弱網(wǎng)識別模型計算的指標有TransportRTT、HttpRTT、NetworkSuccessRate、SuccessRateTrend(成功率趨勢)四個。

2.3 結(jié)果輸出

2.3.1 網(wǎng)絡(luò)質(zhì)量定義

識別模型對外輸出的是一個網(wǎng)絡(luò)質(zhì)量的枚舉值,Google NQE對于網(wǎng)絡(luò)質(zhì)量的定義如下,源碼詳見附錄5:

enum EffectiveConnectionType {
  // Effective connection type reported when the network quality is unknown.
  EFFECTIVE_CONNECTION_TYPE_UNKNOWN = 0,


  // Effective connection type reported when the Internet is unreachable
  // because the device does not have a connection (as reported by underlying
  // platform APIs). Note that due to rare but  potential bugs in the platform
  // APIs, it is possible that effective connection type is reported as
  // EFFECTIVE_CONNECTION_TYPE_OFFLINE. Callers must use caution when using
  // acting on this.
  EFFECTIVE_CONNECTION_TYPE_OFFLINE,


  // Effective connection type reported when the network has the quality of a
  // poor 2G connection.
  EFFECTIVE_CONNECTION_TYPE_SLOW_2G,


  // Effective connection type reported when the network has the quality of a
  // faster 2G connection.
  EFFECTIVE_CONNECTION_TYPE_2G,


  // Effective connection type reported when the network has the quality of a 3G
  // connection.
  EFFECTIVE_CONNECTION_TYPE_3G,


  // Effective connection type reported when the network has the quality of a 4G
  // connection.
  EFFECTIVE_CONNECTION_TYPE_4G,


  // Last value of the effective connection type. This value is unused.
  EFFECTIVE_CONNECTION_TYPE_LAST,
};

Google枚舉定義的最大問題是理解成本比較高,其他開發(fā)同學(xué)看到這個所謂的“3G”、“4G”,他依然不知道網(wǎng)絡(luò)是好是壞,是不是他認為的“弱網(wǎng)”。

所以我們在定義接口的時候,對于枚舉的設(shè)計考慮最多的就是理解成本,結(jié)合開發(fā)同學(xué)最想知道的“是不是弱網(wǎng)”,我們的接口定義如下:

typedef enum : int64_t {
    /// 未知狀態(tài),初始狀態(tài)或者無有效計算窗口時會進入此狀態(tài)
    NetworkQualityTypeUnknown = 0,
    /// 離線狀態(tài),網(wǎng)絡(luò)不可用
    NetworkQualityTypeOffline = 1,
    /// 弱網(wǎng)狀態(tài)
    NetworkQualityTypeBad = 2,
    /// 正常網(wǎng)絡(luò)狀態(tài)
    NetworkQualityTypeGood = 3
} NetworkQualityType;

這樣是不是看起來簡單明了多了,我們接下來就講講怎么計算得出這幾個枚舉的結(jié)果。

2.3.2 網(wǎng)絡(luò)質(zhì)量計算方式

NetworkQualityTypeUnknown 是在初始化或者網(wǎng)絡(luò)切換后的一段時間內(nèi),數(shù)據(jù)不足無法得出網(wǎng)絡(luò)質(zhì)量,會進入此狀態(tài)。

NetworkQualityTypeOffline 的觸發(fā)條件很單一,就是操作系統(tǒng)識別到無網(wǎng)絡(luò)連接,具體的獲取方式由各平臺自行實現(xiàn),例如iOS可以通過Reachability獲取,官方Demo詳見附錄6。

NetworkQualityTypeBad 也就是我們最核心的“弱網(wǎng)”狀態(tài),計算方式是上文提到的TransportRTT、HttpRTT兩個指標任一指標觸發(fā)弱網(wǎng)閾值,或者NetworkSuccessRate和SuccessRateTrend同時滿足弱網(wǎng)閾值。

NetworkQualityTypeGood 是指正常的網(wǎng)絡(luò)質(zhì)量狀態(tài),上述三種網(wǎng)絡(luò)質(zhì)量類型講完后,這個類型就簡單了,即非上述三種情況的場景,歸類到Good,這也是設(shè)計上占比最高的網(wǎng)絡(luò)質(zhì)量類型。

識別模型的運轉(zhuǎn)流程如下:

圖片

  • 數(shù)據(jù)隊列在初始化和網(wǎng)絡(luò)連接狀態(tài)變化兩個時機會被重置,充值后網(wǎng)絡(luò)質(zhì)量類型進入 NetworkQualityTypeUnknown
  • 網(wǎng)絡(luò)連接狀態(tài)進入無連接狀態(tài)時,數(shù)據(jù)隊列被清空,網(wǎng)絡(luò)質(zhì)量類型直接進入 NetworkQualityTypeOffline,在網(wǎng)絡(luò)類型變?yōu)榭捎妙愋颓?,?shù)據(jù)隊列不接受數(shù)據(jù)注入,且不進行計算
  • 數(shù)據(jù)隊列的數(shù)據(jù)變化觸發(fā)質(zhì)量計算,出于資源開銷考慮,要限制計算的頻次,我們采用計算間隔和新增數(shù)據(jù)量兩個閾值限制,計算間隔大于60s或者新增數(shù)據(jù)量超過10條才會觸發(fā)計算;同時也暴露了對外接口,業(yè)務(wù)可按需強制刷新計算結(jié)果
  • 關(guān)于主動網(wǎng)絡(luò)探測,可結(jié)合自身的業(yè)務(wù)需求按需實現(xiàn),目前攜程的APP在使用時網(wǎng)絡(luò)數(shù)據(jù)更新比較頻繁,無需補充主動探測數(shù)據(jù)

2.3.3 弱網(wǎng)閾值制定

模型核心的計算邏輯,就是將加工后得到的各網(wǎng)絡(luò)指標與對應(yīng)的弱網(wǎng)閾值進行對比,從而獲得是否進入弱網(wǎng)的結(jié)果,關(guān)于弱網(wǎng)閾值的制定上,我們經(jīng)歷了如下兩個階段:

第一階段,主要參考NQE EFFECTIVE_CONNECTION_TYPE_2G 的閾值定義

  • HttpRTT > 1726ms
  • TransportRTT > 1531ms
  • 成功率按照內(nèi)部討論的預(yù)期設(shè)置為 NetworkSuccessRate < 90%
  • 成功率趨勢閾值設(shè)置為 SuccessRateTrend < 0.1,即成功率連續(xù)向好增加超過10pp,即使成功率小于90%,也從Bad切換為Good,這個指標主要是為了提升Bad切Good的速度

第二階段,我們通過線上的網(wǎng)絡(luò)質(zhì)量分布監(jiān)控,和一些具體case的分析,不斷迭代我們的閾值,我們需要制定一個識別準確率的指標來指引閾值的調(diào)整工作,達到邏輯準確與自洽。

理論上,我們希望識別模型的入?yún)⑴c當下計算出的網(wǎng)絡(luò)質(zhì)量類型所匹配,例如當前注入NQEMetrics數(shù)據(jù)的HttpRTT <= 1726ms ,那我們預(yù)期當前計算出的網(wǎng)絡(luò)質(zhì)量類型就是Good。但是弱網(wǎng)的決策邏輯是相對復(fù)雜的,需要考慮到各種因素,以下兩點會造成弱網(wǎng)狀態(tài)下的入?yún)?shù)據(jù)不一定符合弱網(wǎng)閾值定義:

1)弱網(wǎng)的計算是對過去已經(jīng)發(fā)生網(wǎng)絡(luò)行為的分析,具有一定的滯后性,所以在識別結(jié)果切換附近,必然有部分的原數(shù)據(jù)已經(jīng)滿足下一階段的網(wǎng)絡(luò)質(zhì)量定義

2)弱網(wǎng)的決策是對多個指標的復(fù)合計算,所以在識別到弱網(wǎng)狀態(tài)時,不一定所有的指標原數(shù)據(jù)都符合弱網(wǎng)定義,比如由HttpRTT觸發(fā)弱網(wǎng)時,當前的TransportRTT數(shù)據(jù)可能表現(xiàn)良好

終上兩點原因,弱網(wǎng)分類下必然有一定的非弱網(wǎng)數(shù)據(jù),這里的誤差數(shù)據(jù)占比與識別準確率負相關(guān),誤差數(shù)據(jù)占比越低,識別準確率越高。所以想到這里,我們的模型識別準確率的指標計算口徑就有了:

  • 模型弱網(wǎng)識別準確性 = 100% - 弱網(wǎng)狀態(tài)下不符合弱網(wǎng)閾值定義原數(shù)據(jù)占比

有了這個指標指引,我們在模型上線后進行了數(shù)個版本的數(shù)據(jù)統(tǒng)計,通過各指標閾值的微調(diào)和case by case解決異常場景,誤差數(shù)據(jù)從剛上線的15%+降低到10%以下,即模型識別準確率優(yōu)化至90%以上。

最終攜程90%準確率的模型對應(yīng)的弱網(wǎng)閾值如下(不同業(yè)務(wù)場景的網(wǎng)絡(luò)請求差別較大,僅供大家參考):

  • HttpRTT > 1220ms;這個值是線上HttpRTT的TP98值,與弱網(wǎng)占比相近
  • TransportRTT > 520ms;同線上TP98值
  • NetworkSuccessRate < 90%
  • SuccessRateTrend < 0.2;之前的0.1導(dǎo)致模型的結(jié)果切換過于頻繁,最終調(diào)整到了0.2

Tips:對于類似攜程這種自定義的弱網(wǎng)識別模型,弱網(wǎng)標準也是考慮業(yè)務(wù)現(xiàn)狀的定制標準,所以不需要太多和外部的弱網(wǎng)標準對齊,重點是自洽和符合業(yè)務(wù)預(yù)期。

三、落地效果

考慮到識別模型要支持多平臺(iOS、Android、Harmony等),所以我們在一開始實現(xiàn)方案時就采用了C++作為開發(fā)語言,天然支持了多平臺,各平臺只需要實現(xiàn)上層數(shù)據(jù)采集和注入模型的少量邏輯即可完成模型的接入。相同的代碼實現(xiàn)和弱網(wǎng)標準,也方便我們在不同的平臺間直接對標數(shù)據(jù),發(fā)現(xiàn)各平臺的問題針對性優(yōu)化。

目前攜程的網(wǎng)絡(luò)質(zhì)量識別模型,已經(jīng)在iOS、Android平臺完成接入并大面積投產(chǎn),網(wǎng)絡(luò)質(zhì)量數(shù)據(jù)與集團的APM監(jiān)控平臺打通,形成了攜程官方統(tǒng)一的網(wǎng)絡(luò)質(zhì)量標準,在網(wǎng)絡(luò)排障、框架網(wǎng)絡(luò)優(yōu)化、業(yè)務(wù)網(wǎng)絡(luò)優(yōu)化等多種場景下扮演重要角色,弱網(wǎng)優(yōu)化相關(guān)的內(nèi)容我們會在后面相關(guān)的專題內(nèi)繼續(xù)分享,此處不再贅述。

最終網(wǎng)絡(luò)質(zhì)量相關(guān)的分布數(shù)據(jù)如下(數(shù)據(jù)為實驗采集,不代表攜程真實業(yè)務(wù)情況,僅參考):

網(wǎng)絡(luò)質(zhì)量分布:

圖片

各網(wǎng)絡(luò)質(zhì)量下對應(yīng)的請求性能數(shù)據(jù):

圖片

四、未來展望

網(wǎng)絡(luò)質(zhì)量識別模型的完成只是我們網(wǎng)絡(luò)優(yōu)化的開始,后續(xù)還有很多的工作需要我們繼續(xù)努力,未來一段時間我們會從以下幾個方面繼續(xù)推進:

1)持續(xù)推進各平臺、各獨立APP的網(wǎng)絡(luò)質(zhì)量識別模型接入,完成攜程終端全平臺的網(wǎng)絡(luò)質(zhì)量模型覆蓋

2)做好識別模型的防劣化工作,解決各業(yè)務(wù)場景的bad case,堅守現(xiàn)階段識別準確率和實時性的標準水位

3)推出攜程內(nèi)部的“網(wǎng)絡(luò)性能白皮書”,從APP、系統(tǒng)平臺、網(wǎng)絡(luò)質(zhì)量、成功率、全鏈路耗時等各維度解析公司內(nèi)部各業(yè)務(wù)線的網(wǎng)絡(luò)表現(xiàn),形成內(nèi)部的網(wǎng)絡(luò)性能數(shù)據(jù)基線,為業(yè)務(wù)優(yōu)化提供參考

4)借助現(xiàn)有的弱網(wǎng)標準和識別能力,從網(wǎng)絡(luò)框架側(cè)和業(yè)務(wù)側(cè)兩個不同的角度進行弱網(wǎng)優(yōu)化,提高整體網(wǎng)絡(luò)表現(xiàn);當下海外市場是業(yè)務(wù)發(fā)力的重點,海外場景的網(wǎng)絡(luò)表現(xiàn)也明顯弱于國內(nèi),我們會針對海外場景從弱網(wǎng)的角度進行重點優(yōu)化。

攜程目前已經(jīng)針對弱網(wǎng)場景推出了一系列優(yōu)化策略,部分策略已經(jīng)取得非常不錯的收益,后續(xù)我們會繼續(xù)推進,也會持續(xù)分享輸出。

責任編輯:張燕妮 來源: 攜程技術(shù)
相關(guān)推薦

2022-06-17 10:44:49

實體鏈接系統(tǒng)旅游AI知識圖譜攜程

2023-08-18 10:49:14

開發(fā)攜程

2023-12-29 09:42:28

攜程開發(fā)

2022-05-27 09:52:36

攜程TS運營AI

2014-12-25 17:51:07

2024-03-22 15:09:32

2024-04-18 09:41:53

2022-07-21 19:36:35

樂高攜程前端

2023-11-13 11:27:58

攜程可視化

2023-03-14 14:01:00

內(nèi)存優(yōu)化

2024-12-18 10:03:30

2024-12-26 09:27:51

2022-07-15 12:58:02

鴻蒙攜程華為

2022-05-13 09:27:55

Widget機票業(yè)務(wù)App

2022-05-27 09:25:12

攜程酒店本地緩存查詢服務(wù)

2017-04-11 15:11:52

ABtestABT變量法

2022-10-21 10:40:08

攜程酒店MySQL慢查詢

2015-05-29 13:59:53

2023-02-08 16:34:05

數(shù)據(jù)庫工具

2022-08-12 08:34:32

攜程數(shù)據(jù)庫上云
點贊
收藏

51CTO技術(shù)棧公眾號