構建高性能微服務架構

傳統架構之痛

當前的時代稱爲互聯網的時代,互聯網應用的特色每每是,新型的應用迅速出現顛覆舊的商業模式,一旦商業模式稍有轉機便會有大量的廠商蜂擁而至,使得藍海變成紅海,通過短期的殘酷競爭,熱度每每持續較短期後,大量廠商退出市場,僅僅前二名到三名可以存活下來,最終這一波浪潮被下一波取代。咱們回想視頻網站,團購網站,社交網站,微博,打車,直播等,全都呈現這種模式。程序員

因此互聯網市場只有一招,天下武功,惟快不破。redis

當一種商業模式出現的時候,爲了迅速切入市場,佔領商業獻祭,快速驗證商業模式,每每軟件的設計會採起傳統的單體架構。數據庫

傳統的單體架構每每分三層,最下面一層是數據庫,中間是應用程序層,全部的商業邏輯都會在這一層,最上面是頁面。swift

若是商業模式比較成功,則應用會添加新的功能,一種方式是所有添加到原有的商業邏輯中,另外一種方式是開發一個全新的三層結構來支撐新的功能。緩存

 

因爲是單體結構,一方面應用層裏面的功能愈來愈多,如圖中一個功能變爲三個功能,未來可能三十個功能,另外一方面不少代碼和邏輯都不能複用,如圖中功能 2,每一個應用都有,這種功能常見的有認證模塊,消息的編碼和解碼模塊等。服務器

這種單體結構會帶來三方面靈活性比較差。網絡

第一,時間靈活性:應用快速迭代,縮短客戶需求到產品上線的時間。session

互聯網應用的需求隨時改變,於是應用開發的迭代速度要求會比較快,傳統的軟件可能半年或者一年發佈一個功能,而互聯網應用則可能每週都發布新的功能。並且互聯網產品會時常搞活動,好比雙十一,每次活動不可能提早很長時間策劃,從而給開發充分的產品週期。架構

然而單體結構的應用若是有了 30 個模塊,每一個模塊由兩到三我的負責,則修改的成本會很是的大,從開發人員看來,整個架構牽一髮動全身,每次修改必需要作好良好的前期設計,而且讓整個團隊評審,若是新的需求要改多個模塊,則代碼的管理和合並就成爲很大的問題。負載均衡

並且不管測試,聯調,上線,擴展,縮減,升級,回滾都須要從新搭建環境,須要配置軟件,須要進行迴歸測試,運維人員須要反覆的部署環境,並且沒法保證環境的一致性,任何一個環境配置的小問題,都有可能致使軟件使用有問題。

第二,空間靈活性:應用彈性伸縮,應對業務量忽然增加後較短期恢復。

互聯網應用每每是針對終端用戶的,終端用戶的行爲每每不如企業用戶那樣容易預測,終端用戶可能由於促銷,過節等因素致使訪問量的迅速的增加,當訪問遭遇峯值的時候,咱們但願應用能夠快速擴展。

然而對於單體架構,應用擴展的過程如萬丈高樓平地起,一層一層慢慢蓋。

若是部署在物理機上面,則還須要採購新的物理設備,若是有虛擬化平臺,則須要申請新的虛擬機,而且配置好網絡和存儲。然而僅僅一個空的虛擬機是沒有用的,上面什麼環境都沒有,接下來須要安裝應用環境,好比 Tomcat, Apache 等,而後就是將應用,頁面配置到應用環境中,尚未結束,新啓動的是一個獨立的系統,還須要將這個系統加入到當前的系統中,才能一塊兒承擔訪問量,例如加入到負載均衡器的配置裏面。這樣每部署一套都須要從頭來一遍,實在是運維人員的噩夢。

第三,管理靈活性:易部署,易遷移,服務發現,依賴管理,自動修復,負載均衡。

如今不少互聯網應用都須要多地,多機房部署,有時候會從一個機房遷移到另外一個機房,若是每次變更都如上面同樣從底層到頂層都作一遍,成本比較大,時間比較長。

當一個應用依賴於另外一個應用,被依賴的應該宕機以後,修復須要手動進行,從底層到頂層配置一遍,並且修復好的系統每每 IP 地址也變了,則依賴於此應用的全部應用都須要修改配置。

 

微服務化之路

要解決上面所述的三個問題,對應的有三個步驟。

第一步,去狀態化,從而實現程序的可擴展。

單體架構的程序每每不少數據是保存在內存裏面的,或者是本地文件系統的,例如用戶訪問的 session 數據,例如用戶上傳的照片。所謂的去狀態化,就是使得應用程序僅僅運行商業邏輯,而將數據的保存所有交給外部的存儲服務。內存裏面的數據能夠放在緩存 redis 裏面,結構化數據放在統一的數據庫服務裏面,文件存放在對象存儲裏面。這樣應用程序就變成了一個只有商業邏輯的應用,能夠隨時擴展。

這裏面有一個問題就是應用程序的狀態外置化了,放在統一的緩存,數據庫,對象存儲裏面了,但是應用程序宕機了是沒有問題了,再啓動一個就能夠,若是緩存,數據庫,對象存儲宕機了,數據不也是沒有了麼?

其實主流的開源的緩存 Redis,數據庫 MySQL,對象存儲 swift 等,他們設計的時候就是考慮了高可用和容災的狀況的,因此數據存儲的工做就應該讓專業的模塊來作這件事情,而應用程序應該關注在商業邏輯的實現,從而加速開發的速度。固然這些存儲模塊的維護則是另外的專業人士在作的,這部分人士是緩存的專家,數據庫的專家,對象存儲的專家,不須要懂商業邏輯。

第二步,容器化,可編排。

與傳統 IaaS 架構不一樣,容器提供的不只僅是基礎資源,而是將操做系統,應用運行環境以及代碼打包成一個不可修改的鏡像進行交付,容器的機制能夠保證不管在哪裏,何時運行,都能保持環境的一致性,也就是 Docker 所宣稱的「Build, Ship, and Run Any App, Anywhere(一次構建,隨處運行)」。

容器特別適合部署無狀態的服務,上一步的無狀態化,給容器化奠基了良好的基礎。

一個服務每每會包含多個組件,於是會封裝成爲多個容器,容器之間會有相互的依賴,相互的調用,Kubernetes 能夠實現服務的編排、自發現、自修復,使得複雜服務的部署變成了一次 API 調用。

如圖所示,Kubernetes 管理了相互依賴的四個服務,所有部署在容器裏面,分別運行在不一樣的機器上面。服務之間的調用經過服務名稱進行,而非固定 IP 進行,而服務名稱 Kubernetes 會管理起來。

當一臺服務器宕機的時候,服務 B 和服務 C 會被自動調度到另外兩臺機器上,因爲服務是無狀態的,因此沒有問題。然而服務 A 和服務 D 如何再找到服務 B 和服務 C 能,這兩個服務的物理主機變了,極可能 IP 也變了。實際上是沒有問題的,Kubernetes 會自動將服務名和對應的 IP 地址關聯起來,服務之間只要配置的是服務名,而非 IP 地址,就依然可以相互訪問。

有了容器和 Kubernetes 這兩個工具後,解決了管理複雜性的問題,可是須要專門的團隊和技術力量,去玩轉 Kubernetes。

第三步,DevOps,可迭代。

從前面的一張圖中,Dev 和 Ops,開發和運維之間隔着長長的流程,致使迭代速度很慢。DevOps 就是能夠加快迭代速度的一種方法。

然而如何讓開發直接進入到運維流程中呢?容器的鏡像不可改變性提供了方案。

Docker 能夠保證容器中的運行環境,業務代碼不管在哪一個環境都是一致的,惟一不一樣的是不一樣環境的不一樣配置,能夠經過環境變量注入的方式設置。有了這個模式,開發人員能夠從很早就使用容器鏡像的方式進行開發,而且以容器鏡像的方式交付給測試,測試使用一樣的鏡像獲得一樣的環境進行測試用例的執行,當決定發佈的時候,也肯定真正到了生產環境的時候,同測試環境是同樣的。這樣避免了環境不斷重複的部署過程。

容器鏡像能夠手動維護和交付,可是也能夠藉助 CICD 持續集成的工具,來監控代碼庫的更改,當有程序員提交代碼的時候,會觸發一個 hook,這個 hook 會調用 CI 工具,告知他代碼已經有更新了,能夠根據最新的代碼打成最新的鏡像,CI 工具根據配置好的 Dockerfile,將代碼打包成鏡像,上傳到鏡像庫,每次打鏡像都應該有新的版本,而不該該總使用 latest。

鏡像打好了之後,接下來 CD 的工具會將鏡像部署到測試環境,測試人員能夠就這個新的測試環境進行一輪測試,若是測試成功,則能夠告知線上管理人員,能夠更新新的版本。

線上管理人員在恰當的時間,使用編排工具,將容器鏡像的版本改成最新的版本,從而生產環境也就更新了。若是發現生產環境有問題,新的版本有 Bug,沒有問題,只要將鏡像改成上個版本的鏡像便可,能夠保證原來那個能用的版本,全部的配置和原來同樣,從而功能也同樣,實現了升級和回滾功能。

固然這套持續集成的工具和流程,須要開發人員和開發流程進行改進,才能夠順利使用。

小結

只須要逐步作到如下三步,就能夠實現微服務和快速交付:

  1. 去狀態化:將內存數據寫入緩存,將持久化數據寫入數據庫,將文件寫入對象存儲。
  2. 容器化:可彈性伸縮,自我修復,動態遷移。
  3. 微服務化:可快速迭代,持續集成。
相關文章
相關標籤/搜索