前言 - 碁峰資訊epaper.gotop.com.tw/PDFSample/A442.pdf · 持續交付( continuous...

15
前言 微服務(microservice)是一種分散式系統的做法,倡導使用具有自身生命週期的細 微化服務,更且,這些服務協同合作,相互支援。因為微服務基本上圍繞著業務領域 business domain)而塑模,它們避開了傳統分層架構(tiered architecture)所蘊含的 一些問題。另外,微服務還整合了過去十年出現的新科技與新技術,這有助於它們避開 許多服務導向架構(service-oriented architecture)的實作陷阱。 這本書充滿了全世界普遍在用的微服務實例,包括 NetflixAmazonGilt 、和 REA 團等組織,這些大廠全都已經發現,微服務架構為其團隊所增添的自主性(autonomy具有非常大的優勢。 誰應該閱讀這本書 這本書的討論範圍甚廣,因為細微化或細微化(fine-grained)微服務架構的意涵也是相 當寬闊的,因此,它應該會吸引各路人馬的關注,包括設計、開發、部署、測試、和系 統維護等相關人員。不管是要新建應用程式,或者是要分解既有的單體式系統,那些已 經踏上微服務架構之征途的人會從本書中找到許多有用的實務建議。另外,對於想要瞭 解這一切是怎麼回事的人,這本書也是非常有幫助的,藉此,你可以自行判斷微服務是 否適合你。

Transcript of 前言 - 碁峰資訊epaper.gotop.com.tw/PDFSample/A442.pdf · 持續交付( continuous...

Page 1: 前言 - 碁峰資訊epaper.gotop.com.tw/PDFSample/A442.pdf · 持續交付( continuous delivery)的觀念讓我們知道如何更有效且有效率地讓軟體上線,同時灌輸我們應該把

前言

微服務(microservice)是一種分散式系統的做法,倡導使用具有自身生命週期的細微化服務,更且,這些服務協同合作,相互支援。因為微服務基本上圍繞著業務領域

(business domain)而塑模,它們避開了傳統分層架構(tiered architecture)所蘊含的一些問題。另外,微服務還整合了過去十年出現的新科技與新技術,這有助於它們避開

許多服務導向架構(service-oriented architecture)的實作陷阱。

這本書充滿了全世界普遍在用的微服務實例,包括 Netflix、Amazon、Gilt、和 REA集團等組織,這些大廠全都已經發現,微服務架構為其團隊所增添的自主性(autonomy)具有非常大的優勢。

誰應該閱讀這本書

這本書的討論範圍甚廣,因為細微化或細微化(fine-grained)微服務架構的意涵也是相當寬闊的,因此,它應該會吸引各路人馬的關注,包括設計、開發、部署、測試、和系

統維護等相關人員。不管是要新建應用程式,或者是要分解既有的單體式系統,那些已

經踏上微服務架構之征途的人會從本書中找到許多有用的實務建議。另外,對於想要瞭

解這一切是怎麼回事的人,這本書也是非常有幫助的,藉此,你可以自行判斷微服務是

否適合你。

Page 2: 前言 - 碁峰資訊epaper.gotop.com.tw/PDFSample/A442.pdf · 持續交付( continuous delivery)的觀念讓我們知道如何更有效且有效率地讓軟體上線,同時灌輸我們應該把

xvi | 前言

為什麼撰寫這本書

多年前,在協助人們更快速地交付軟體時,我開始思考應用程式架構(application architecture)的主題,我體認到,儘管基礎設施自動化、測試、與持續交付技術有幫助,然而,假如系統的基本設計未能讓變更很容易進行,那麼,能夠完成的事情自然有限。

與此同時,許多組織都在嘗試以較細微化的架構來完成類似的目標,並且提升系統的擴

展性,增進團隊的自主性,或者更輕鬆愉快地擁抱新技術。無論如何,我自己(以及

ThoughtWorks和其他地方的同事)的經驗突顯出一項事實:使用具有獨立生命週期的服務越多,必須處理的頭痛問題也越多。在許多面向上,這本書被想像成一站購足式的商

店(one-stop shop),涵蓋關於微服務所必須瞭解的各種主題-一些在過去令我搥胸頓足的重要事項,俗話說的好,千金難買早知道,萬般無奈沒想到!

關於當前的微服務

微服務是快速發展的領域,雖然想法並不新穎(即使這個術語本身頗新鮮),但全球專

業人士的實務經驗,加上蓬勃發展的新技術,對微服務的運用產生了極為深遠的影響。

由於更迭快速,我試圖把這本書聚焦在觀念上,更甚於特定技術,因為實作細節的改變

總是快過底層想法的演進。儘管如此,我預期,未來幾年,我們將更瞭解微服務究竟適

用在什麼地方,以及如何充分運用它們。

因此,雖然我已經在這本書中竭力淬煉出問題的本質,但如果你對此主題深感興趣,就

要有心理準備,你必須不斷學習,長期抗戰,以便掌握這個領域的最新進展!

本書簡介

這本書主要根據主題(topic)組織而成,因此,你可能想要直接跳到最感興趣的特定材料。雖然我已經盡量在前面幾章說明術語和觀念,但我希望,即使自認為相當有經驗的

人也能夠在此找到各個章節中他有興趣的東西。我會特別建議你好好閱讀第 2章,這一章粗淺而寬廣地探索整個領域,並且說明我如何探討這些事情,好讓你更輕鬆地深入研

究特定主題。

針對這個領域的新手,我已經以希望能夠幫助你從頭讀到尾的方式組織各個章節。

下面是各章概述:

Page 3: 前言 - 碁峰資訊epaper.gotop.com.tw/PDFSample/A442.pdf · 持續交付( continuous delivery)的觀念讓我們知道如何更有效且有效率地讓軟體上線,同時灌輸我們應該把

前言 | xvii

第 1章,微服務我們會從微服務的簡介開始,包括一些關鍵的好處及缺點。

第 2章,進化的架構師本章討論身為架構師的我們在權衡得失時所面臨的困難,並且說明,關於微服務,

我們究竟需要考量多少事情。

第 3章,如何塑模服務在此,我們會開始定義微服務的邊界,運用領域驅動設計(domain-driven design)的技術來幫忙聚焦我們的思維。

第 4章,整合在此,我們開始稍微深入特定技術實作,因為我們會討論什麼樣的服務協作技術最

有幫助。我們也會深入使用者介面的主題,以及如何與遺舊系統(legacy system)和商用現成(off-the-shelf,COTS)產品進行整合。

第 5章,拆分單體式系統許多人對微服務有興趣,是因為它可以作為龐大且難以變更之單體式系統

(monolithic system)的解毒劑,而這正是本章會仔細說明的東西。

第 6章,部署雖然這本書基本上是理論性的,但少數幾個主題受到部署技術之新進更迭的衝擊,

所以我們會在這裡探討它們。

第 7章,測試這一章深入測試主題,在部署多個獨立服務時會特別關注的領域,尤其注意,在確

保軟體品質上,消費者驅動的契約(consumer-driven contract)能夠扮演什麼角色。

第 8章,監控假如上線後發生問題,那麼,上線前的軟體測試能夠提供的幫助有限。這一章探討

如何監控我們的細微化系統,並且處理分散式系統的一些緊急複雜度。

第 9章,資訊安全在此,我們會檢視微服務的資安問題,並且考慮如何處理使用者對服務以及服務對

服務的認證和授權。資訊安全在計算機領域中是一個非常重要而且太容易被忽略的

主題。雖然我完全不是什麼安全防護專家,但我希望這一章至少能夠幫助你在建構

系統(尤其是微服務系統)時,確實考慮到一些需要注意的面向。

Page 4: 前言 - 碁峰資訊epaper.gotop.com.tw/PDFSample/A442.pdf · 持續交付( continuous delivery)的觀念讓我們知道如何更有效且有效率地讓軟體上線,同時灌輸我們應該把

xviii | 前言

第 10章,Conway定律與系統設計

這 一 章 聚 焦 於 組 織 結 構(organizational structure) 與 系 統 架 構(system architecture)的相互作用,許多組織已經意識到,如果你不讓兩者保持和諧,麻煩將接踵而至,我們會試圖弄清楚這個進退兩難的困局,並且考慮一些讓系統設計與

團隊結構相互契合的不同機制。

第 11章,大規模的微服務在這一章中,我們開始檢視如何以大規模的方式進行這一切,這樣的話,我們就可

以處理隨著服務數量與交通流量增加而增加的失敗可能性。

第 12章,全部組織起來最後一章試圖淬煉出讓微服務與眾不同的核心本質,包括七個微服務原則,並且總

結本書的一些關鍵要點。

本書所用的慣例

本書使用的字型、字體慣例,如下所示:

斜體字(Italic)

用來表示檔名、副檔名、網址和電子郵件。對於初次提到或重要的詞彙,中文以楷

體字呈現,其對應的英文則以斜體表示。

定寬字(Constant width)

用以表示程式碼,以及在段落裡參照程式元素,例如,變數或函式名稱、資料庫、

資料型別、環境變數、陳述式及關鍵字等。

定寬粗體字(Constant width bold)

用以表示使用者必須如實鍵入的指令或其他文字。

定寬斜體字(Constant width italic)

用來表示應以使用者提供或由上下文決定之值取代的文字。

Page 5: 前言 - 碁峰資訊epaper.gotop.com.tw/PDFSample/A442.pdf · 持續交付( continuous delivery)的觀念讓我們知道如何更有效且有效率地讓軟體上線,同時灌輸我們應該把

第一章

微服務

多年來,我們一直在尋找更好的系統建構方式,我們從經驗中學習,採納新技術,並且

觀察新一波科技公司如何以不同的方式運作,創造出幫忙讓客戶與開發者本身雙贏的 IT系統。

Eric Evans 所著的《Domain-Driven Design》(Addison-Wesley)幫助我們理解以程式碼表現真實世界的重要性,並且提供更好的系統塑模方式。持續交付(continuous delivery)的觀念讓我們知道如何更有效且有效率地讓軟體上線,同時灌輸我們應該把每一份程式碼簽入(check-in)視為候選釋出版本(release candidate)的理念。對 Web運作方式的理解促使我們發展出讓機器彼此溝通的更好方式。Alistair Cockburn的六角架構(hexagonal architecture,或稱六邊形架構,http://bit.ly/1GZuFW9)引導我們遠離分

層架構裡業務邏輯可能隱匿其中的窘態。虛擬化平台(virtualization platform)允許我們任意供應及重新調整機器,搭配基礎設施自動化(infrastructure automation),我們得以大規模地處理這些機器。一些成功大型組織(如 Amazon與 Google)所信奉的觀點是讓小團隊負責並掌握服務的完整生命週期,更且,近來,Netflix公司與我們分享了建構反脆弱系統(antifragile system)的觀念,那可是十年前無法理解的境況。

領域驅動設計、持續交付、隨需虛擬化(on-demand virtualization)、基礎設施自動化、小型自主團隊(small autonomous team)、大規模系統等等,微服務早就現身於世,它們的出現並非橫空出世;而是一種源自於現實應用的趨勢或模式,一切只是水到渠成。

貫穿本書,我會探討這些前期工作,協助描繪如何建立、管理、及演進微服務的整體 圖像。

許多組織發現,透過擁抱細微化的微服務架構,他們能夠更快速地交付軟體,並且更順

利地擁抱新技術。微服務提供我們更多自由度,以便進行及回應不同的決策,讓我們更

迅速地對無可避免的變更與衝擊做出回應。

Page 6: 前言 - 碁峰資訊epaper.gotop.com.tw/PDFSample/A442.pdf · 持續交付( continuous delivery)的觀念讓我們知道如何更有效且有效率地讓軟體上線,同時灌輸我們應該把

2 | 第一章

什麼是微服務?

微服務是一群協同運作的小型自主服務(autonomous service),讓我們稍微分解它的定義,並且思考一下讓微服務不同凡響的幾個特點。

小巧,並且專注於做好一件事

隨著我們撰寫程式碼,添加新功能,程式碼基礎(codebase)逐漸增長,經過一段時間後,可能連判斷要在哪裡進行變更都很難,因為程式碼基礎變得相當龐大。儘管我們盡

可能朝向乾淨的、模組化的單體式程式碼基礎發展,但這些任意發展的行程內之邊界

總會瓦解,類似功能的相關程式碼開始散落各處,讓修正臭蟲及實作新功能變得更加 困難。

在單體式系統中,我們盡量確保程式碼更有內聚性(通常藉由抽象化與模組化),

因而能夠對抗這些阻力。內聚性(cohesion,讓相關程式碼聚合在一起的驅力)是思考微服務時需要掌握的重要觀念,在〈Single Responsibility Principle〉(http://bitly.

com/1zOFMxl)中,Robert C. Martin所闡述的單一責任原則特別強化這個論點,「將

那些因為相同理由而改變的東西集合起來,將那些因為不同理由而改變的東西分離 開來」。

微服務採取相同的做法,達成它的獨立性。我們將服務邊界聚焦在業務邊界,讓程式碼

清楚地為特定功能片段而存在,而且,藉由讓服務聚焦在明確的邊界,我們避免讓它過

於膨脹,因而引進各種相關的棘手問題。

經常有人問我,多小才算小?無法給定明確的程式碼行數,因為某些語言比其他語言

更具表達性,因而能夠以較少的程式碼做較多的事情,而且,還必須考慮一項事實,我

們可能引進諸多依賴性(dependencies),它們本身包含很多行程式碼。另外,你的領域(domain)的某些部分可能天生就很複雜,需要使用較多的程式碼。RealEstate.com.au的 Jon Eaves將微服務描繪成可以在二週內重寫過的東西,這個經驗法則適用於他所處的特定作業情境。

我可以提供的另一個陳腐答案是:夠小,而不會更小。在研討會上發表演說時,我幾

乎總是會詢問,誰擁有太過龐大的系統,以及是否想要分解它?幾乎每個人都會舉

手,看起來,我們似乎相當瞭解什麼是太過龐大,因此,可以這麼說,一旦程式碼片段

不再讓人感覺過於龐大,可能就是夠小了。

Page 7: 前言 - 碁峰資訊epaper.gotop.com.tw/PDFSample/A442.pdf · 持續交付( continuous delivery)的觀念讓我們知道如何更有效且有效率地讓軟體上線,同時灌輸我們應該把

微服務 | 3

幫助我們回答這個問題的重要因素是:服務與團隊結構(team structure)有多契合,如果程式碼基礎過於龐大,無法由小團隊管理,試著分解它自然是非常明智的做法。稍

後,我們會談論更多關於組織調校(organizational alignment)的問題。

當論及多小才算夠小時,我喜歡從這個觀點思考:服務越小,微服務架構的好處與缺點

就越被放大。因為微服務越小,相互依賴(interdependence)的好處就越大,然而,更多活動元件(moving part)所產生的複雜度也越高,我們會在本書裡探討這些東西。隨著你能夠處理的複雜度越來越高,你有能力掌握的服務就越來越小。

自主性

我們的微服務是獨立的實體(entity),它可能被部署為平台即服務(platform as a service,PaaS)上的獨立服務,或者可能是它自己的作業系統行程。我們盡量避免將多個服務整合到相同機器上,雖然機器的定義在現今世界裡是很模糊的!如稍後即將討

論,儘管這種隔離會增加一些開銷(overhead),但它所產生的簡單性會讓分散式系統更容易理解,而且,較新穎的技術也能夠消弭許多與這種部署形式相關的困難與挑戰。

不同服務之間透過網路呼叫來溝通,強化了服務之間的分隔,避免緊密耦合的危險性。

這些服務必須能夠彼此獨立地變更,並且可以獨立地部署,而不需要服務消費者

(consumer)改變什麼。我們必須思考服務應該開放什麼,以及應該允許哪些東西被隱藏。如果存在太多共用(sharing),用戶端服務(consuming service)就會跟我們的內部表示(internal representation)產生耦合,繼而降低我們的自主性(autonomy),因為,在進行變更時,我們必須跟消費者進行更多額外的協調。

我們的服務開放一些 API(application programming interface,應用程式介面),協同合作的服務則透過這些 API跟我們溝通。另外,我們也必須考慮什麼技術能夠確保不跟消費者產生耦合,這可能意味著,選用技術無關(technology-agnostic)的 API,確保我們不受限於特定技術選項。在這本書中,我們會持續探討解耦合之良好 API的重要性。

如果沒能解耦合,一切都是徒然。最高指導原則是:你能夠獨立地對服務進行變更,並

且獨立地部署它,而不需要改變其他事情嗎?如果答案是否定的,那麼,本書所討論的

諸多好處都將是你難以達成的。

為了解耦合,你必須正確地塑模你的服務,並且將 API弄對。我會深入討論這個主題。

Page 8: 前言 - 碁峰資訊epaper.gotop.com.tw/PDFSample/A442.pdf · 持續交付( continuous delivery)的觀念讓我們知道如何更有效且有效率地讓軟體上線,同時灌輸我們應該把

4 | 第一章

主要的好處

微服務的好處是多方面的,其中很多是任何分散式系統都具備的,然而,微服務傾向於

更徹底地追求這些好處,主要是因為它們將分散式系統與服務導向架構背後的觀念進一

步發揚光大。

技術異質性

採用由多個協作服務(collaborating service)組成的系統時,我們可以決定針對每一個服務使用不同的技術,這允許我們針對每個任務選擇合適的工具,而不必選擇更標準、

更一體適用的做法,那樣往往導致不甚理想的最「小」公約數。

如果系統的某一部分需要提升效能,我們可能決定採用更符合效能需求的技術堆疊

(technology stack)。我們也可能決定針對系統的不同部分採取不同的資料儲存方式,例如,對社群網路來說,我們可能將使用者的互動儲存在圖學導向資料庫(graph-oriented database),以便反映出社交圖譜(social graph)的高度互聯本質,另一方面,使用者張貼的文章或許能夠被儲存在文件導向資料庫(document-oriented database),因而產生圖 1-1所顯示的異質架構(heterogeneous architecture)。

文章<<ruby>>

Documentstore

朋友<<golang>>

GraphDB

照片<<java>>

Blobstore

圖 1-1 微服務讓你更輕鬆地擁抱新技術

藉由微服務,我們還能夠更迅速地採用新技術,並且瞭解它對我們有什麼幫助。嘗試及

採用新技術的最大障礙之一就是與它相關聯的風險。使用單體式應用程式時,如果我想

要嘗試新的編程語言、資料庫、或框架,任何變更都會對我的系統產生巨幅的影響。採

用由多個服務組成的系統時,我可以在不同的地方嘗試新技術,我可以挑選風險最低的

服務來嘗試新技術,因為我能夠明確地限制潛在的負面影響。許多組織發現,這項能力

讓他們得以更迅速地吸納新技術,成為組織的實際優勢。

Page 9: 前言 - 碁峰資訊epaper.gotop.com.tw/PDFSample/A442.pdf · 持續交付( continuous delivery)的觀念讓我們知道如何更有效且有效率地讓軟體上線,同時灌輸我們應該把

微服務 | 5

當然,擁抱多種技術自然有它的額外開銷,某些組織選擇約束採用的語言,例如,

Netflix和 Twitter主要使用 Java虛擬機器(JVM)作為平台,因為他們非常瞭解該系統的可靠性與效能,他們還針對 JVM開發程式庫和工具,讓大規模運作變得更容易,然而,這卻讓非奠基於 Java的服務或客戶端變得更難融入。無論如何,Twitter與 Netflix都不是僅用一個技術堆疊應付所有的任務。另一個關於混用不同技術的顧慮就是規模,

如果我真的能夠在兩週之內重寫微服務,或許就能夠減輕擁抱新技術的風險。

如本書即將說明,許多與微服務相關的事情其實都只是在尋找適當的平衡點。第 2章討論如何挑選技術,重點在於演進的架構;第 4章處理整合問題,你會學到如何確保各個服務能夠演進自己的技術,彼此獨立,沒有不適當的耦合。

彈性

彈性工程(resilience engineering)的關鍵概念是隔艙(bulkhead),如果系統的一個元件失敗,而該失敗並未蔓延,你就可以區隔問題,系統的其餘部分就能夠繼續運作。服

務邊界成為你的隔艙。在單體式服務中,如果服務失敗,一切停止運作。使用單體式系

統時,我們可以在多台機器上運行,以減少徹底潰敗的可能性,然而,使用微服務時,

我們自然就能夠讓系統避免全面失敗,並且根據實際狀況降級(degrade),維持一定程度的功能性。

然而,我們確實需要非常小心。為確保微服務系統適切地提升彈性(resilience),我們必須瞭解分散式系統需要處理的新失敗來源,網路會故障,機器也一樣,我們必須知道

如何處理這個問題,以及它對軟體的終端使用者會有什麼影響(如果有的話)。

在第 11章中,我們會更深入地探討如何較妥善地處理彈性工程和失敗模式的問題。

擴展

使用龐大的單體式服務時,我們必須同時擴展一切。假設整體系統的一小部分受制於效

能問題,如果該行為發生在龐大的單體式應用程式中,我們必須一體擴展,其影響遍及

整個系統。使用較小的服務時,我們可以只擴展那些需要擴展的服務,並且在較小、處

理能力較低的硬體上運行系統的其餘部分,如圖 1-2所示。

Page 10: 前言 - 碁峰資訊epaper.gotop.com.tw/PDFSample/A442.pdf · 持續交付( continuous delivery)的觀念讓我們知道如何更有效且有效率地讓軟體上線,同時灌輸我們應該把

6 | 第一章

Instance 1 Instance 2

文章

Instance 3 Instance 4 Instance 5

照片

Instance 6

Instance 1 Instance 2 Instance 3

Instance 1

朋友

Instance 2

圖 1-2 你可以只針對有需要的微服務進行擴展

Gilt,線上精品零售商,正是因為這個理由而採用微服務。從 2007年開始,Gilt使用單體式 Rails應用程式,到 2009年,Gilt的系統無法應付它的負載,透過將系統的核心元件切割出來,Gilt更有能力處理它的流量尖峰,目前,Gilt已經擁有超過 450個微服務,每一個都運行在多台獨立的機器上。

擁抱隨需供應系統(on-demand provisioning system,如 Amazon Web Services提供的那些)時,我們甚至可以將這樣的隨需擴展(scaling on demand)應用到那些有需要的軟體片段,讓我們更有效地控制成本,一般而言,架構性的解決方案通常不會跟即刻性的

成本節省如此密切相關。

容易部署

對包含百萬行程式碼的單體式應用程式做一行改變仍需部署整個應用程式,以便發布這

個變更,那可能是具有重大影響與風險的部署。在實務中,這樣的部署不常發生,因為

人們瞭解它的可怕,不幸的是,這也意味著,變更會在不同釋出版本之間持續積累,最

後,正式上線的新版應用程式包含一堆變更,而且,不同釋出版本之間的差異越大,犯

錯的風險就越高!

Page 11: 前言 - 碁峰資訊epaper.gotop.com.tw/PDFSample/A442.pdf · 持續交付( continuous delivery)的觀念讓我們知道如何更有效且有效率地讓軟體上線,同時灌輸我們應該把

微服務 | 7

使用微服務時,我們可以針對單一服務做變更,並且獨立於系統其餘部分進行部署,讓

我們能夠更快速地部署程式碼。若有問題發生,它可以乾淨俐落地被隔離在個別的服務

中,讓撤銷部署(rollback,回滾)更容易實現,同時,這也意味著,我們可以更快速地將新功能交到客戶手上,這是 Amazon與 Netflix等組織會使用這類架構的主要原因之一—盡可能消除軟體交付的障礙。

在過去幾年中,這個領域的相關技術發生很大的變化,我們會在第 6章中更深入地探討微服務部署的主題。

組織調校

很多人都經歷過一些與大型團隊和龐大程式碼基礎相關的問題,在團隊分散各處時,這

些問題可能更加嚴重,另外,我們也知道,處理較小程式碼基礎的較小團隊往往更具生

產力。

微服務讓我們更容易將我們的組織調校成與我們的架構相契合,幫助我們盡可能減少從

事單一程式碼基礎的人員數量,達成團隊規模與生產力的甜蜜點。我們也可以在不同

團隊之間轉移服務的所有權,盡量讓開發同一個服務的人員同處一地。在第 10章關於Conway定律的討論中,我們將更深入地探索這個主題。

組合性

分散式系統與服務導向架構的核心承諾之一就是:開拓功能重利用的機會。藉由微服

務,我們讓功能透過不同的方式、針對不同的目的被運用,這在考慮消費者如何使用我

們的軟體時尤其重要。現在,我們不能夠再以狹隘的方式思考桌面網站或行動應用程

式,我們必須通盤考量各種途徑,我們可能想要整合 Web、原生應用程式、行動 app、平板 app、或穿載式裝置的各種能力。隨著組織從狹隘的通道式思維演進到更全面的客戶參與,我們需要一種跟得上時代的架構。

使用微服務時,要想到我們正在開放系統中可由外部觸及的縫隙(seams)。隨著情況改變,我們會以不同的方式打造軟體。使用單體式應用程式時,通常有一個能夠從外部使

用的粗粒度縫隙(coarse-grained seam),假如我想要分解它,獲得更有用的東西,那可是一項需要大費周章的工程!在第 5章中,我會探討一些方法,讓你分解既有的單體式系統,希望能夠將它們轉變成一些可重利用、可重新組合的微服務。

Page 12: 前言 - 碁峰資訊epaper.gotop.com.tw/PDFSample/A442.pdf · 持續交付( continuous delivery)的觀念讓我們知道如何更有效且有效率地讓軟體上線,同時灌輸我們應該把

8 | 第一章

最佳化可替換性

如果你服務於中大型的組織,很可能知道辦公室的角落存在著某種龐大、難搞的遺舊系

統(legacy system),一個沒有人願意去碰的系統,然而,它對公司的運作至關重要,但剛好以某種奇怪的 Fortran變形寫成,並且執行在早該退役的硬體上,為什麼還沒被取代?你知道原因:這項任務實在太過龐雜且深具風險。

由於個別服務的規模小,以較佳實作替換它們(甚至完全移除)的成本比較容易管理。

你多常在一天內刪除超過一百行程式碼而不必太過擔心?因為微服務通常是這般大小,

重寫或完全移除它的障礙是非常低的。

使用微服務架構的團隊很習慣在必要時重寫服務,並且在服務不再被需要時直接刪除

它。當程式碼基礎只有幾百行時,你在情感上不會太難割捨,而且,替換它的成本是非

常小的。

服務導向架構呢?

服務導向架構(service-oriented architecture,SOA)是一種設計方法,在當中,多個服務協同合作,提供一組功能,在此,服務通常是指完全獨立的作業系統行程

(process),這些服務通常透過網路呼叫進行溝通,而不是在行程邊界之內的方法呼叫(method call)。

SOA 是一種挑戰大型單體式應用程式的做法,目標是促進軟體的可重利用性(reusability);例如,兩個以上的終端使用者應用程式能夠使用相同的服務。SOA的目標是讓我們更容易維護或重寫軟體,理論上,我們可以無聲無息地使用一個服務替換另

一個服務,只要服務的語義(semantics)不會變動太大。

SOA在根本上是非常明智的想法,然而,儘管經過許多努力,SOA的合適實作還是缺乏良好的共識,在我看來,許多業界人士未能全盤思考這個問題,並且提出令人折服的

解決方案,以便取代業內各個供應商的一家之言。

事實上,SOA 面臨的諸多問題包括通訊協定(如 SOAP)、供應商中間件(vendor middleware)、缺乏服務細粒度(granularity)的指導方針、或者缺乏要挑選什麼地方進行系統分割的正確指導。貫穿全書,我們會依次處理這些問題。憤世嫉俗的人可能認為

供應商們吸納(甚至驅使)SOA作為一種推廣業務或促銷產品的機制,而那些完全相同的產品最終卻損害了 SOA的目標。

Page 13: 前言 - 碁峰資訊epaper.gotop.com.tw/PDFSample/A442.pdf · 持續交付( continuous delivery)的觀念讓我們知道如何更有效且有效率地讓軟體上線,同時灌輸我們應該把

微服務 | 9

許多圍繞著 SOA的傳統智慧未能幫助你瞭解如何將大玩意分解成小東西,沒說明多大叫作太大,也不夠深入現實世界,探討確保服務不致於變得過度耦合的實務方法,許多

未說清楚的事情正是諸多 SOA陷阱的根源。

微服務方法衍生自現實世界的實際運用,讓我們更清楚地理解有助於妥善建構 SOA的系統與架構,因此,你應該把微服務想成是 SOA的特定解法,就像 XP或 Scrum被視為敏捷軟體開發的特定做法那樣。

其他分解技術

當你想通時,會發現,微服務架構的諸多優勢源自於它的細粒度本質,以及提供你更多

解法選項的事實,然而,類似的分解技術可能達到相同的好處嗎?

共用程式庫

幾乎任何語言均內建的標準分解技術就是將程式碼基礎分解成多個程式庫(library),這些程式庫可由第三方提供,或者由你自己的組織打造。

程式庫提供一種在不同團隊與不同服務之間共用功能性的機制,例如,我可能建立一組

有用的資料收集工具程式,或者統計程式庫,供他人重利用。

多個團隊可以圍繞著這些程式庫組織起來,而這些程式庫本身能夠被重利用,然而,這

也存在著一些缺點。

首先,你失去了技術異質性(heterogeneity),程式庫通常必須以相同的語言寫成,或至少執行在相同的平台上。其次,你們彼此獨立地擴展系統零件的困難度變高。再者,

除非使用動態連結程式庫,否則,沒有重新部署整個行程,就無法部署新的程式庫,因

此,獨立部署變更的能力降低。或許,還有一個潛藏的困難,你缺乏明顯的縫隙可用來

建立架構安全措施,以確保系統的彈性(resiliency)。

無論如何,共用程式庫確實佔有一席之地,你會發現自己正在建立不屬於特定業務領域

的通用程式碼,而且,你會想要在整個組織中重利用它,那正是成為共用程式庫的明顯

候選人。然而,確實必須小心,被用來在不同服務之間進行溝通的共用程式碼會變成耦

合點,我們將在第 4章中討論這個問題。

服務可以,也應該,大量使用第三方程式庫,重利用共通的程式碼,但它們不是萬能的。

Page 14: 前言 - 碁峰資訊epaper.gotop.com.tw/PDFSample/A442.pdf · 持續交付( continuous delivery)的觀念讓我們知道如何更有效且有效率地讓軟體上線,同時灌輸我們應該把

10 | 第一章

模組

有些語言提供自己的模組分解技術,超越簡單的程式庫,允許某種模組生命週期管理,

這樣的話,它們就可以被部署到運作中的行程裡,所以,無需停止整個行程,即可進行

變更。

Open Source Gateway Initiative(OSGI)可作為一項技術特定的模組分解方法。Java本身沒有真實的模組概念,至少必須等到 Java 9才能夠看到這項機制被添加進來。最初以框架的形式出現,允許插件被安裝在 Eclipse Java IDE中,OSGI現在被當作一種透過程式庫在 Java裡翻新模組概念的機制。

OSGI的問題是,它試圖強制實施模組生命週期管理之類的事情,而語言本身並沒有足夠的支援,導致模組作者必須完成更多工作,才能夠以適切隔離的方式交付模組。在行

程邊界內,這也很容易落入不同模組過度耦合的陷阱,造成各種問題。關於 OSGI,我自己的經驗(許多業界同仁也一樣)是,即使有很好的作業團隊,OSGI還是很容易變成更大的複雜度來源,遠超過它所帶來的利益。

Erlang遵循不同的做法,在當中,模組被轉化成語言的執行時期環境(runtime),因此,Erlang具有非常成熟的模組分解機制。Erlang模組能夠順利無礙地被停止、重啟、及升級。Erlang甚至允許在特定時間下執行多個模組版本,支援更優雅的模組升級。

Erlang模組的能力令人印象深刻,然而,即使很幸運地能夠使用具備這些能力的平台,我們還是會有與一般共用程式庫相同的缺點,亦即,使用新技術與獨立擴展的能力嚴格

受到限制,可能朝向過度耦合的整合技術發展,並且缺乏可用來建立架構安全措施的縫

隙。

還有一個觀察值得與你分享,技術上來說,在單體式行程裡建立妥善分解的獨立模組應

該是可能的,然而,我們很少看到這種情況發生,這些模組本身很快就會跟其餘程式碼

緊密耦合,放棄自己的主要優勢之一。隔離行程邊界確實讓程式碼乾淨俐落(或至少

讓它比較不容易做錯事!)。當然,我不認為這應該是行程隔離的主要驅力,但有趣的

是,於行程邊界內分離模組的諾言在現實世界中很少被兌現。

所以,雖然行程邊界內的模組分解可能是你想要做的事情,就跟將你的系統分解成多個

服務一樣,但是,單靠它本身並沒有辦法解決所有問題。如果你是在純 Erlang的環境裡,Erlang模組實作的品質對此確實大有幫助,但我懷疑你們當中有許多人並非處於這種狀況,對那些人來說,應該把模組視為跟共用程式庫提供相同的好處。

Page 15: 前言 - 碁峰資訊epaper.gotop.com.tw/PDFSample/A442.pdf · 持續交付( continuous delivery)的觀念讓我們知道如何更有效且有效率地讓軟體上線,同時灌輸我們應該把

微服務 | 11

沒有銀子彈

在本章結束前,我應該聲明,微服務不是免費的午餐或萬能的銀子彈,更不是一體通用

的金錘子,它們具有與分散式系統相關聯的各種複雜度,雖然我們已經瞭解如何妥善管

理分散式系統的諸多相關知識(本書會討論),這還是一項艱鉅的任務。如果你的背景

來自於單體式系統,你必須更精於處理部署、測試、與監控等問題,以便獲得目前所提

到的各種好處,你必須以不同的角度思考,想想如何擴展你的系統,並且確保它們是有

彈性的(resilient)。如果分散式交易或 CAP定理之類的事情開始困擾你,請不要覺得太驚訝 !

每一個公司、組織、和系統都不一樣,許多因素會影響微服務是否適合你,以及你可以

多積極地採用它們。貫穿本書的每一章,我會盡量為你點出潛在的陷阱與隱患,那應該

會幫助你開拓出一條康莊大道。

總結

現在,希望你明白什麼是微服務,什麼讓它與眾不同,以及關鍵優勢有那些。在後續的

每一章裡,我們將更深入地探討如何實現這些好處,以及如何避免一些常見的陷阱。

需要說明的主題不勝枚舉,但總得有個開頭。關於微服務,最主要的挑戰之一就是,經

常主導系統演進的那些人(亦即,架構師)在角色上有所更動,接下來,我們將探討架

構師能夠採取哪些不同的做法,確保我們充分利用這種新架構的諸多好處。