Spring Cloud?Dubbo?還是K8s?
之前寫過關于微服務架構的文章,發現挺受歡迎的,所以今天打算再聊聊云原生和微服務架構。
圖片來自 包圖網
本篇分享主要圍繞以下 4 個主題進行:
- 什么是云原生?
- 為什么要用云原生架構?
- 微服務的概念
- 微服務的技術選型
什么是云原生?
①云計算和云原生
云計算不同于傳統的自建機房,云計算就是將計算的抽象為基礎設施然后通過網絡分發。
得益于云計算的無限擴展能力,使得“云計算”就像自來水廠一樣,我們可以隨時接水,并且不限量,按照自己家的用水量,付費給自來水廠就可以。
以下云計算的五個基本特征:
以下是一些目前比較主流的公有云廠商:
云原生顧名思義,就是基于云計算特性所設計的應用服務,得益于云計算快速發展,基于云計算特性所設計的云原生應用相比傳統的單體應用在安全性,擴展性,快速迭代,運維等各方便都有巨大的領先優勢。
云原生并不是指某一種技術,它是一種架構設計理念,只要符合這種架構設計理念的應用,都可以稱為云原生應用。
看看 CNCF 官方對于云原生的定義:
②容器云技術的發展
虛擬化技術的發展歷史
云原生是依賴容器作為技術技術來實現的,但是容器并不是什么新潮技術,以下是容器云技術的發展歷史,其中有幾個關鍵的歷史節點:
早在 2006 年的時候 Amazon 基于容器技術構建的 IaaS 平臺 AWS,成為所有云計算廠商的鼻祖,由于技術領先的優勢 AWS 現在依然也是云計算行業老大。
2013 年 Docker 的誕生進一步簡化容器技術的使用門檻,Docker 公司自以為掌握云時代的核心技術,開始野心勃勃的有意挑戰傳統的云計算大廠,例如 RedHat,Google 的江湖地位,公司股價也是一騎絕塵,卻不料被 RedHat 聯合 Google 發布的 Kubernetes 擊潰,Kubernetes 的成功讓大家以為容器技術并非云時代的核心技術,容器編排才是核心技術。(備注:2020 年 K8S 官方宣布只要滿足 K8S CRI 接口的容器均可以被 K8S 進行編排,Docker 被時代拋棄)
2015 年借助 Kubernetes 的成功,Google 宣布成立 CNCF 基金會,這是云原生時代的代表性的組織。致力于完善云時代的基礎設施,幫助開發者構建更出色的產品
下圖是 CNCF 的全景圖:
為什么用云原生架構?
主要從 4 個方面來聊聊:
- 自動恢復
- 服務安全
- 彈性擴展
- 快速發布
①自動恢復
早期剛參加工作的時候接手過一個年久失修的遺留系統,這個系統有一個很神奇的 Bug 每天晚上會自動宕機,誰也不知道什么原因。
只要重啟就能恢復正常,當時為了保證業務系統的正常使用,我總是在半夜爬起來重啟服務器,我當時就在想:要是有一種工具可以檢測到系統宕機后,就自動重啟恢復就好了,這樣我就可以睡一個好覺了。
這就是云原生架構想要解決的第一個問題:應用系統掛掉后,無需人工的介入,可以自動在最短的時間恢復來保證系統的健壯性。
當然除了未知的 Bug,還有詭異的異常會導致服務崩潰了,例如:
- 代碼沒寫好,系統發生 OOM
- 服務器本身的資源不足
- 死鎖,磁盤,網絡等問題
- 等等……
Kubernetes Pod 應用自動恢復的三種策略:
- Always:當容器終止退出后,總是重啟容器,默認策略。
- OnFailure:當容器異常退出(退出狀態碼非 0)時,才重啟容器。
- Never:當容器終止退出,從不重啟容器。
- spec:
- restartPolicy: Always # 當容器終止退出后,總是重啟容器,默認策略
- containers:
- - image: nginx
- name: web
②安全性
在微服務架構的大型分布式系統,服務和服務之間是通過熔斷建立安全的保護隔離機制。
云原生架構保障系統的安全性主要體現 2 個方面:
- 服務隔離
- 資源隔離
服務隔離:先來看看服務調用的安全隔離,如圖:
假如服務 A 和服務 B 之間存在依賴的調用關系,它的處理邏輯如下:
- 如果服務 B 宕機或者異常下線,注冊中心會發送服務 B 的狀態給服務 A,服務 A 就會啟動熔斷保護機制。
- 服務 A 采用降級策略或者不再發送向服務 B 發送請求,避免產生調用鏈雪崩,同時也保護服務 A 的可用性。
- 服務 B 再次被拉起的時候,服務 A 收到注冊中心對服務 B 的健康檢查,恢復對服務 B 的調用或者移除降級策略。
資源隔離:云原生架構對于服務的保護機制也體現在對資源的使用上,以前多套系統共享一臺主機的資源,總是容易出現木桶的短板效應。
就是只要有一個系統把主機資源占滿,那么其他的系統都會因為資源不足受到影響。進而產生連鎖反應,同主機上的所有系統都會崩潰。
現在基于容器部署的微服務系統,你的系統在生產環境的真實部署情況就像被關進一個個小房間里面,預先安排的資源設置就是這個服務房間的大小。
它只能在指定的大小范圍內活動,就算程序內部異常導致把資源全部占用,也不會影響其他房間的小伙伴的正常活動,從而保證整個系統的可用性。
通過 Kubernetes 指定內存請求和限制的 Pod 配置文件:
- spec:
- containers:
- - name: memory-demo-ctr
- image: polinux/stress
- resources:
- limits:
- memory: "200Mi" # 內存會被限制在 200 MiB 以內
- requests:
- memory: "100Mi" # 容器將會請求 100 MiB 內存
通過服務隔離,資源隔離的方式為云原生系統提供安全和可用性,這里僅僅做一個入門的介紹,如果展開來講的話,內容還有很多,有興趣的同學可以自行去研究和探索。
③彈性擴展
傳統的單體的應用,往往部署在機房的服務器主機內,那么自購的服務器難以應對業務快速增長,存在以下問題:
- 時間成本:采購服務器需要事先填好配置清單,走各種流程,等物流,等機器送到接上電源,估計 1~2 周都過去了。
- 空間成本:要騰出很大的空間來放置這些大家伙。
- 其他成本:24 小時開空調,專人輪班值守,機器的維護,服務下線后服務器容易閑置,閑魚不好出手等等。
在基于云計算的基本特征所設計的云原生系統,則不存在以上這些問題,在主流的公有云廠商提供 ECS 主機基本可以任意擴展和伸縮配置,在資源使用上也提供按量付費的運行模式,有效避免對于計算資源的限制和浪費。
如下圖:
④快速發布
隨著類似 Kubernetes 等云原生基礎設置的完善,現代應用的部署方式也跟以前大不相同。
相比傳統低效的停機發布,云原生服務提供的 Rolling Update 滾動升級幫我們實現不停機升級系統的目標,對于需要快速響應市場需求的企業,快速迭代的業務系統的功能對于企業取得市場競爭力顯得來說尤為重要。
KubernetesRollingUpdate 策略用于解決不停機發布的問題:
另外,我們可以通過 kubectl rollout undo 將 deployment 回滾到指定的版本,來解決微服務的快速回滾的問題。
以上就是云原生架構相比傳統系統所帶來的巨大優勢,我們目前也是處于云時代架構演進的早期。
我個人認為,我們程序員作為知識工作者非常值得投入時間去學習下一代的主流架構設計。這將為我們帶來巨大的技術優勢和技術領先。
微服務的概念
①微服務的理論基礎
微服務并不特指某一種具體的技術,它是一個抽象的概念,只要滿足它的所有規范,那么就可以理解為你的系統實現了微服務。
②何時用微服務?
關于你的項目何時應該引入微服務架構,行業一直有兩種聲音:
- 方案 A 單體優先:隨著架構的演進逐漸替換為微服務架構
- 方案 B 微服務優先:避免后期的大范圍架構重構
其實,早在 2015 年技術大牛 Martin Fowler 在博客文章 MicroservicePremium 中就給出了具備參考性答案:
早期(2015 年左右)微服務使用成本和上手門檻很高,生產效率不如單體應用。
但是伴隨系統的業務復雜度逐漸上升,單體應用的生產效率逐漸降低,在到達臨界點的時候微服務的優勢逐漸出現,微服務的生產效率開始超過單體應用。
所以在 2015 年的時候結合成本和收益的權衡,大多數人會選擇單體優先的架構方案,后續再逐步演化成為微服務。
③Netflix OSS 的誕生
早在 2015 年的 CNCF 基金會剛誕生,社區的微服務基礎設置非常不完善,Netflix+Pivotal 公司作為微服務的實踐的探索者,通過應用層面提供許多微服務的基礎組件來實現微服務架構。
關于 Netflix 提供的微服務全家桶解決方案稱作 Netflix OSS(Open Source Software Center)。
Netflix OSS 全景圖如下:
④微服務優先
Martin Fowler 在 2015 年提出的觀點,顯然已經不再適用 2021 的現代系統架構。
這幾年隨著 CNCF 的快速發展,云原生的基礎設施逐漸的完善和成熟,微服務的使用成本逐年降低,微服務的實現成本已經趨向于單體,甚至未來會優于單體。
我的個人看法是,微服務如果能夠解決使用和學習成本的問題,那么未來微服務也將完全取代單體應用。
從長期主義來說,任何新項目都應該優先選擇微服務架構,不僅可以保證業務系統的生產效率、擴展性,還可以避免未來產生大規模的重構。
微服務的技術選型
①微服務框架選擇
市面上微服務框架很多,目前行業的大公司基本都會有自己的微服務框架。
我們只看幾款主流并且具備代表性微服務框架:
- Dubbo(阿里巴巴)
- Spring Cloud(Netflix)
- Kubernetes(Google)
我們通過功能對比,看看都是如何根據自己的理解實現微服務的基本理論概念。
我們將主流框架從微服務的基礎關注點,運維架構,產品背景進行三方面維度的比較:
通過橫向對比,我們可以看到不論是 Dubbo 還是 Spring Cloud 對比 Kubernetes 都有諸多缺點。
相比阿里巴巴的 Dubbo、Netflix 的 Spring Cloud,Google 提供的 Kubernetes 才是具備完整的一站式的微服務解決方案的技術方案。
如下圖:
如果使用住房來比喻的話,前者就像毛坯房,還要自己裝修,Kubernetes 則是精裝修的商品房,幫你解決所有問題,拎包入駐即可。
另外,自建 Kubernetes 集群成本比較高,推薦使用公有云廠商提供的 Kubernetes 服務。
②微服務和網關
如果把分布式的微服務系統比喻成一家公司的話,那么網關就是該公司的前臺,當有用戶要訪問公司必須在前臺登記確認身份,疫情期間可能還需要量一下體溫什么的。
這一步驟就叫網關鑒權,根據用戶描述的任務和身上攜帶的證明,網關用戶的業務類型將用戶帶到所屬業務范圍內辦公室,這一步驟就叫做網關路由。
如果用戶太多一個前臺處理不過來,就會多開設幾個窗口來分流,這一步驟就叫做 網關層面的負載均衡。網關是微服務的大門,對于微服務至關重要。
以下是網關常見的工作方式:
除了上述的鑒權,動態路由,負載均衡,通過網關還可以實現以下高級特性:
- 網關限流(人太多,把門關起來,或者在門口排隊)
- 金絲雀發布(將小部分用戶帶到還未開放的新辦公場地去體驗一下)
- 彈性伸縮
網關是微服務的大門,因為網關對于對微服務來說至關重要,是微服務彈性伸縮的能力來源。
并且網關的開發成本其實并不高,所以市場面有很多單獨的網關產品,我們可以簡單看看,如圖:
③微服務和安全認證
早期分布式單體應用的會話管理:早期的單體應用用戶會話方案都是通過服務端存儲 sessionid+cookid+filter 來保存和管理用戶狀態會話。
但是這種有狀態服務有很多弊端,例如服務重啟用戶狀態丟失,難以橫向擴展等等,后單體應用時代大家開始把用戶會話狀態放在類似 Redis 等存儲中間件中,來解決系統的橫向擴展和重啟后會話不丟失的問題。
架構如圖:
微服務中基于 Auth 的認證方案:在的微服務體系中,身份認證模塊將被統一抽取出來交給單獨的服務處理,該服務通常稱為 Auth Service。
訪問令牌通常由 Auth 頒發,由網關統一鑒權,AuthService 身份認證職責的分離,可以讓微服務本身更加關注業務。
基于 Auth Service 的工作邏輯如圖:
不過這種基于 Auth 認證服務的方案會將所有請求發往 Auth 進行驗證,認證服務承受的壓力大,架構方案重,造成不必要的性能損失。其實大部分的應用系統都不需要這么嚴格的安全認證等級。
那么有沒有一種輕量級的技術是可以由認證服務頒發令牌后,不在需要依賴 Auth 鑒權,由服務自行驗證令牌的有效性,這樣就可以大大減少對 Auth 的鑒權請求。答案是有的。它就是目前非常流行的 JWT 鑒權方案。
JWT 結合 RBAC 角色權限模型是目前非常主流的輕量級認證方案。它的工作流程如下:
JWT 備受推崇,廣泛使用的原因,是因為它在由 Auth 服務頒發令牌后,在網關即可驗證令牌合法性,無需再請求認證服務,請求少,性能好。
令牌本身還可以自包含少量的用戶信息,JWT 大概是一串這樣的編碼,它由三個部分組成,你可以通過 JWT IO 這個網站對 JWT 進行解碼,從而獲取 JWT 中的信息:
JWT 的詳細生成和解碼過程就這里不在贅述了,JWT 并非沒有缺點,我們看看它的優缺點:
總結:RBAC 角色模型+JWT 鑒權方案是目前微服務主流的安全認證體系,也能應對大多數系統對于安全認證的需求,也是目前市面上大部分的企業應用生產中的最佳實踐。
④微服務的運維監控
生產就緒系統 Production Ready:說完了開發環節,最后來說說微服務是怎么運維的。
我們知道僅僅只是完成功能(Feature-Complete) 只是軟件開發流程中很少的一部分,那么從完成編碼到生產就緒(Production Ready),還需要經歷哪些環節?
我們可以參考上圖:
- 集成測試:用戶功能的準確性,性能和壓力測試。
- 日志管理:日志要規范,要區分:Info,Wrong,Error 等不同的等級,日志格式統一,方便日志收集,監控和排查。
- 監控預警:包含業務指標監控,應用指標監控,CPU,內存,磁盤網絡 IO 監控等等,設定合理的預警信息。
- 調用鏈監控:呈現分布式系統的調用關系,調用性能,找到性能瓶頸,快速定位問題。
- 高可用考量:雙機備份,主從備份,異地多活,容災策略,應用彈性機制等。
當我們確保應用滿足生產就緒(Production Ready)的要求,我們就可以發布到生產,交付價值了。
基于 EFK 的日志采集方案:基于容器部署的微服務架構不可能像傳統應用那樣通過 SSH 登錄服務器上扒日志信息,所以只能采取統一的收集機制。
Kubernetes 中推薦使用 EFK (Elasticsearch+Fluentd+Kibana)采集日志。
它的工作流程如上圖:
- Fluentd 會將采集的日志直接發到 ElasticSearch,中間也可以增加 kafka 作為緩存層。
- ElasticSearch 通過 Log Parser 初步解析日志,可以過濾垃圾日志。
- 通過 Kibana Dashboard 查詢 ElasticSearch 顯示日志。
分布式系統的服務監控方案:目前主流的微服務監控體系是通過 Kubernetes + Prometheus 來搭建。
如上圖:
- 通過 Prometheus 發現 Kubernetes 服務
- 通過 Alert Manager 監控和報警 Email,SMS
- 通過 Grafana 展現和監控服務的運行各項指標
基于 Skywalking 分布式鏈路跟蹤監控:Skywalking 是無侵入分布式鏈路跟蹤框架,可以在不添加一行代碼的前提下完成對微服務分布式系統的鏈路跟蹤,是目前主流的分布式鏈路跟蹤的解決方案。
2019 年 SkyWalking 成為 Apache 頂級項目,SkyWalking 的作者吳晟也因此當選為 Apache 軟件基金會首位華人董事,這里就不展開講了。
SkyWalking 工作大致工作原理如下:
SkyWalking 對分布式調用鏈的展示:
總結
本文從云原生的發展歷史,講述了我們程序員為什么要擁抱選擇云原生。講解了基于云計算的基礎底座所衍生出來的云原生系統對傳統單體應用所帶來的顛覆性改變,然后講述一些微服務的工作原理,架構布局和運維方案。
但是在真正生產級云原生應用中,遠遠不止要要考慮以上的內容,還有更多需要考慮的因素。
例如:
- HTTPS
- 編碼規范,測試覆蓋率,E2E 測試
- 監控:Log/Trace/Metrics,業務指標監控
- 持續集成:CI/CD 流水線
- 完善的 README 幫助文檔
更多細節就不展開講了,期待跟大家共同學習和交流,謝謝大家。
作者:肖斌2
編輯:陶家龍
來源:轉載自公眾號小二十七(ID:drak-phoenix)