基于微服務架構,改造企業核心系統之實踐

jopen 9年前發布 | 39K 次閱讀 微服務 軟件架構

1. 背景與挑戰

隨著公司國際化戰略的推行以及本土業務的高速發展,后臺支撐系統已經不堪重負。在吞吐量、穩定性以及可擴展性上都無法滿足日益增長的業務需求。對于 每10萬元額度的合同,從銷售團隊準備材料、與客戶簽單、遞交給合同部門,再到合同生效大概需要3.5人天。隨著業務量的快速增長,簽訂合同的成本急劇增 加。

合同管理系統是后臺支撐系統中重要的一部分。當前的合同系統是5年前使用.NET基于SAGE CRM二 次開發的產品。 一方面,系統架構過于陳舊,性能、可靠性無法滿足現有的需求。另一方面,功能繁雜,結構混亂,定制的代碼與SAGE CRM系統耦合度極高。由于是遺留系統,熟悉該代碼的人早已離職多時,新團隊對其望而卻步,只能做些周邊的修補工作。同時,還要承擔著邊補測試,邊整理邏 輯的工作。

基于微服務架構,改造企業核心系統之實踐

 

在無法中斷業務處理的情況下,為了解決當前面臨的問題,團隊制定了如下的策略:

1). 在現有合同管理系統的外圍,構建功能服務接口,將系統核心的功能分離出來。

2). 利用這些功能服務接口作為代理,解耦原合同系統與其調用者之間的依賴;

 

3). 通過不斷構建功能服務接口,逐漸將原有系統分解成多個獨立的服務。

4). 摒棄原有的合同管理系統,使用全新構建的(微)服務接口替代。

2. 什么是微服務

多年來,我們一直在技術的浪潮中不斷乘風破浪,揚帆奮進,尋找更好的方式構建IT系統。微服務架構(Micro Service Architect)是近一段時間在軟件體系架構領域里出現的一個新名詞。它通過將功能分解到多個獨立的服務,以實現對解決方案或者復雜系統的解耦。

微服務的誕生并非偶然: 領域驅動設計指導我們如何分析并模型化復雜的業務;敏捷方法論幫助我們消除浪費,快速反饋;持續交付促使我們構建更快、更可靠、更頻繁的軟件部署和交付能力;虛擬化和基礎設施自動化( Infrastructure As Code)則幫助我們簡化環境的創建、安裝;DevOps文化的流行以及特性團隊的出現,使得小團隊更加全功能化。這些都是推動微服務誕生的重要因素。

實際上,微服務本身并沒有一個嚴格的定義。不過從業界的討論來看,微服務通常有如下幾個特征:

小,且專注于做一件事情

每個服務都是很小的應用,至于有多小,是一個非常有趣的話題。有人喜歡100行以內,有人贊成1000行以內。數字并不是最重要的。仁者見仁,智者 見智,只要團隊覺得合適就好。只關注一個業務功能,這一點和我們平常談論的面向對象原則中的”單一職責原則”類似,每個服務只做一件事情,并且把它做好。

運行在獨立的進程中

每個服務都運行在一個獨立的操作系統進程中,這意味著不同的服務能被部署到不同的主機上。

輕量級的通信機制

服務和服務之間通過輕量級的機制實現彼此間的通信。所謂輕量級通信機制,通常指基于語言無關、平臺無關的這類協議,例如XML、JSON,而不是傳統我們熟知的Java RMI或者.Net Remoting等。

松耦合

不需要改變依賴,只更改當前服務本身,就可以獨立部署。這意味著該服務和其他服務之間在部署和運行上呈現相互獨立的狀態。

綜上所述,微服務架構采用多個服務間互相協作的方式構建傳統應用。每個服務獨立運行在不同的進程中,服務與服務之間通過輕量的通訊機制交互,并且每個服務可以通過自動化部署方式獨立部署。

3.微服務的優勢

相比傳統的單塊架構系統(monolithic),微服務在如下諸多方面有著顯著的優勢:

異構性

問題有其具體性,解決方案也應有其針對性。用最適合的技術方案去解決具體的問題,往往會事半功倍。傳統的單塊架構系統傾向采用統一的技術平臺或方案來解決所有問題。而微服務的異構性,可以針對不同的業務特征選擇不同的技術方案,有針對性的解決具體的業務問題。

對于單塊架構的系統,初始的技術選型嚴重限制將來采用不同語言或框架的能力。如果想嘗試新的編程語言或者框架,沒有完備的功能測試集,很難平滑的完 成替換,而且系統規模越大,風險越高。基于微服務架構,使我們更容易在遺留系統上嘗試新的技術或解決方案。譬如說,可以先挑選風險最小的服務作為嘗試,快 速得到反饋后再決定是否試用于其他服務。這也意味著,即便對一項新技術的嘗試失敗,也可以拋棄這個方案,并不會對整個產品帶來風險。

基于微服務架構,改造企業核心系統之實踐

該圖引用自Martin Fowler的Microservices一文

獨立測試與部署

單塊架構系統運行在一個進程中,因此系統中任何程序的改變,都需要對整個系統重新測試并部署。 而對于微服務架構而言,不同服務之間的打包、測試或者部署等,與其它服務都是完全獨立的。對某個服務所做的改動,只需要關注該服務本身。從這個角度來說, 使用微服務后,代碼修改、測試、打包以及部署的成本和風險都比單塊架構系統降低很多。

按需伸縮

單塊架構系統由于單進程的局限性,水平擴展時只能基于整個系統進行擴展,無法針對某一個功能模塊按需擴展。 而服務架構則可以完美地解決伸縮性的擴展問題。系統可以根據需要,實施細粒度的自由擴展。

錯誤隔離性

微服務架構同時也能提升故障的隔離性。例如,如果某個服務的內存泄露,只會影響自己,其他服務能夠繼續正常地工作。與之形成對比的是,單塊架構中如果有一個不合格的組件發生異常,有可能會拖垮整個系統。

團隊全功能化

康威定律(Conway’s law)指出:一個組織的設計成果,其結構往往對應于這個組織中的溝通結構(organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations)。傳統的開發模式在分工時往往以技術為單位,比如UI團隊、服務端團隊和數據庫團隊,這樣的分工可能會導致任何功能上的改變 都需要跨團隊溝通和協調。而微服務則倡導圍繞服務來分工,團隊需要具備服務設計、開發、測試到部署所需的所有技能。

4. 微服務快速開發實踐

隨著團隊對業務的理解加深和對微服務實踐的嘗試,數個微服務程序已經成功構建出來。不過,問題同時也出現了:對于這些不同的微服務程序而言,雖然具 體實現的代碼細節不同,但其結構、開發方式、持續集成環境、測試策略、部署機制以及監控和告警等,都有著類似的實現方式。那么如何滿足DRY原則并消除浪費呢?帶著這個問題,經過團隊的努力,Stencil誕生了。 Stencil是一個幫助快速構建Ruby微服務應用的開發框架,主要包括四部分:Stencil模板、代碼生成工具,持續集成模板以及一鍵部署工具。

基于微服務架構,改造企業核心系統之實踐

Stencil模板

Stencil模板是一個獨立的Ruby代碼工程庫,主要包括代碼模板以及一組配置文件模板。

代碼模板使用Webmachine作為Web框架,RESTful和JSON構建服務之間的通信方式,RSpec作為測試框架。同時,代碼模板還定義了一組Rake任務,譬如運行測試,查看測試報告,將當前的微服務生成RPM包,使用Koji給RPM包打標簽等。

除此之外,該模板也提供了一組通用的URL,幫助使用者查看微服務的當前版本、配置信息以及檢測該微服務程序是否健康運行等。

[
    {
        rel: "index",
        path: "/diagnostic/"
    },
    {
        rel: "version",
        path: "/diagnostic/version"
    },
    {
        rel: "config",
        path: "/diagnostic/config"
    },
    {
        rel: "hostname",
        path: "/diagnostic/hostname"
    },
    {
        rel: "heartbeat",
        path: "/diagnostic/status/heartbeat"
    },
    {
        rel: "nagios",
        path: "/diagnostic/status/nagios"
    }
]

配置文件模板主要包括NewRelic配置,Passenger配置、Nagios配置、Apache配置以及Splunk配置。通過定義這些配置文件模板,當把新的微服務程序部署到驗收環境或者產品環境時,我們立刻就可以使用Nagios、NewRelic以及Splunk等第三方服務提供的功能,幫助我們有效的監控微服務,并在超過初始閾值時獲得告警。

代碼生成工具

借助Stencil代碼生成工具,我們能在很短時間內就構建出一個可以立即運行的微服務應用程序。隨著系統越來越復雜,微服務程序的不斷增多,Stencil模板和代碼生成工具幫助我們大大簡化了創建微服務的流程,讓開發人員更關注如何實現業務邏輯并快速驗證。

Create a project from the stencil template (version 0.1.27)
        --name, -n <s>:   New project name. eg. things-and-stuff
        --git-owner, -g <s>:   Git owner (default: which team or owner)
        --database, -d:   Include database connection code
        --triggered-task, -t:   Include triggered task code
        --provider, -p:   Is it a service provider? (other services use this service)
        --consumer, -c:   Is it a service consumer? (it uses other services)
        --branch, -b <s>:   Specify a particular branch of Stencil
        --face-palm, -f:   Overide name validation 
        --help, -h:   Show this message

如上代碼所示,通過指定不同參數,我們能創建具有數據庫訪問能力的微服務程序,或者是包含異步隊列處理的微服務程序。同時,我們也可以標記該服務是數據消費者還是數據生產者,能幫助我們理解多個微服務之間的聯系。

持續集成模板

基于持續集成服務器Bamboo,團隊創建了針對Stencil的持續集成模板工程,并定義了三個主要階段:

  • 打包:運行單元測試,集成測試,等待測試通過后生成RPM包。
  • 發布:將RPM包發布到Koji服務器上,并打上相應的Tag。然后使用Packer在亞馬遜 AWS云環境中創建AMI,建好的AMI上已經安裝了當前微服務程序的最新RPM包。
  • 部署:基于指定版本的AMI,將應用快速部署到驗收環境或者產品環境上。

利用持續集成模板工程,團隊僅需花費很少的時間,就可以針對新建的微應用程序,在Bamboo上快速定義其對應的持續集成環境。

一鍵部署工具

所有的微服務程序都部署并運行在亞馬遜AWS云環境上。同時,我們使用Asgard對AWS云環境中的資源進行創建、部署和管理。 Asgard是一套功能強大的基于Web的AWS云部署和管理工具,由Netflix采用Groovy on Grails開發,其主要優點有:

  • 基于B/S的AWS部署及管理工具,使用戶能通過瀏覽器直接訪問AWS云資源,無需設置Secret Key和Access Key;
  • 定義了`Application`以及`Cluster`等邏輯概念,更清晰、有效地描述了應用程序在AWS云環境中對應的部署拓撲結構。
  • 在對應用的部署操作中,集成了AWS Elastic Load Balancer、AWS EC2以及AWS Autoscaling Group,并將這些資源自動關聯起來。
  • 提供RESTful接口,能夠方便地與其他系統集成。
  • 簡潔易用的用戶接口,提供可視化的方式完成一鍵部署以及流量切換。

由于Asgard對RESTful的良好支持,團隊實現了一套基于Asgard的命令行部署工具,只需如下一條命令,提供應用程序的名稱以及版本號,就可自動完成資源的創建、部署、流量切換、刪除舊的應用等操作。

asgard-deploy [AppName] [AppVersion]

同時,基于命令行的部署工具,也可以很容易的將自動化部署集成到Bamboo持續集成環境。

通過使用微服務框架Stencil,大大縮短了團隊開發微服務的周期。同時,基于Stencil,我們定義了一套團隊內部的開發流程,幫助團隊的每一位成員理解并快速構建微服務。

微服務架構下的新系統

經過5個月的努力,我們重新構建了合同管理系統,將之前的產品、價格、銷售人員、合同簽署、合同審查以及PDF生成都定義成了獨立的服務接口。相比 之前大而全、難以維護的合同管理系統而言,新的系統由不同功能的微服務組成,每個微服務程序只關注單一的功能。每個微服務應用都有相關的負責人,通過使用Page Duty建立消息通知機制。每當有監控出現告警的時候,責任人能立即收到消息并快速做出響應。

基于微服務架構,改造企業核心系統之實踐

由于微服務具有高內聚,低耦合的特點,每個應用都是一個獨立的個體。當出現問題時,很容易定位問題并解決問題,大大縮短了修復缺陷的周期。另外,通 過使用不同功能的微服務接口提供數據,用戶接口(UI)部分變成了一個非常簡潔、輕量級的應用,更關注如何渲染頁面以及表單提交等交互功能。

總結

通過使用微服務架構,在不影響現有業務運轉的情況下,我們有效的將遺留的大系統逐漸分解成不同功能的微服務接口。同時,通過Stencil微服務開 發框架,我們能夠快速地構建不同功能的微服務接口,并能方便地將其部署到驗收環境或者產品環境。最后,得益于微服務架構的靈活性以及擴展性,使得我們能夠 快速構建低耦合、易擴展、易伸縮性的應用系統。

參考文獻

  1. http://martinfowler.com/articles/microservices.html
  2. http://jaxenter.com/cracking-microservices-practices-50692.html
  3. http://microservices.io/patterns/microservices.html

作者簡介

王磊,ThoughtWorks公司的程序員,咨詢師。開源軟件的愛好者和貢獻者,社區活動的參與 者,Practical RubyGems的譯者。于2012年加入ThoughtWorks,為國內外諸多客戶提供項目交付和咨詢服務;在加入ThoughtWorks之前,曾 就職過多家知名外企,具有豐富的敏捷項目實戰經驗。目前致力于微服務架構、高可用性的Web應用以及Devops的研究與實踐。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!