JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

整合服務、區分服務,以及為什麼盡力而為通常會贏

曾有兩套宏大的計畫,想讓整個網際網路都享有服務品質保證——一套替每條資料流預訂私人車道,另一套只在封包上漆出快速道的標線。這篇收尾把兩者放上天秤,再揭開那個比較安靜的真相:聰明的端主機加上便宜的頻寬,讓老派的盡力而為一路贏下去。

向網路討人情的兩種方式

你現在已認識端主機能獨力使用的每一樣工具:吸收抖動的播放緩衝區、替通話打包與建立的 RTPSIP,以及第四篇談過的路由器機器——排程與監管。但這一切,仍然騎在一張對每個封包一視同仁的網路之上。這級階梯更深的問題是:我們能不能要求網路本身厚此薄彼?而結果發現,正好有兩套宏大的問法。兩者都歸在服務品質(QoS)這把大傘底下,而本篇全部的戲劇張力就在於:那個比較有野心的方案,輸了。

第一種方式,是一次對「一條」資料流做出鄭重的承諾:在你的通話開始之前,走遍整條路徑,要求每一台路由器都替你保留一份有保證的自身切片,等所有人都點頭了才開始。這就是整合服務(IntServ)——把它想成在一通通話的期間內,端到端地預訂一條私人車道。第二種方式則乾脆完全拒絕做逐通話的承諾:在網路邊緣替每個封包蓋上一個小小的類別標籤,再讓路由器對整「類」流量給予粗略的優待,根本不知道任何封包屬於哪一條個別資料流。這就是區分服務(DiffServ)——把它想成在路上漆出一條快速道,讓任何貼了正確貼紙的東西都能用它。

整合服務:端到端預留的私人車道

整合服務認真看待時間問題,並試圖把它好好解決:如果一條資料流需要,比方說,穩定的 100 kbps 並帶有上限延遲,那麼沿途每一台路由器都應該真正把這麼多承諾給它。為了把它建立起來,發送端的通話會用一個訊號協定(經典的那個是 RSVP),把一個預留請求逐跳地往接收端送。每一台路由器都會檢查:在我已經承諾過的一切之上,我是否還有足夠的閒置容量來兌現這個?這道檢查叫做准入控制——網路是可以說不的,就像一家訂滿的餐廳在門口把你回絕,而不是把你硬塞進去、毀了所有人的一餐。

  1. 撥話方描述它的資料流:它有多突發(常以一個權杖桶的速率與突發量來表示),以及它想要什麼保證——是硬性的頻寬加延遲上限,還是較寬鬆的「受控負載」。
  2. 一個預留請求沿著路徑逐跳地往接收端行進,途中拜訪每一台路由器。
  3. 每一台路由器都執行准入控制:若它有足夠未承諾的容量,就保留那份切片並轉發請求;若沒有,就回絕整通通話。
  4. 若路徑上每一台路由器都點頭,預留就端到端地確認,媒體便開始在它那條有保證的車道裡流動。
  5. 在資料流運行期間,每一台路由器用像加權公平佇列這樣的排程器來執行承諾,並在通話結束時把預留拆除。

在紙面上這很美好:一個貨真價實、可被執行的保證,是網際網路最接近老式電話網那種預留電路的一次。而這恰恰是它的致命傷。一條繁忙鏈路上的骨幹路由器,可能同時承載數十萬甚至數百萬條資料流,而整合服務卻要求它替「每一條」記住逐流狀態——那份預留、那些權杖桶參數、一個佇列——並且在「每一個」封包上都去查閱這全部。這叫做逐流狀態,是你能要求一台高速路由器保管的最沉重的東西。更糟的是,這份預留必須橫跨路徑所穿越的每一個獨立網路都成立;只要有一台路由器不會講 RSVP,或有一個自治系統拒絕兌現陌生人的預留,那份保證就會悄悄蒸發。

區分服務:貼紙,而非預留

區分服務是由一群看著整合服務被自己的記帳工作噎住的人設計的,它的核心動作是把所有困難的、逐流的工作推到「邊緣」,讓核心保持笨拙而快速。每個 IP 封包的標頭裡本就帶著一個小欄位(DS 欄位,由舊的服務類型位元組改用而來),邊緣可以在裡面寫進一個類別標籤——一個 DSCP 值。網路邊界上屈指可數的幾台路由器負責那個昂貴的部分:它們把封包分類(這是語音?視訊?還是大量下載?)、用約定的速率對它們監管,再替每一個蓋上正確的類別。在那之後,旅行的就只剩這個標籤了。

在核心深處,路由器做的事情清爽得令人耳目一新。它不知道、也不在乎一個封包屬於哪一條資料流;它只是讀那個類別標籤,套用一個事先約定好的轉發行為——行話叫做逐跳行為(per-hop behavior)。標成語音的封包也許進入一個低延遲的優先佇列;標成「保證」的商務流量進入一個分到慷慨份額的加權公平佇列類別;其餘一切則進入普通的盡力而為。路由器逐「類」保管狀態——也許四個或八個桶——而非逐「流」。這就是全部的把戲,也正是它讓區分服務能在整合服務做不到的骨幹速度上運行的原因。

IntServ  (per-FLOW state, set up before the call)
   sender --RSVP reserve--> R1 --> R2 --> R3 --> receiver
   each router stores: this flow -> {rate, delay bound, queue}
   millions of flows  =>  millions of entries per router  (does not scale)

DiffServ (per-CLASS state, decided once at the edge)
   edge router: classify + police + stamp DSCP tag onto each packet
   core router: read tag -> apply per-hop behavior
      EF  (voice)     -> priority queue, low delay
      AF  (business)  -> weighted-fair share
      BE  (default)   -> plain best-effort
   a handful of classes  =>  a handful of entries per router  (scales)
整合服務替每條資料流保管一個承諾,且每個封包都得查閱它;區分服務把工作推到邊緣,讓核心把封包分進幾個類別桶裡。粒度就是整個故事。

區分服務能擴展——但它不承諾

問題就在這裡,這也是這場比較最誠實的核心。一個區分服務的類別標籤並不是預留;它只是一種「相對的」偏好。你的語音封包確實會比大量下載先被處理——但若同一瞬間另有十萬人也把他們的封包標成語音,那個優先佇列本身就會滿溢,你那個低延遲的類別便和其他所有人一起遭殃。區分服務不像整合服務那樣給出任何逐流的頻寬或延遲上限。它改善你的勝算;它不會給你寫一紙合約。即使是這個相對的承諾,要在跨網路時站得住,也需要服務等級協議(SLA)並在每個邊界上監管,這正是為什麼區分服務在單一營運商的網路「內部」往往運行得乾淨俐落,到了營運商「之間」的接縫處卻會綻裂。

所以這兩套架構,按各自的標準來看,都不是乾淨的贏家。整合服務提供真正的保證,卻無法擴展到公開網際網路的數百萬條資料流,跨越所有權邊界時也表現很差。區分服務擴展得很漂亮,卻只提供軟性的、相對的偏好,而且在單一網路之外要有任何意義,仍需要商業協議。這兩套設計都是真實、已部署的技術——尤其是區分服務,在企業網路、行動電信營運商的核心、以及資料中心裡都活得好好的,那些地方由單一管理者掌控每一台路由器,能讓那些標記真的算數。它們倆都沒有成為的,是陌生人之間那張開放網際網路的預設底料。

為什麼盡力而為通常會贏

退一步,真正的結局便清晰起來:在公開的網際網路上,大多數流量仍以盡力而為的方式行進——每個封包待遇相同、毫無承諾,與任何人夢想出 QoS 之前一模一樣。這不是因為工程師失敗了。而是因為有三股比較安靜的力量,一再讓那些花俏的保證變得不值得費事。第一股是你在基礎那一級遇過的端到端原則:讓網路核心保持簡單而笨拙,把智慧推到邊緣。在核心裡逐流預留,直接違反了這條原則,而網際網路整部的擴展史,正是「讓中間保持愚笨」的一場漫長的平反。

第二股力量是,端主機就是變得太會應付了。這級階梯前面的一切,都是不需要網路任何幫忙的端主機招數:慷慨的播放緩衝區吞下抖動,遺失隱藏掩飾掉一個不見的音訊畫格,而自適應位元率串流則盯著連線,在網路一吃緊的那一刻就悄悄降到較低的畫質,等它鬆開了再爬回來。當邊緣能憑自己優雅地撐過顛簸時,為了「預防」顛簸而重新改造核心的理由,就變得單薄了。

第三股力量最直白:頻寬變便宜了,所以最簡單的那個解法——乾脆多加點容量,這策略綽號叫過度配置(overprovisioning)——通常在成本與心力上都勝過聰明的排程。一條很少超過半滿的鏈路,對所有人來說都有極小的佇列延遲、幾乎沒有遺失,不需要任何標記。QoS 賺得它價值的地方,恰恰是你沒辦法直接砸頻寬解決的場合:一條壅塞的行動電話鏈路、一張超額認購的資料中心底料、一段衛星跳躍、一張由單一擁有者掌控的企業廣域網。這就是整級階梯誠實的判決。那些機制是真實的、在受控網路裡也確實重要,但在陌生人之間那張開放的網際網路上,聰明的邊緣加上便宜又粗的鏈路,一再讓老派的盡力而為贏下去。