使用容器技術來建立一個微服務架構
之前的博文中,我講解了Linux容器技術的相關實現,比如如何使用Docker來建立流線型的開發和測試體驗。因為可以實現跨不同類型基礎設施的兼容(比如,在AWS上,容器也可以如實體服務器上一樣輕松的運行),容器讓代碼的部署異常便捷。在實際工作中,測試和開發環境的細微不同很可能會導致應用程序的部署失敗;因此在這種情況下,對于開發和測試工作,容器技術可以讓開發者豁免很多預想之外的工作和相互推脫。
在本篇文章中,我們將討論是什么特性讓容器技術如此適應開發和測試工作,同樣適用于在AWS平臺上構建一個基于微服務的架構。對于Web應用程序來說,微服務架構可以讓應用程序的代碼庫更加敏捷,并且容易管理。下面,我們將介紹這個架構為何可以大幅提升開發者生產效率的原因,并了解它能夠快速迭代和擴充一個代碼庫的原理。對于快速發展中的創業公司來說,微服務架構可以讓開發團隊在研發過程中更加的敏捷和靈活。
Web開發簡史
首先,我們先簡潔地回顧下20年內基于Web開發的歷史,它可以讓我們知悉微服務架構為什么可以在Web開發領域如此的盛行,同時也順便了解這個架構可以解決的問題。
在Web應用程序開發的早期,應用程序通常使用Common Gateway Interface(CGI)建立,這個接口為網絡服務器提供了處理瀏覽器發來的HTTP請求時執行腳本(通常情況下用Perl編寫)的能力。CGI的擴展性非常很好,因為它需要為每個輸入請求都建立一個Perl進程。為了解決這個問題,那個時代的網絡服務器通常都會添加模塊化的支持。Apache,現下最為流行的網絡服務器之一,增加了“mod_perl”讓Perl代碼可以在內部運行,這樣一來,CGI腳本就可以在更少的時間內執行。
即使對比傳統的CGI類似mod_perl這些技術有了很大的提升,但仍然存在問題。也就是說,負責視圖層(比如,在HTML頁面上執行一個動態模塊)的代碼通常會被混入應用程序邏輯代碼中。這就意味著,完成一個簡單的任務,比如在HTML列表中增加一列,或者在form中增加一個元素,通常需要修改一個低等級的應用程序代碼。因此,Web程序開發技術下一個階段中衍生了“server pages”,它允許在HTML嵌入執行代碼。這樣一來,應用程序邏輯代碼與視圖代碼被很好的分離。在Java開發領域,一個被稱為“Model 2”的設計模式得以快速演變,在這里,應用程序代碼放到Java servlets中,數據則通過Java Beans進行,視圖層邏輯則使用了Java server pages,詳見下圖:
圖1:Model 2設計模型
隨后,在Java領域,“Model 2”模式在很短的時間就演化成了“Model-View-Controller(MVC)”框架,比如Apache Struts。而在其他領域,Ruby on Rails則非常盛行。在MVC模式中,控制器類會定義方法,通過“route”類映射成URL模式被調用。 控制器方法會利用“model”類封核心應用程序實體的業務邏輯和數據。最后,每個控制方法都會渲染一個“view”用于顯示,并修改相應模式類的方法。在這種模式下,業務、應用程序、視圖邏輯被很好的分離,如圖2:
圖2:MVC設計模型
REST協議的盛行
就在MVC被廣泛接受并成為網絡開發途徑的同時,進程間通信(IPC)也開始利用上了基于文本的序列化格式,比如XML和JSON。而在類似SOAP這些協議實現跨HTTP IPC的不久后,網絡開發已不再限制于給瀏覽器建立交付內容的應用程序,為其他程序執行操作和交付數據的網絡服務也逐漸走上歷史的舞臺。這種基于服務的架構擁有非常強大的功能,因為它消除了代碼庫共享的依賴性,從而開發者可以更進一步的解耦應用程序組件。而SOAP協議和相關的WS-*標準也變得越來越復雜,并更加依賴于應用程序服務器的實現,至此開發者開始投身更為輕量級的REST協議。同時,隨著移動設備的劇增,Web UX development逐漸走向AJAX和JavaScript框架,應用程序開發者開始廣泛使用REST在客戶端設備和網絡服務器之間做數據傳輸。
后來人們發現,MVC框架同樣非常適合開發REST端點。REST面向資源的特性被很好的映射成了控制器和模型理念,如圖3所示:
圖3:MVC的REST端點
Monolithic架構
因此,曾今由模型、視圖層、控制器組成,主要用于給應用程序交付HTML內容的MVC應用程序發生了本質上的變化——它們不僅可以支撐傳統的HTML,也可以通過REST端點來支撐JSON。應用程序被部署為一個單一的文件(比如Java)或者同一個目錄下的文件合集(比如Rails)。然而不容忽視的是,所有應用程序代碼都運行在相同的進程中。因此在縮放過程中,開發者需要將應用程序代碼的多個副本部署到多個所需的服務器上。下圖解析了Monolithic架構:
圖片4:Monolithic架構
在Monolithic架構中存在著很多的問題。首先,隨著應用程序的功能和服務越來越多,代碼將變得越來越復雜。對于新的開發者來說,這一點非常頭疼。新型集成開發環境在加載、編譯整個應用程序代碼時也可能存在問題,同時這個過程的耗時也可能非常長。此外,因為所有程序代碼都運行在服務器上的相同進程中,導致應用程序某個組成的擴展也非常難。如果某個服務是內存密集型的,而另一個是CPU密集型的,那么服務器必須有足夠的內存和CPU來滿足每個服務的需求。因此,鑒于每個服務器都使用非常高的CPU和內存,基礎設施的整體花費可能會非常高,特別是在縱向擴展策略下。最后非常微妙的是,應用程序的組成通常也會映射到研發團隊的結構上。UX工程師負責UI組件的建立,中間層開發者通常負責建立服務器端點,而數據庫工程師和DBA們則負責數據訪問組件和數據庫。如果某個UX工程師期望給增加一些顯示,他往往需要來自中間層和數據庫工程師的配合。就像水一樣,人們通常期望以最少的阻力執行,每個工程師也都期望為其負責的應用程序嵌入盡可能多的邏輯。鑒于這些問題,隨著時間的推移,代碼將越來越難以管理。
微服務架構
微服務架構的發明就是用來解決這些問題。定義在Monolithic架構應用程序中的服務將拆分成獨立的服務,它們在不同的主機上進行獨立的部署。
圖片5:微服務架構
每個微服務都對應了一個獨立的業務功能,也只定義了該功必須的一些操作。這聽起來比較類似面向服務架構(SOA),事實上,微服務架構和面向服務的架構確實有很多共同的特性。兩個架構都使用服務的模式組織代碼,兩種架構在不同的服務間都建立了非常明確的邊界。然而,面向服務的架構起源于Monolithic應用程序交互的需求,通常彼此都會提供一個API(基于SOAP)。在面向服務架構中,集成重度依賴于中間件,特別在企業服務總線(EBS)中。微服務架構通常會利用一個消息總線,但是無論任何情況在消息層都不會存在邏輯——它純粹的被用于服務之間的交互。這與ESB有著非常顯著的差別,ESB包含了大量邏輯——用于消息路由、模式驗證、消息翻譯和業務規則。因此,對比傳統的面向服務架構,微服務架構往往更為簡單,不會包含用于定義服務間接口的同級別控制和規范化數據建模。通過使用微服務,開發將非常快速,服務的衍變也只需匹配業務的需求。
微服務架構的另一個核心優勢就是服務可以基于資源的需求進行獨立擴展。取代運行包含大量CPU和內存的大服務器,微服務可以被部署在更小的主機上,這些主機只需要滿足其部署服務的需求。同時,開發者可以根據業務的需求選擇開發語言,比如:一個圖像處理服務可以使用類似C++這樣的高性能語言實現,一個執行數學或者靜態操作的服務可以使用Python實現,對資源進行增刪查改的基礎操作則往往通過Ruby進行。在微服務中,開發者并不需要考慮Monolithic架構中使用的“一刀切”模型——比如只使用MVC框架和單一的編程語言。
然而,不容忽視的是,微服務同樣存在一些劣勢。因為服務通常部署在多個主機上,很難持續跟蹤指定服務究竟運行在某臺主機上。同時,因為微服務架構使用的主機容量往往小于Monolithic架構,隨著微服務架構不停的橫向擴展,主機數量將以一個非常恐怖的速度增長。在AWS環境中,微服務架構中獨立服務需要的資源往往會小于最小的EC2實例類型。從而造成了超量配置并浪費開銷。此外,如果服務使用不同的編程語言將開發,這就意味著每個服務的部署都需要完全不同的庫和框架,從而服務的部署非常復雜。
容器的用武之地
Linux容器技術的使用可以很大程度上緩解微服務架構所帶來的問題。Linux容器技術使用了類似cnames和namespaces這樣的內核接口,它允許不同容器共享相同的內核,同時容器之間還進行了完全的隔離。Docker執行環境使用了一個被稱為libcontainer的模塊,它標準化了這些接口。Docker同樣為容器鏡像提供了一個類GitHub的資源庫DockerHub,讓容器的共享和發布非常簡單,也正是這種相同主機上的容器隔離簡易了不同語言開發的微服務代碼部署。使用Docker,我們可以創建一個DockerFile來描述所有用到的語言、框架和服務間庫的依賴性。舉個例子,下面代碼中的DockerFile可以用來定義一個微服務的Docker鏡像,它使用了Ruby和Sinatra框架:
FROM ubuntu:14.04
MAINTAINER John Doe <jdoe@example.com>
RUN apt-get update && apt-get install -y curl wget default-jre git
RUN adduser --home /home/sinatra --disabled-password --gecos ''
sinatra
RUN adduser sinatra sudo
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER sinatra
RUN curl -sSL https://get.rvm.io | bash -s stable
RUN /bin/bash -l -c "source /home/sinatra/.rvm/scripts/rvm"
RUN /bin/bash -l -c "rvm install 2.1.2"
RUN /bin/bash -l -c "gem install sinatra"
RUN /bin/bash -l -c "gem install thin"
使用這個鏡像建立的容器可以便捷地被部署到一個主機上,這個主機同時還運行了另一個使用Java和DropWizard 定義的Docker鏡像所建立的容器。容器執行緩解隔離了主機上運行的不同容器,因此不存在使用不同語言、庫和框架容器所造成的沖突問題。
同時值得高興的是,近期發布的Amazon EC2 Container Service(Amazon ECS)可以幫你搞定所有這些工作。使用Amazon ECS,你可以定義一個被稱為“cluster”的計算資源池,一個cluster由一個或以上的EC2實例組成。Amazon ECS負責管理集群中所有基于容器的應用程序,提供 telemetry和logging,并管理集群的容量優化,進行高效的任務調度。Amazon ECS提供了一個“任務內容(task definition)”的理念,它可以定義組成一個應用程序的一組容器。task definition中的每個容器都指定了該容器所需的資源,而Amazon ECS將基于集群中的可用資源來調度這個任務的執行。
微服務可以非常便捷地被定義為一個任務,它可以由兩個容器組成——一個負責運行服務終端代碼,另一個負責運行數據庫。Amazon ECS可以管理這些容器之間的依賴性,同時也可以跨集群進行資源平衡。同時,Amazon ECS還可以無縫的訪問多個AWS重點服務,比如Elastic Load Balancing、Amazon EBS、Elastic Network Interface和Auto Scaling。通過Amazon ECS,使用 Amazon EC2部署應用程序的所有基本特征都對基于容器的應用程序可用。
此外,類似Amazon ECS 這樣的容器解決方案還可以簡化“service discovery(服務搜尋)”這樣的實現。因為微服務往往會跨多個主機部署,并根據負載進行縮放,service discovery更有利于服務之間的定位。在最簡單的情況下,可以使用負載均衡器來進行,但是在更為復雜的環境中,一個真正的分布式配置服務非常有必要,比如Apache Zookeeper。使用Amazon ECS API,與類似Zookeeper這樣的第三方工具整合將非常容易。配置了Zookeeper的容器可以被添加到一個task definition中,并可以通過Amazon ECS在集群中的Amazon EC2調度執行。
從許多方面來看,使用容器技術實施微服務架構轉變都與過去20年Web開發的衍變非常類似。許多這些衍變都是為了更好的利用計算資源,以及更方便的維護越來越復雜的Web應用程序。如我們所見,使用Linux容器技術來實現微服務架構完全匹配了這兩個需求。在本文中,我們簡單地接觸了使用Amazon ECS來定義一個微服務架構,但是容器在分布式系統中的使用已經遠超過了微服務。在分布式系統中,越來越多的容器成為了first class citizens,而在未來的報告中,我將討論為什么 Amazon ECS對管理給予容器的計算是至關重要的。
責任編輯:售電衡衡
-
權威發布 | 新能源汽車產業頂層設計落地:鼓勵“光儲充放”,有序推進氫燃料供給體系建設
2020-11-03新能源,汽車,產業,設計 -
中國自主研制的“人造太陽”重力支撐設備正式啟運
2020-09-14核聚變,ITER,核電 -
探索 | 既耗能又可供能的數據中心 打造融合型綜合能源系統
2020-06-16綜合能源服務,新能源消納,能源互聯網
-
新基建助推 數據中心建設將迎爆發期
2020-06-16數據中心,能源互聯網,電力新基建 -
泛在電力物聯網建設下看電網企業數據變現之路
2019-11-12泛在電力物聯網 -
泛在電力物聯網建設典型實踐案例
2019-10-15泛在電力物聯網案例
-
權威發布 | 新能源汽車產業頂層設計落地:鼓勵“光儲充放”,有序推進氫燃料供給體系建設
2020-11-03新能源,汽車,產業,設計 -
中國自主研制的“人造太陽”重力支撐設備正式啟運
2020-09-14核聚變,ITER,核電 -
能源革命和電改政策紅利將長期助力儲能行業發展
-
探索 | 既耗能又可供能的數據中心 打造融合型綜合能源系統
2020-06-16綜合能源服務,新能源消納,能源互聯網 -
5G新基建助力智能電網發展
2020-06-125G,智能電網,配電網 -
從智能電網到智能城市