隨着公司國際化戰略的推行以及本土業務的高速發展,後臺支撐系統已經不堪重負。在吞吐量、穩定性以及可擴展性上都沒法知足日益增加的業務需求。對於每10萬元額度的合同,從銷售團隊準備材料、與客戶簽單、遞交給合同部門,再到合同生效大概須要3.5人天。隨着業務量的快速增加,簽定合同的成本急劇增長。php
合同管理系統是後臺支撐系統中重要的一部分。當前的合同系統是5年前使用.NET基於SAGE CRM二次開發的產品。 一方面,系統架構過於陳舊,性能、可靠性沒法知足現有的需求。另外一方面,功能繁雜,結構混亂,定製的代碼與SAGE CRM系統耦合度極高。因爲是遺留系統,熟悉該代碼的人早已離職多時,新團隊對其望而卻步,只能作些周邊的修補工做。同時,還要承擔着邊補測試,邊整理邏輯的工做。html
在沒法中斷業務處理的狀況下,爲了解決當前面臨的問題,團隊制定了以下的策略:ios
1). 在現有合同管理系統的外圍,構建功能服務接口,將系統核心的功能分離出來。git
2). 利用這些功能服務接口做爲代理,解耦原合同系統與其調用者之間的依賴;程序員
3). 經過不斷構建功能服務接口,逐漸將原有系統分解成多個獨立的服務。github
4). 摒棄原有的合同管理系統,使用全新構建的(微)服務接口替代。web
多年來,咱們一直在技術的浪潮中不斷乘風破浪,揚帆奮進,尋找更好的方式構建IT系統。微服務架構(Micro Service Architect)是近一段時間在軟件體系架構領域裏出現的一個新名詞。它經過將功能分解到多個獨立的服務,以實現對解決方案或者複雜系統的解耦。數據庫
微服務的誕生並不是偶然: 領域驅動設計指導咱們如何分析並模型化複雜的業務;敏捷方法論幫助咱們消除浪費,快速反饋;持續交付促使咱們構建更快、更可靠、更頻繁的軟件部署和交付能力;虛擬化和基礎設施自動化( Infrastructure As Code)則幫助咱們簡化環境的建立、安裝;DevOps文化的流行以及特性團隊的出現,使得小團隊更加全功能化。這些都是推進微服務誕生的重要因素。apache
實際上,微服務自己並無一個嚴格的定義。不過從業界的討論來看,微服務一般有以下幾個特徵:編程
每一個服務都是很小的應用,至於有多小,是一個很是有趣的話題。有人喜歡100行之內,有人同意1000行之內。數字並非最重要的。仁者見仁,智者見智,只要團隊以爲合適就好。只關注一個業務功能,這一點和咱們日常談論的面向對象原則中的」單一職責原則」相似,每一個服務只作一件事情,而且把它作好。
每一個服務都運行在一個獨立的操做系統進程中,這意味着不一樣的服務能被部署到不一樣的主機上。
服務和服務之間經過輕量級的機制實現彼此間的通訊。所謂輕量級通訊機制,一般指基於語言無關、平臺無關的這類協議,例如XML、JSON,而不是傳統咱們熟知的Java RMI或者.Net Remoting等。
不須要改變依賴,只更改當前服務自己,就能夠獨立部署。這意味着該服務和其餘服務之間在部署和運行上呈現相互獨立的狀態。
綜上所述,微服務架構採用多個服務間互相協做的方式構建傳統應用。每一個服務獨立運行在不一樣的進程中,服務與服務之間經過輕量的通信機制交互,而且每一個服務能夠經過自動化部署方式獨立部署。
相比傳統的單塊架構系統(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團隊、服務端團隊和數據庫團隊,這樣的分工可能會致使任何功能上的改變都須要跨團隊溝通和協調。而微服務則倡導圍繞服務來分工,團隊須要具有服務設計、開發、測試到部署所需的全部技能。
隨着團隊對業務的理解加深和對微服務實踐的嘗試,數個微服務程序已經成功構建出來。不過,問題同時也出現了:對於這些不一樣的微服務程序而言,雖然具體實現的代碼細節不一樣,但其結構、開發方式、持續集成環境、測試策略、部署機制以及監控和告警等,都有着相似的實現方式。那麼如何知足DRY原則並消除浪費呢?帶着這個問題,通過團隊的努力,Stencil誕生了。 Stencil是一個幫助快速構建Ruby微服務應用的開發框架,主要包括四部分: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的持續集成模板工程,並定義了三個主要階段:
利用持續集成模板工程,團隊僅需花費不多的時間,就能夠針對新建的微應用程序,在Bamboo上快速定義其對應的持續集成環境。
全部的微服務程序都部署並運行在亞馬遜AWS雲環境上。同時,咱們使用Asgard對AWS雲環境中的資源進行建立、部署和管理。 Asgard是一套功能強大的基於Web的AWS雲部署和管理工具,由Netflix採用Groovy on Grails開發,其主要優勢有:
因爲Asgard對RESTful的良好支持,團隊實現了一套基於Asgard的命令行部署工具,只需以下一條命令,提供應用程序的名稱以及版本號,就可自動完成資源的建立、部署、流量切換、刪除舊的應用等操做。
asgard-deploy [AppName] [AppVersion]
同時,基於命令行的部署工具,也能夠很容易的將自動化部署集成到Bamboo持續集成環境。
經過使用微服務框架Stencil,大大縮短了團隊開發微服務的週期。同時,基於Stencil,咱們定義了一套團隊內部的開發流程,幫助團隊的每一位成員理解並快速構建微服務。
通過5個月的努力,咱們從新構建了合同管理系統,將以前的產品、價格、銷售人員、合同簽署、合同審查以及PDF生成都定義成了獨立的服務接口。相比以前大而全、難以維護的合同管理系統而言,新的系統由不一樣功能的微服務組成,每一個微服務程序只關注單一的功能。每一個微服務應用都有相關的負責人,經過使用Page Duty創建消息通知機制。每當有監控出現告警的時候,責任人能當即收到消息並快速作出響應。
因爲微服務具備高內聚,低耦合的特色,每一個應用都是一個獨立的個體。當出現問題時,很容易定位問題並解決問題,大大縮短了修復缺陷的週期。另外,經過使用不一樣功能的微服務接口提供數據,用戶接口(UI)部分變成了一個很是簡潔、輕量級的應用,更關注如何渲染頁面以及表單提交等交互功能。
經過使用微服務架構,在不影響現有業務運轉的狀況下,咱們有效的將遺留的大系統逐漸分解成不一樣功能的微服務接口。同時,經過Stencil微服務開發框架,咱們可以快速地構建不一樣功能的微服務接口,並能方便地將其部署到驗收環境或者產品環境。最後,得益於微服務架構的靈活性以及擴展性,使得咱們可以快速構建低耦合、易擴展、易伸縮性的應用系統。
王磊,ThoughtWorks公司的程序員,諮詢師。開源軟件的愛好者和貢獻者,社區活動的參與者,Practical RubyGems的譯者。於2012年加入ThoughtWorks,爲國內外諸多客戶提供項目交付和諮詢服務;在加入ThoughtWorks以前,曾就任過多家知名外企,具備豐富的敏捷項目實戰經驗。目前致力於微服務架構、高可用性的Web應用以及Devops的研究與實踐。