歡迎光臨
每天分享高質量文章

網易訊息推送系統微服務化實踐

微服務架構是一種架構樣式,它提倡將單一應用程式劃分成一組小的服務,服務之間相互協調、互相配合,為使用者提供最終價值。每個服務執行在其獨立的行程中,服務和服務之間採用輕量級的通訊機制相互溝通。每個服務都圍繞著具體的業務進行構建,並且能夠被獨立的部署到生產環境、類生產環境等。
微服務加上如今的服務發現,在基礎設施即程式碼(指使用指令碼配置計算基礎設施,而不是手動配置計算機的方法)的過程中,我們正在不斷的嘗試各種實踐方案。如何在雲基礎設施下結合業務場景,透過負載均衡、服務發現、容器化來實現業務鏈自動化,這就是本文給大家帶來的分享。
背景介紹

 

困擾和煩惱
首先來看下我們其中一個平臺之前的大體架構:
隨著業務的遞增,我們遇到了以下的問題:
  • 在非雲環境下,為了節省資源,當前只能透過業務混布的方式提高資源利用率,但這種方式可能會導致業務之間互相影響,不能進行有效的隔離,並無法實現資源最大化利用;

  • 由於每個業務都要使用獨立一套資源進行隔離,一個業務的上下線至少需要進行 10-15 個步驟來完成;

  • 靜態的配置導致多個服務互相依賴時,每次服務 A 變更需要通知依賴服務 B 進行變更,變更維護等一系列的流程變得成本越來越高;

     

  • 混布業務的機器異常會導致上面的 N 個服務受影響,需要人工介入花費大量時間確保服務恢復正常,故障自動恢復程度不高;

     

  • 變更所帶來的資料資訊變動需要額外的機制來保證實時更新,保證產品的穩定性。

 

新思路和改進

 

  • 容器化部署:首先我們將服務透過程式設計化,指定 CPU、MEM、DISK 等等一些列引數配置我們的基礎系統環境,利用映象批次建立 N 個 Docker 容器(微服務化的同時,我們透過程式設計化的方式來解決硬體基礎設定的利用率提升問題)。

  • 服務發現:在容器建立時的 IP 隨機分配時,在頻繁的建立銷毀過程中,如何讓各個服務之間實現自動快速的通訊?這裡我結合了 Consul 的域名服務發現功能,能夠在 1 分鐘左右實現從容器銷毀 –> 容器新建 —> 服務恢復可用,整個過程自動完成,保證容器本身和其它容器互相訪問的一個正常通訊。

什麼是服務發現?
在分散式微服務架構中,一個應用可能由一組職責單一化的服務組成。這時候就需要一個註冊服務的機制,註冊某個服務或者某個節點是可用的,還需要一個發現服務的機制來找到哪些服務或者哪些節點還在提供服務。
在實際應用中,通常還都需要一個配置檔案告訴我們一些配置資訊,比如資料連線的地址,Redis 的地址等等。但很多時候,我們想要動態地在不修改程式碼的情況下得到這些資訊,並且能很好地管理它們。
然而,服務發現元件記錄了(大規模)分散式系統中所有服務的資訊,其它服務可以據此找到這些服務。DNS 就是一個簡單的例子。當然,複雜系統的服務發現元件要提供更多的功能,例如,服務元資料儲存、健康監控、多種查詢和實時更新等。服務發現是支撐大規模 SOA 的核心服務。
Consul 介紹
Consul 是一個支援多資料中心分散式高可用,用於服務發現和配置共享的開源工具。它具有開箱即用、可跨系統平臺部署(在任何基礎架構上連線任何應用)等特點。Consul 的三個主要應用場景:服務發現、服務隔離、服務配置。Consul 關鍵特性:
  • 多資料中心

  • 服務發現

  • 健康檢查

  • Key/Value 儲存

  • 執行時編排 (Consul Template)

  • Web UI

Consul 之服務發現
  • 透過 HTTP 和 DNS 進行服務發現簡化了跨分散式基礎架構部署的連線服務。

  • 通訊方式從以往的 ip:port 向域名 :port 的轉變。

  • 變更(新增/縮減等)的服務會實時自動更新域名解析地址,即 Consul 內部域名保持實時解析最新的可用服務地址。

  • 具有服務健康檢查、心跳檢測、服務域名等等一系列可自定義特性。

 

Consul 之服務配置
首先 Consul 叢集內的所有資料都是可共享的,任何一個節點都是可以同時獲取到叢集內最新的資料資訊。然後透過一些例如 Key/Value、Server、Node 等等資料進行文字內容渲染,從而達到一個變更的全程實時自動化。例如根據 Key/Value 資訊渲染:
  1. #For example:
  2. {{ range tree "service/redis" }}
  3. {{ .Key }}:{{ .Value }}{{ end }}
  4. #renders
  5. minconns 2
  6. maxconns 12
  7. nested/config/value "value"
例如根據服務資訊渲染:
  1. #For example:
  2. {{ range service "web" }}
  3. server {{ .Name }}{{ .Address }}:{{ .Port }}{{ end }}
  4. #renders the IP addresses of all healthy nodes with a logical service named "web":
  5. server web01 10.5.2.45:2492
  6. server web02 10.2.6.61:2904
在傳統運維方式上可以有哪些改變
  • Consul 讓服務具有較強的可擴充套件性,根據其動態的服務註冊和健康檢測,可以使服務被頻繁替換時,避免服務中斷。

  • Consul 讓配置檔案管理變得更加輕鬆,不用經過 CMDB 和多個變更流程實現,配置內容跟隨業務進行實時自動變化調整。

傳統方式如何向微服務化轉變

 

入口的動態自動化
容器和服務發現始終只是在對內部的通訊實現,如何將這些服務快速方便的對外實現通訊,並且能夠高度自動化呢?我們透過將 HA 作為各類後端服務的對外統一入口;配置 backend 服務時,配置的是 Consul 中的服務域名。從而作為內部和外部通訊的一個通訊轉發樞紐。
HA 的域名動態解析
首先看看容器化下的服務地址是怎樣透過 Consul 完成變更的。
  1. 容器新建 or 銷毀等操作頻繁,IP 地址隨機生成分配一個。

  2. 每個服務有一個 Consul 域名,對應一個容器的 IP 地址,進行服務地址註冊。

  3. 容器重建後,Consul 的域名對應的 IP 重新註冊,掃清服務地址,Consul DNS域名解析會立即發生更新變化,對外完成變更。

 
然後為什麼是 HA 的 DNS 動態解析?這個不是 DNS 的鍋麼?
在常見的程式碼更新、服務配置變更、遷移、擴容等需要容器重建時,會導致 N 個容器同時發生 Consul 域名解析變更(當然也是預期內的變更),這個時候需要使用了 Consul 域名的服務在訪問失敗時能夠去重新解析一次域名獲取新的 IP,完成解析的自動變更。
需要註意的是這裡有個坑,原來使用 HAProxy 1.5 版本,後端服務配置使用域名時,啟動服務後只解析一次(和 Nginx 類似)域名,這時如果已解析的服務掛掉或進行了切換等,即使異常節點已遮蔽,訪問 HA 時依然會出現例如 503 等異常(即使 DNS 已經發生了改變,但 HA 服務本身快取了舊 IP 等於地址未更新)。後續查詢官網得知 HAProxy 1.6+ 才支援了動態DNS。
如何利用 HA 的域名解析配置實現後端路由動態化
首先,HA配置增加一段 resolvers 定義,用來實現 HA 的域名動態解析。
  1. resolvers consuldns
  2. nameserver dns1 127.0.0.1:53
  3. resolve_retries 200
  4. timeout retry 1s
  5. hold valid 10s
其次,對不同業務環境隔離的路由分發,同樣需要增加 HA 的 frontend 配置進行流量隔離。
  1. #自定義服務監聽相關邏輯
  2. frontend serverA
  3. balance leastconn
  4. cookie JSESSIONID prefix
  5. bind 0.0.0.0:1000 accept-proxy
  6. capture request essay-header Host len 128
  7. option httplog
  8. log-format %si:%sp\ %ci\ %ft\ %hrl\ %r\ %ST\ %B\ %Tt
  9. #自定義ACL(路由)策略
  10. acl host_hostname1 hdr_dom(host) -i a.test.com
  11. acl host_hostname2 hdr_dom(host) -i b.test.com
  12. use_backend hostname1 if host_hostname1
  13. use_backend hostname2 if host_hostname2
最後,在 HA 的 backend 處取用前面定義的 resolvers 和 frontend,實現到後端RS的動態轉發。
  1. #自定義轉發的rs地址,採用consul域名配置,利用自定義resolvers consuldns進行動態解析,從而保證後端服務自動化變更的靈活性。
  2. backend hostname1
  3. server hostname1 a.service.consul:1000 resolvers consuldns maxconn 50000 check inter 2000 rise 2 fall 100
  4. backend hostname2
  5. server hostname2 b.service.consul:1000 resolvers consuldns maxconn 50000 check inter 2000 rise 2 fall 100
  6. .........
WEB 配置內容自動託管
檔案內容更新:使用 Consul 的 K/V watch 功能,一旦有新服務上線/下線時,配置自動化接入和自動化下線流程,更新 Web 服務配置並 reload(觸發指令碼完成),完成整個流程的自動化。
  1. #當監控的key狀態發生變化時,觸發執行指定的自定義指令碼。
  2. /usr/local/bin/consul watch -type=key -key=key 自定義觸發的指令碼路徑。
  3. #當監控的key狀態發生變化時,實時渲染配置檔案,並執行reload。
  4. consul-template -consul-addr 127.0.0.1:8500 -template "ha.conf.ctmpl:ha.conf:HA reload"
後端服務自動加入叢集
雲主機節點自動初始化自身後進行服務註冊,自動匯入流量。
  1. #web_service.json
  2. {
  3. "service": {
  4. "name": "web",
  5. "port": 80,
  6. "id": "web",
  7. "address": "10.1.1.1",
  8. "check": {
  9. "id": "web",
  10. "name": "tcp",
  11. "tcp": "10.1.1.1:80",
  12. "interval": "60s",
  13. "timeout": "30s"
  14. }
  15. }
  16. }
  17. #nslookup web.service.consul
  18. Server: 127.0.0.1
  19. Address: 127.0.0.1#53
  20. Name: web.service.consul
  21. Address: 10.1.1.1
  22. Name: web.service.consul
  23. Address: 10.1.1.2
  24. Name: web.service.consul
  25. Address: 10.1.1.3
總結

 

總的來說,我們根據業務特性,使用 HA、Consul、Docker 這樣的一個組合來實現高度可擴充套件性、穩定性,及流程的基本全自動化過程。
業務鏈高度自動化,從上線到下線,整個流程包括服務上線、配置變更、產品釋出、功能迭代、下線回收等全自動銜接完成。
  1. 利用雲特性解決不同業務之間的資源隔離問題,並根據服務效能分配 CPU、Mem、disk 等實現硬體基礎資源程式設計化。

  2. 整套業務拆分,微服務化,每個服務一個 Docker 實體,故障自動漂移恢復,透過服務發現實現自愈,去掉人工介入環節。

  3. 利用 Consul 解決服務模組的擴充套件性,根據其動態的服務註冊和健康檢測功能,在避免服務中斷的情況下,可以接受服務的頻繁變更。

  4. 利用 HA 統一我們的入口,容器化後的服務,變更時產生的容器銷毀&建立導致服務地址變更時,HA 和 Consul 是實時監控服務心跳,自動更新 DNS 解析,整套環境高度自動化。

整個過程至少實現了:
  • 服務依賴解耦

  • 配置檔案的動態自動化變更

  • 產品的自動釋出

  • 服務故障自愈

  • 不斷簡化的流程和中間層

  • HA 代理的弱化與替代

  • 基礎設施雲化,利用率提升

  • 去掉了 90% 的人工參與過程

現在(圖 A)和原有(圖 B)對比如下:
作者:丁易鋒,網易遊戲資深運維工程師,主要工作方向為網易遊戲專案運維支援。專註於運維技術的突破,以及為產品提供更加高質量和便捷的服務支撐。
已同步到看一看
贊(0)

分享創造快樂