【ZStack】4.進程內服務

為了應對諸如驚人的操作開銷、重復的努力、可測試性等微服務通常面臨的挑戰,以及獲得諸如代碼解耦,易于橫向擴展等微服務帶來的好處,ZStack將所有服務包含在單個進程中,稱為管理節點,構建一個進程內的微服務架構。

動機

構建一個IaaS軟件是很難的,這是一個已經從市場上現存的IaaS軟件獲得的教訓。作為一個集成軟件,IaaS軟件通常需要去管理復雜的各種各樣的子系統(如:虛擬機管理器hypervisor,存儲,網絡,身份驗證等)并且需要組織協調多個子系統間的交互。例如,創建虛擬機操作將涉及到虛擬機管理模塊,存儲模塊,網絡模塊的合作。由于大多數IaaS軟件通常對架構考慮不夠全面就急于開始解決一個具體問題,它們的實現通常會演變成:

隨著一個軟件的不斷成長,這個鐵板一塊的架構(monolithic architecture)將最終變為一團亂麻,以至于沒有人可以修改這個系統的代碼,除非把整個系統從頭構建。這種鐵板一塊的編程問題是微服務可以介入的完美場合。通過劃分整個系統的功能為一個個小的、專一的、獨立的服務,并定義服務之間交互的規則,微服務可以幫助轉換一個復雜笨重的軟件,從緊耦合的、網狀拓撲架構,變成一個松耦合的、星狀拓撲的架構。


因為服務在微服務中是編譯獨立的,添加或者刪除服務將不會影響整個系統的架構(當然,移除某些服務會導致功能的缺失)。
微服務遠比我們已經討論的內容更多:微服務的確有很多引入注目的優點,尤其是在一個的開發運維 流程(DevOps process)中,當涉及到一個大機構的很多團隊時。我們不打算討論微服務的所有支持和反對意見,我們確定你可以在網上找到大量的相關文章,我們主要介紹一些我們認為對IaaS軟件影響深遠的特性。

問題

雖然微服務可以解耦合架構,但這是有代價的。閱讀Microservices - Not A Free Lunch!和Failing at Microservices會對這句話有更深的理解。在這里,我們重點強調一些我們認為對IaaS軟件影響重大的事情。

1. 難以定義服務的邊界和重復做功

創建Microservices架構的挑戰之一是決定應該把哪一部分的代碼定義為服務,一些是非常明顯的,比如說,處理主機部分的邏輯代碼可以被定義為一個服務。然而,管理數據庫交互的代碼非常難以決定應不應該被定義為服務。數據庫服務可以使得整個架構更加清晰明了,但是這樣會導致嚴重的性能下降。通常,類似于這樣的代碼可以被定義為庫,庫可以被各個服務調用。鑒于所有服務一般在互相隔離的目錄下開發和維護,創建一個給不同的單一的軟件提供接口的虛擬的庫,要求開發者必須具有良好的和各個不同組的開發者溝通協調的能力。綜上,服務很容易重復造輪子和導致不必要的重復做功。

2. 軟件難以部署、升級和維護

服務,尤其是那些分散在不同進程和機器上的,是難以部署和升級的。用戶通常必須去花費幾天甚至幾周去部署一個完整的可運行的系統,并害怕升級一個已經構建好的穩定的系統。盡管一些類似puppet的配置管理軟件一定程度上緩解了這個問題,用戶依舊需要克服陡峭的學習曲線去掌握這些配置工具,僅僅是為了部署或者升級一個軟件。管理一個云是非常困難的,努力不應該被浪費在管理這些原本應該使生活更輕松的軟件上。
服務的數量確實很重要:IaaS軟件通常有許許多多的服務。拿著名的openstack舉個例子,為了完成一個基礎的安裝你將需要:Nova, Cinder, Neutron, Horizon, Keystone, Glance。除了nova是在每臺主機都需要部署的,如果你想要4個實例(instances),并且每個服務運行在不同機器上,你需要去操縱20臺服務器。雖然這種人造的案例將不太可能真實地發生,它依舊揭示了管理相互隔離的服務的挑戰。

3. 零散的配置

運行在不同服務器上的服務,分別維護著它們散亂在系統各個角落的配置副本。在系統范圍更新配置的操作通常由臨時特定的腳本完成,這會導致由不一致的配置產生的令人費解的失敗。

4. 額外的監控努力

為了跟蹤系統的健康狀況,用戶必須付出額外的努力去監控每一個服務實例。這些監控軟件,要么由第三方工具搭建,要么服務自身維護,仍然受到和微服務面臨的問題所類似的問題的困擾,因為它們仍然是以分布式的方式工作的軟件。

5. 插件殺手

插件這個詞在微服務的世界中很少被聽到,因為每個服務都是運行在不同進程中一個很小的功能單元(function unit);傳統的插件模式(參考The Versatile Plugin System)目標是把不同的功能單元相互掛在一起,這在微服務看來是不可能的,甚至是反設計模式的。然而,對于一些很自然的,要在功能單元間強加緊密依賴的業務邏輯,微服務可能會讓事情變得非常糟糕,因為缺乏插件支持,修改業務邏輯可能引發一連串服務的修改。

所有的服務都在一個進程

意識到上述的所有問題,以及這么一個事實,即一個可以正常工作的IaaS軟件必須和所有的編排服務一起運行之后,ZStack把所有服務封裝在單一進程中,稱之為管理節點。除去一些微服務已經帶來的如解耦架構的優點外,進程內的微服務還給了我們很多額外的好處:

1. 簡潔的依賴

因為所有服務都運行在同一進程內,軟件只需要一份支持軟件(如:database library, message library)的拷貝;升級或改變支持庫跟我們對一個單獨的二進制應用程序所做的一樣簡單。

2. 高可用,負載均衡和監控

服務可以專注于它們的業務邏輯,而不受各種來自于高可用、負載均衡、監控的干擾,這一切只由管理節點關心;更進一步,狀態可以從服務中分離以創建無狀態服務,詳見ZStack's Scalability Secrets Part 2: Stateless Services。

3. 中心化的配置

由于在一個進程中,所有的服務共享一份配置文件——zstack.properties;用戶不需要去管理各種各樣的分散在不同機器上的配置文件。

4. 易于部署、升級、維護和橫向擴展

部署,升級或者維護一個單一的管理節點跟部署升級一個單一的應用程序一樣容易。橫向擴展服務只需要簡單的增加管理節點。

5. 允許插件

因為運行在一個單一的進程中,插件可以很容易地被創建,和給傳統的單進程應用程序添加插件一樣。
進程內的微服務并不是一個新發明: 早在90年代,微軟在COM(Component Object Model)中把server定義為遠程、本地和進程內三種。這些進程內的server是一些DLLs,被應用程序在同一進程空間內加載,屬于進程內的微服務。Peter Kriens在四年前就聲稱已經定義了一種總是在同一進程內通信的服務,OSGi μservices。

服務樣例

在微服務中,一個服務通常是一個可重復的業務活動的邏輯表示,是無關聯的、松耦合的、自包含的,而且對服務的消費者而言是一個“黑盒子”。簡單來說,一個傳統的微服務通常只關心特定的業務邏輯,有自己的API和配置方法,并能像一個獨立的應用程序一樣運行。盡管ZStack的服務共享同一塊進程空間,它們擁有這些特點中的絕大多數。ZStack很大程度上是一個使用強類型語言java編寫的項目,但是在各個編排服務之間沒有編譯依賴性,例如:計算服務(包含VM服務、主機服務、區域服務、集群服務)并不依賴于存儲服務(包含磁盤服務、基礎存儲服務、備份存儲服務、磁盤快照服務等),雖然這些服務在業務流程中是緊密耦合的。
在源代碼中,一個ZStack的服務并不比一個作為一個獨立的jar文件構建的maven模塊多任何東西。每一個服務可以定義自己的APIs、錯誤碼、全局配置,全局屬性和系統標簽。例如KVM的主機服務擁有自己的APIs(如下所示)和各種各樣的允許用戶自己定義配置的方式。

<?xml version="1.0" encoding="UTF-8"?>
<service xmlns="http://zstack.org/schema/zstack">
    <id>host</id>
    <message>
        <name>org.zstack.kvm.APIAddKVMHostMsg</name>
        <interceptor>HostApiInterceptor</interceptor>
        <interceptor>KVMApiInterceptor</interceptor>
    </message>
</service>

通過全局配置來配置

備注:這里只簡單展示一小部分,用戶可以使用API去更新/獲取全局配置,在這里展示一下全局配置的視圖。

<?xml version="1.0" encoding="UTF-8"?>
<globalConfig xmlns="http://zstack.org/schema/zstack">
    <config>
        <category>kvm</category>
        <name>vm.migrationQuantity</name>
        <description>A value that defines how many vm can be migrated in parallel when putting a KVM host into maintenance mode.(當一個KVM主機變成維護模式的時候,這里的值定義了可以被并發遷移的虛擬機的數量)</description>
        <defaultValue>2</defaultValue>
        <type>java.lang.Integer</type>
    </config>

    <config>
        <category>kvm</category>
        <name>reservedMemory</name>
        <description>The memory capacity reserved on all KVM hosts. ZStack KVM agent is a python web server that needs some memory capacity to run. this value reserves a portion of memory for the agent as well as other host applications. The value can be overridden by system tag on individual host, cluster and zone level(所有的KVM主機預留的內存容量。ZStack中的KVM代理運行時是一個需要一部分內存容量去運行的python的web服務器,這個值為代理和其他主機應用程序預留了一部分內存,在單一主機上的、集群上的、區域上的系統標簽可以覆蓋這個值)</description>
        <defaultValue>512M</defaultValue>
    </config>
</globalConfig>

通過全局屬性配置

備注:以下代碼對應zstack.properties文件夾中相應的屬性

@GlobalPropertyDefinition
public class KVMGlobalProperty {
    @GlobalProperty(name="KvmAgent.agentPackageName", defaultValue = "kvmagent-0.6.tar.gz")
    public static String AGENT_PACKAGE_NAME;
    @GlobalProperty(name="KvmAgent.agentUrlRootPath", defaultValue = "")
    public static String AGENT_URL_ROOT_PATH;
    @GlobalProperty(name="KvmAgent.agentUrlScheme", defaultValue = "http")
    public static String AGENT_URL_SCHEME;
}

通過系統標簽配置

備注:以下代碼對應數據庫中相應的系統標簽。

@TagDefinition
public class KVMSystemTags {
    public static final String QEMU_IMG_VERSION_TOKEN = "version";
    public static PatternedSystemTag QEMU_IMG_VERSION = new PatternedSystemTag(String.format("qemu-img::version::%s", QEMU_IMG_VERSION_TOKEN), HostVO.class);

    public static final String LIBVIRT_VERSION_TOKEN = "version";
    public static PatternedSystemTag LIBVIRT_VERSION = new PatternedSystemTag(String.format("libvirt::version::%s", LIBVIRT_VERSION_TOKEN), HostVO.class);

    public static final String HVM_CPU_FLAG_TOKEN = "flag";
    public static PatternedSystemTag HVM_CPU_FLAG = new PatternedSystemTag(String.format("hvm::%s", HVM_CPU_FLAG_TOKEN), HostVO.class);
}

載入服務

服務在Spring的bean的xml文件中聲明自身,例如,kvm的部分聲明類似于:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:zstack="http://zstack.org/schema/zstack"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://zstack.org/schema/zstack
    http://zstack.org/schema/zstack/plugin.xsd"
    default-init-method="init" default-destroy-method="destroy">

    <bean id="KvmHostReserveExtension" class="org.zstack.kvm.KvmHostReserveExtension">
        <zstack:plugin>
            <zstack:extension interface="org.zstack.header.Component" />
            <zstack:extension interface="org.zstack.header.allocator.HostReservedCapacityExtensionPoint" />
        </zstack:plugin>
    </bean>

    <bean id="KVMHostFactory" class="org.zstack.kvm.KVMHostFactory">
        <zstack:plugin>
            <zstack:extension interface="org.zstack.header.host.HypervisorFactory" />
            <zstack:extension interface="org.zstack.header.Component" />
            <zstack:extension interface="org.zstack.header.managementnode.ManagementNodeChangeListener" />
            <zstack:extension interface="org.zstack.header.volume.MaxDataVolumeNumberExtensionPoint" />
        </zstack:plugin>
    </bean>

    <bean id="KVMSecurityGroupBackend" class="org.zstack.kvm.KVMSecurityGroupBackend">
        <zstack:plugin>
            <zstack:extension interface="org.zstack.network.securitygroup.SecurityGroupHypervisorBackend" />
            <zstack:extension interface="org.zstack.kvm.KVMHostConnectExtensionPoint" />
        </zstack:plugin>
    </bean>  

    <bean id="KVMConsoleHypervisorBackend" class="org.zstack.kvm.KVMConsoleHypervisorBackend">
        <zstack:plugin>
            <zstack:extension interface="org.zstack.header.console.ConsoleHypervisorBackend"/>
        </zstack:plugin>
    </bean>  

    <bean id="KVMApiInterceptor" class="org.zstack.kvm.KVMApiInterceptor">
        <zstack:plugin>
            <zstack:extension interface="org.zstack.header.apimediator.ApiMessageInterceptor"/>
        </zstack:plugin>
    </bean>  
</beans>

管理節點,作為所有服務的容器,將在啟動階段讀取它們的XML配置文件,載入每一個服務。

總結

在這篇文章中,我們演示了ZStack的進程內微服務架構。通過使用它,ZStack擁有一個非常干凈的,松耦合的代碼結構,這是創建一個強壯IaaS軟件的基礎。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,908評論 6 541
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,324評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,018評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,675評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,417評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,783評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,779評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,960評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,522評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,267評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,471評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,009評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,698評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,099評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,386評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,204評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,436評論 2 378

推薦閱讀更多精彩內容

  • 轉載本文需注明出處:微信公眾號EAWorld,違者必究。 微服務架構現在是談到企業應用架構時必聊的話題,微服務之所...
    72a1f772fe47閱讀 3,482評論 0 38
  • 微服務最近非常流行,各大互聯網公司紛紛采用微服務架構體系,微服務架構模式正在為敏捷部署以及復雜企業應用實施提供巨大...
    Sting閱讀 9,106評論 0 57
  • “微服務架構”這一術語在前幾年橫空出世,用于描述這樣一種特定的軟件設計方法,即以若干組可獨立部署的服務的方式進行軟...
    ThoughtWorks閱讀 16,944評論 1 71
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,823評論 18 139
  • 一、微服務將變得輕量級 架構需要由人去設計,這些人被稱為架構師。或許很多人并未授予架構師的頭銜,但自己卻從事著架構...
    justmilkrain閱讀 5,442評論 10 109