流量調度、微服務可尋址性和註冊中心

前言

現代計算機基於計算、存儲和調度的體系, 於是現代架構都是圍繞這三大話題不斷演進。

在基礎架構部, 也是主要爲了解決這三個難題,爲業務事業部提供透明的、高可用、可快速伸縮的 三大能力, 我們組主要負責 [流量調度] 這個話題,下面是一些宏觀的技術筆記。



在單體結構, 流量調度是直觀且無感的(DNS+Nginx就可以完成一次流量調度)。
演進到 微服務結構(服務粒度變得更細、服務伸縮更靈活(上下線更加頻繁),團隊松耦合),流量調度並沒有消失,而是變得更加複雜。

關鍵名詞解釋

1. 控制平面/數據平面

控制平面: 內含路由表、負責路由控制, 引導流量的走向,注重“引導”, 屬於旁路業務(核心)。  

數據平面:根據控制平面的路由邏輯,業務流量的實際走向。

控制面很多屬於[核心]旁路業務:要求一致性=> raft協議。

2. 東西/南北流量

南北流量: 業務客戶端--->服務器;
東西流量: 數據中心內或者數據中心之間的服務間調用;

東西/南北流量都屬於數據平面流量。



服務治理的演進

服務治理的基石是動態服務發現, 阿里雲服務治理的演進 大而全,這裏只記錄我的理解。

階段 目標 手段
孵化期 動態服務發現 客戶端/服務端服務發現,負載均衡
成長期 提高開發和迭代效率 規範API、 統一配置、 版本管理
成熟期 部署邊界、鏈路追蹤,彈性伸縮 服務預熱、優雅下線、監控追蹤、限流,熔斷, 回退

核心的技能點

1. 爲什麼需要註冊中心?

並不是微服務催生了 註冊中心,而是微服務強化了註冊中心。

早期DNS+nginx 就能完成單體的 流量調度,但是不管是DNS解析出ip, 還是nginx解析出upstream ,底層都有註冊中心的影子。

這裏面有一個addressability的概念,也即服務可尋址性, 服務必須有一個唯一的可尋址的名字,這個名字不依賴於部署環境,表徵一組可以處理流量的實例資源。

對於資源,必定存在CRUD交互,這便是部署平臺和服務發現,與此同時當實例出現故障時,註冊中心必須能夠指示服務現在在何處運行。

很多時候除了在部署層面,存在健康探測告知業務方目前的應用就緒情況; 實際在接流的時候,負載層還會有自己的主動健康檢查探測。

2. 規範API接口, 統一配置

提高開發迭代效率,統一使用一種method、body payload形式的API接口(規避錯誤格式的傳參導致的撕逼)、不用上n臺實例修改配置。

各個團隊是松耦合的關係,上下游的變更並不會主動通知,故需要版本管理(低版本不能直接下線)、提供給開發團隊的版本調試接口。

3. 服務發現

服務發現是服務治理的基石,三板斧: 註冊、心跳、尋址。

  • 部署系統做[註冊]動作。
  • 微服務客戶端尋址
  • 主動上報心跳/註冊中心主動探活: 維護實例資源狀態。

存在兩種模式: 客戶端服務發現、服務器服務發現, 核心區別在於 : 客戶端是否保存服務列表信息。

4. 負載均衡

  • 隨機
  • 輪詢
  • 帶權輪詢
  • 根據後端實例服務質量動態調度

最近思考了一個問題,負載均衡不僅是拿到服務的可用實例列表,然後做流量均分; 其實負載均衡的存在也爲我們無損切流提供了契機。

5. 飛機起飛和降落最容易出事故

  • 服務預熱: 服務進程啓動,等待業務配置/緩存就緒,再向註冊中心通報實例資源就緒,可以接流。
  • 優雅下線: 下線時設置服務終止時間(30s),處理在途流量, 不再接收新的請求流量。

6. 限流 熔斷

鏈路上部分服務的狀態會影響整個鏈路(雪崩), 故需要保障微服務鏈路的高可用 => 服務的熔斷、限流

熔斷: 熔斷掉對於下游的調用; 限流: 限制進入本應用的流量。

不管是客戶端服務發現,還是服務器服務發現,都存在註冊中心,也可以叫名字服務,是流量調度的基石,統一了流量調度的入口。



現代互聯網結構,流量在打到應用之前,都會以對應的姿勢接入某種負載層。

大多數時候,流量其實不care某個特定的應用實例,更在意的是服務的可用性;

服務端服務發現,在客戶端和接流應用之間形成了一個負載層,除了負載均衡外,還提供了故障轉移和無損擴縮容、無損切流的契機,這些都涉及動態上下線實例, 不同負載層有不同的接流姿勢。


基於nginx7層負載的動態服務發現

我們着重聊一聊基於nginx主機名字的動態服務發現(服務端服務發現)。

nginx做反向代理,負載均衡的時候,我們關注nginx [http配置節]的上下文[server配置節][upstream配置節]。

上面這個配置,nginx會匹配請求的Host頭server_name指令,決定該請求轉發給哪一個upstream虛擬主機。

相關知識,請關注Host請求頭在虛擬主機服務多網域服務中的關鍵作用

利用nginx的第三方組件nginx_http_dyups_module,可以做到動態修改upstream的配置。

This module can be used to update your upstream-list without reloadding Nginx.

daemon off;
error_log logs/error.log debug;

events {
}

http {
    upstream test_upstream {
         server 127.0.0.1:8088;
         server 127.0.0.1:8089;
     }

    server {
        listen   80;

        location / {
            # The upstream here must be a nginx variable
             set $up test_upstream ;
             proxy_pass http://$up;
        }
    }

    server {
        listen 8088;
        location / {
            return 200 "8088";
        }
    }

    server {
        listen 8089;
        location / {
            return 200 "8089";
        }
    }

    server {
        listen  8090;
        location / {
           return 200  "8090" ;
       }
    }

    server {
        listen 8081;
        location / {
            dyups_interface;
        }
    }
}


1. 該組件默認不被編譯進tengine(淘寶開源的具備強特性的nginx分發版),請使用--with-http_dyups_module配置參數啓用。

./configure --add-module=./modules/ngx_http_upstream_dyups_module              // 配置成靜態組件
 make             // 編譯
 make install     // 安裝

2. 需要添加dyups_interface指令激活[動態修改upstream配置]能力

3. 演示利用dyups api在不重啓nginx的情況下修改upstream配置。

查詢upstream和server:localhost:8081/detail

test_upstream
server 127.0.0.1:8088 weight=1 max_conns=0 max_fails=1 fail_timeout=10 backup=0 down=0
server 127.0.0.1:8089 weight=1 max_conns=0 max_fails=1 fail_timeout=10 backup=0 down=0

// 實際請求`curl 127.0.0.1`,輪詢返回8088或者8089

更新upstream配置:
curl -d "server 127.0.0.1:8090;" 127.0.0.1:8081/upstream/test_upstream

// 再次調用`localhost:8081/detail`
test_upstream
server 127.0.0.1:8090 weight=1 max_conns=0 max_fails=1 fail_timeout=10 backup=0 down=0
// 實際請求`curl 127.0.0.1`,輪詢返回8090

以上是對於流量調度這個大的topic的理解,限於篇幅,戰術性動作沒有展開,路漫漫其修遠兮,文辭拙劣,如果錯誤或者不同見解,歡迎留言探討。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章