使用Spring Boot構建服務(文末福利)(使用springboot的好處)

      網友投稿 1200 2022-05-30

      學習微服務的關鍵特征

      了解微服務是如何適應云架構的

      將業務領域分解成一組微服務

      使用Spring Boot實現簡單的微服務

      掌握基于微服務架構構建應用程序的視角

      學習什么時候不應該使用微服務

      軟件開發的歷史充斥著大型開發項目崩潰的故事,這些項目可能投資了數百萬美元、集中了行業里眾多的頂尖人才、消耗了開發人員成千上萬的工時,但從未給客戶交付任何有價值的東西,最終由于其復雜性和負擔而轟然倒塌。

      這些龐大的項目傾向于遵循大型傳統的瀑布開發方法,堅持在項目開始時界定應用的所有需求和設計。這些項目的開發人員非常重視軟件說明書的“正確性”,卻很少能夠滿足新的業務需求,也很少能夠重構并從開發初期的錯誤中重新思考和學習。

      但現實情況是,軟件開發并不是一個由定義和執行所組成的線性過程,而是一個演化過程,在開發團隊真正明白手頭的問題前,需要經歷與客戶溝通、向客戶學習和向客戶交付的數次迭代。

      使用傳統的瀑布方法所面臨的挑戰在于,許多時候,這些項目交付的軟件制品的粒度具有以下特點。

      緊耦合的——業務邏輯的調用發生在編程語言層面,而不是通過實現中立的協議(如SOAP和REST)。這大大增加了即使對應用程序組件進行小的修改也可能打破應用程序的其他部分并引入新漏洞的機會。

      有漏洞的——大多數大型軟件應用程序都在管理著不同類型的數據。例如,客戶關系管理(CRM)應用程序可能會管理客戶、銷售和產品信息。在傳統的模型里,這些數據位于相同的數據模型中并在同一個數據存儲中保存。即使數據之間存在明顯的界限,在絕大多數的情況下,來自一個領域的團隊也很容易直接訪問屬于另一個團隊的數據。這種對數據的輕松訪問引入了隱藏的依賴關系,并讓組件的內部數據結構的實現細節泄漏到整個應用程序中。即使對單個數據庫表的更改也可能需要在整個應用程序中進行大量的代碼更改和回歸測試。

      單體的——由于傳統應用程序的大多數組件都存放在多個團隊共享的單個代碼庫中,任何時候更改代碼,整個應用程序都必須重新編譯、重新運行并且需要通過一個完整的測試周期并重新部署。無論是新客戶的需求還是修復錯誤,應用程序代碼庫的微小變化都將變得昂貴和耗時,并且幾乎不可能及時實現大規模的變化。

      基于微服務的架構采用不同的方法來交付功能。具體來說,基于微服務的架構具有以下特點。

      有約束的——微服務具有范圍有限的單一職責集。微服務遵循UNIX的理念,即應用程序是服務的集合,每個服務只做一件事,并只做好一件事。

      松耦合的——基于微服務的應用程序是小型服務的集合,服務之間使用非專屬調用協議(如HTTP和REST)通過非特定實現的接口彼此交互。與傳統的應用程序架構相比,只要服務的接口沒有改變,微服務的所有者可以更加自由地對服務進行修改。

      抽象的——微服務完全擁有自己的數據結構和數據源。微服務所擁有的數據只能由該服務修改。可以鎖定微服務數據的數據庫訪問控制,僅允許該服務訪問它。

      獨立的——微服務應用程序中的每個微服務可以獨立于應用程序中使用的其他服務進行編譯和部署。這意味著,與依賴更重的單體應用程序相比,這樣對變化進行隔離和測試更容易。

      為什么這些微服務架構屬性對基于云的開發很重要?基于云的應用程序通常有以下特點。

      擁有龐大而多樣化的用戶群——不同的客戶需要不同的功能,他們不想在開始使用這些功能之前等待漫長的應用程序發布周期。微服務允許功能快速交付,因為每個服務的范圍很小,并通過一個定義明確的接口進行訪問。

      極高的運行時間要求——由于微服務的分散性,基于微服務的應用程序可以更容易地將故障和問題隔離到應用程序的特定部分之中,而不會使整個應用程序崩潰。這可以減少應用程序的整體宕機時間,并使它們對問題更有抵御能力。

      不均勻的容量需求——在企業數據中心內部部署的傳統應用程序通常具有一致的使用模式,這些模式會隨著時間的推移而定期出現,這使這種類型的應用程序的容量規劃變得很簡單。但在一個基于云的應用中,Twitter上的一條簡單推文或Slashdot上的一篇文章就能夠極大帶動對基于云計算的應用的需求。

      因為微服務應用程序被分解成可以彼此獨立部署的小組件,所以能夠更容易將重點放在正處于高負載的組件上,并將這些組件在云中的多個服務器上進行水平伸縮。

      本文的內容會包含在業務問題中構建和識別微服務的基礎知識,構建微服務的骨架,然后理解在生產環境中成功部署和管理微服務的運維屬性。如果你想要更深入了解,請直接讀《Spring微服務實戰》

      要想成功設計和構建微服務,開發人員需要像警察向目擊證人訊問犯罪活動一樣著手處理微服務。即使每個證人看到同一事件發生,他們對犯罪活動的解釋也是根據他們的背景、他們所看重的東西(例如,給予他們動機的東西),以及在那個時刻目睹這個事件所帶來的環境壓力塑造出來的。每個參與者都有他們自己認為重要的視角(和偏見)。

      就像一名成功的警察試圖探尋真相一樣,構建一個成功的微服務架構的過程需要結合軟件開發組織內多個人的視角。盡管交付整個應用程序需要的不僅僅是技術人員,但我相信,成功的微服務開發的基礎是從以下3個關鍵角色的視角開始的。

      架構師——架構師的工作是看到大局,了解應用程序如何分解為單個微服務,以及微服務如何交互以交付解決方案。

      軟件開發人員——軟件開發人員編寫代碼并詳細了解如何將編程語言和該語言的開發框架用于交付微服務。

      DevOps工程師——DevOps工程師不僅為生產環境而且為所有非生產環境提供服務部署和管理的智慧。DevOps工程師的口號是:保障每個環境中的一致性和可重復性。

      本文將演示如何從這些角色的視角使用Spring Boot和Java設計和構建一組微服務。到本文結束時,讀者將有一個可以打包并部署到云的服務。

      架構師在軟件項目中的作用是提供待解決問題的工作模型。架構師的工作是提供腳手架,開發人員將根據這些腳手架構建他們的代碼,使應用程序所有部件都組合在一起。

      在構建微服務架構時,項目的架構師主要關注以下3個關鍵任務:

      (1)分解業務問題;

      (2)建立服務粒度;

      (3)定義服務接口。

      1.1.1分解業務問題

      面對復雜性,大多數人試圖將他們正在處理的問題分解成可管理的塊。因為這樣他們就不必努力把問題的所有細節都考慮進來。他們將問題抽象地分解成幾個關鍵部分,然后尋找這些部分之間存在的關系。

      在微服務架構中,架構師將業務問題分解成代表離散活動領域的塊。這些塊封裝了與業務域特定部分相關聯的業務規則和數據邏輯。

      雖然我們希望微服務封裝執行單個事務的所有業務規則,但這并不總是行得通。我們經常會遇到需要跨業務領域不同部分的一組微服務來完成整個事務的情況。架構師通過查看數據域中那些不適合放到一起的地方來劃分一組微服務的服務邊界。

      例如,架構師可能會看到代碼執行的業務流程,并意識到它們同時需要客戶和產品信息。存在兩個離散的數據域時,通常就意味著需要使用多個微服務。業務事務的兩個不同部分如何交互通常成為微服務的服務接口。

      分離業務領域是一門藝術,而不是非黑即白的科學。讀者可以使用以下指導方針將業務問題識別和分解為備選的微服務。

      (1)描述業務問題,并聆聽用來描述問題的名詞。在描述問題時,反復使用的同一名詞通常意味著它們是核心業務領域并且適合創建微服務。第1章中EagleEye域的目標名詞可能會是合同、許可證和資產。

      (2)注意動詞。動詞突出了動作,通常代表問題域的自然輪廓。如果發現自己說出“事務X需要從事物A和事物B獲取數據”這樣的話,通常表明多個服務正在起作用。如果把注意動詞的方法應用到EagleEye上,那么就可能會查找像“來自桌面服務的Mike安裝新PC時,他會查找軟件X可用的許可證數量,如果有許可證,就安裝軟件。然后他更新了跟蹤電子表格中使用的許可證的數量”這樣的陳述句。這里的關鍵動詞是查找和更新。

      (3)尋找數據內聚。將業務問題分解成離散的部分時,要尋找彼此高度相關的數據。如果在會話過程中,突然讀取或更新與迄今為止所討論的內容完全不同的數據,那么就可能還存在其他候選服務。微服務應完全擁有自己的數據。

      讓我們將這些指導方針應用到現實世界的問題中。第1章介紹了一種名為EagleEye的現有軟件產品,該軟件產品用于管理軟件資產,如軟件許可證和安全套接字層(SSL)證書。這些軟件資產被部署到組織中的各種服務器上。

      EagleEye是一個傳統的單體Web應用程序,部署在位于客戶數據中心內的J2EE應用程序服務器。我們的目標是將現有的單體應用程序梳理成一組服務。

      首先,我們要采訪EagleEye應用程序的所有用戶,并討論他們是如何交互和使用EagleEye的。圖1-1描述了與不同業務客戶進行的對話的總結。通過查看EagleEye的用戶是如何與應用程序進行交互的,以及如何將應用程序的數據模型分解出來,可以將EagleEye問題域分解為以下備選微服務。

      圖1-1 采訪EagleEye用戶,了解他們如何做日常工作

      圖1-1強調了與業務用戶對話時出現的一些名詞和動詞。因為這是現有的應用程序,所以可以查看應用程序并將主要名詞映射到物理數據模型中的表。現有應用程序可能有數百張表,但每張表通常會映射回一組邏輯實體。

      圖1-2展示了基于與EagleEye客戶對話的簡化數據模型。基于業務對話和數據模型,備選微服務是組織、許可證、合同和資產服務。

      圖1-2 簡化的EagleEye數據模型

      1.1.2建立服務粒度

      擁有了一個簡化的數據模型,就可以開始定義在應用程序中需要哪些微服務。根據圖1-2中的數據模型,可以看到潛在的4個微服務基于以下元素:

      資產;

      許可證;

      合同;

      組織。

      我們的目標是將這些主要的功能部件提取到完全獨立的單元中,這些單元可以獨立構建和部署。但是,從數據模型中提取服務需要的不只是將代碼重新打包到單獨的項目中,還涉及梳理出服務訪問的實際數據庫表,并且只允許每個單獨的服務訪問其特定域中的表。圖1-3展示了應用程序代碼和數據模型如何被“分塊”到各個部分。

      圖1-3 將數據模型作為把單體應用程序分解為微服務的基礎

      將問題域分解成不同的部分后,開發人員通常會發現自己不確定是否為服務劃分了適當的粒度級別。一個太粗粒度或太細粒度的微服務將具有很多的特征,我們將在稍后討論。

      構建微服務架構時,粒度的問題很重要,可以采用以下思想來確定正確的解決方案。

      (1)開始的時候可以讓微服務涉及的范圍更廣泛一些,然后將其重構到更小的服務——在開始微服務旅程之初,容易出現的一個極端情況就是將所有的事情都變成微服務。但是將問題域分解為小型的服務通常會導致過早的復雜性,因為微服務變成了細粒度的數據服務。

      (2)重點關注服務如何相互交互——這有助于建立問題域的粗粒度接口。從粗粒度重構到細粒度是比較容易的。

      (3)隨著對問題域的理解不斷增長,服務的職責將隨著時間的推移而改變——通常來說,當需要新的應用功能時,微服務就會承擔起職責。最初的微服務可能會發展為多個服務,原始的微服務則充當這些新服務的編排層,負責將應用的其他部分的功能封裝起來。

      糟糕的微服務的“味道”

      如何知道微服務的劃分是否正確?如果微服務過于粗粒度,可能會看到以下現象。

      服務承擔過多的職責——服務中的業務邏輯的一般流程很復雜,并且似乎正在執行一組過于多樣化的業務規則。

      該服務正在跨大量表來管理數據——微服務是它管理的數據的記錄系統。如果發現自己將數據持久化存儲到多個表或接觸到當前數據庫以外的表,那么這就是一條服務過于粗粒度的線索。我喜歡使用這么一個指導方針——微服務應該不超過3~5個表。再多一點,服務就可能承擔了太多的職責。

      測試用例太多——隨著時間的推移,服務的規模和職責會增長。如果一開始有一個只有少量測試用例的服務,到了最后該服務需要數百個單元測試用例和集成測試用例,那么就可能需要重構。

      如果微服務過于細粒度呢?

      問題域的一部分微服務像兔子一樣繁殖——如果一切都成為微服務,將服務中的業務邏輯組合起來會變得復雜和困難,因為完成一項工作所需的服務數量會快速增長。一種常見的“壞味道”出現在應用程序有幾十個微服務,并且每個服務只與一個數據庫表進行交互時。

      微服務彼此間嚴重相互依賴——在問題域的某一部分中,微服務相互來回調用以完成單個用戶請求。

      微服務成為簡單CRUD(Create,Read,Update,Delete)服務的集合——微服務是業務邏輯的表達,而不是數據源的抽象層。如果微服務除了CRUD相關邏輯之外什么都不做,那么它們可能被劃分得太細粒度了。

      應該通過演化思維的過程來開發一個微服務架構,在這個過程中,你知道不會第一次就得到正確的設計。這就是最好從一組粗粒度的服務而不是一組細粒度的服務開始的原因。同樣重要的是,不要對設計帶有教條主義。我們可能會面臨兩個單獨的服務之間交互過于頻繁,或者服務的域之間不存在明確的邊界這樣的物理約束,當面臨這樣的約束時,需要創建一個聚合服務來將數據連接在一起。

      最后,采取務實的做法并進行交付,而不是浪費時間試圖讓設計變得完美,最終導致沒有東西可以展現你的努力。

      1.1.3互相交流:定義服務接口

      架構師需要關心的最后一部分,是應用程序中的微服務該如何彼此交流。使用微服務構建業務邏輯時,服務的接口應該是直觀的,開發人員應該通過學習應用程序中的一兩個服務來獲得應用程序中所有服務的工作節奏。

      一般來說,可使用以下指導方針思考服務接口設計。

      (1)擁抱REST的理念——REST對服務的處理方式是將HTTP作為服務的調用協議并使用標準HTTP動詞(GET、PUT、POST和DELETE)。圍繞這些HTTP動詞對基本行為進行建模。

      (2)使用URI來傳達意圖——用作服務端點的URI應描述問題域中的不同資源,并為問題域內的資源的關系提供一種基本機制。

      (3)請求和響應使用JSON——JavaScript對象表示法(JavaScript Object Notation,JSON)是一個非常輕量級的數據序列化協議,并且比XML更容易使用。

      (4)使用HTTP狀態碼來傳達結果——HTTP協議具有豐富的標準響應代碼,以指示服務的成功或失敗。學習這些狀態碼,并且最重要的是在所有服務中始終如一地使用它們。

      所有這些指導方針都是為了完成一件事,那就是使服務接口易于理解和使用。我們希望開發人員坐下來查看一下服務接口就能開始使用它們。如果微服務不容易使用,開發人員就會另辟道路,破壞架構的意圖。

      接下來,讓我們了解一下其中的考量因素:

      (1)構建分布式系統的復雜性;

      (2)虛擬服務器/容器散亂;

      (3)應用程序的類型;

      (4)數據事務和一致性。

      1.2.1構建分布式系統的復雜性

      因為微服務是分布式和細粒度(小)的,所以它們在應用程序中引入了一層復雜性,而在單體應用程序中就不會出現這樣的情況。微服務架構需要高度的運維成熟度。除非組織愿意投入高分布式應用程序獲得成功所需的自動化和運維工作(監控、伸縮),否則不要考慮使用微服務。

      1.2.2服務器散亂

      微服務最常用的部署模式之一就是在一個服務器上部署一個微服務實例。在基于微服務的大型應用程序中,最終可能需要50~100臺服務器或容器(通常是虛擬的),這些服務器或容器必須單獨搭建和維護。即使在云中運行這些服務的成本較低,管理和監控這些服務器的操作復雜性也是巨大的。

      2.2.3 應用程序的類型

      微服務面向可復用性,并且對構建需要高度彈性和可伸縮性的大型應用程序非常有用。這就是這么多云計算公司采用微服務的原因之一。如果讀者正在構建小型的、部門級的應用程序或具有較小用戶群的應用程序,那么搭建一個分布式模型(如微服務)的復雜性可能太昂貴了,不值得。

      2.2.4 數據事務和一致性

      開始關注微服務時,需要考慮服務的數據使用模式以及服務消費者如何使用它們。微服務包裝并抽象出少量的表,作為執行“操作型”任務的機制,如創建、添加和執行針對存儲的簡單(非復雜的)查詢,其工作效果很好。

      如果應用程序需要跨多個數據源進行復雜的數據聚合或轉換,那么微服務的分布式性質會讓這項工作變得很困難。這樣的微服務總是承擔太多的職責,也可能變得容易受到性能問題的影響。

      還要記住,在微服務間執行事務沒有標準。如果需要事務管理,那就需要自己構建邏輯。另外,如第7章所述,微服務可以通過使用消息進行通信。消息傳遞在數據更新中引入了延遲。應用程序需要處理最終的一致性,數據的更新可能不會立即出現。

      在構建微服務時,從概念到實現,需要視角的轉換。具體來說,開發人員需要建立一個實現應用程序中每個微服務的基本模式。雖然每項服務都將是獨一無二的,但我們希望確保使用的是一個移除樣板代碼的框架,并且微服務的每個部分都采用相同的布局。

      在本節中,我們將探討開發人員從EagleEye域模型構建許可證微服務的優先事項。許可證服務將使用Spring Boot編寫。Spring Boot是標準Spring庫之上的一個抽象層,它允許開發人員快速構建基于Groovy和Java的Web應用程序和微服務,比成熟的Spring應用程序能夠節省大量的配置。

      對于許可證服務示例,這里將使用Java作為核心編程語言并使用Apache Maven作為構建工具。

      在接下來的幾節中,我們將要完成以下幾項工作。

      (1)構建微服務的基本框架并構建應用程序的Maven腳本。

      (2)實現一個Spring引導類,它將啟動用于微服務的Spring容器,并啟動類的所有初始化工作。

      (3)實現映射端點的Spring Boot控制器類,以公開服務的端點。

      1.3.1 從骨架項目開始

      1.3.1 從骨架項目開始

      首先,要為許可證服務創建一個骨架項目。讀者可以從本文的GitHub存儲庫拉取源代碼,也可以創建具有以下目錄結構的許可證服務項目目錄:

      licensing-service

      src/main/java/com/thoughtmechanix/licenses

      controllers

      model

      services

      resources

      一旦拉取或創建了這個目錄結構,就可以開始為項目編寫Maven腳本。這就是位于項目根目錄下的pom.xml文件。代碼清單1-1展示了許可證服務的Maven POM文件。

      代碼清單1-1 許可證服務的Maven POM文件

      這里不會詳細討論整個腳本,但是在開始的時候要注意幾個關鍵的地方。Spring Boot被分解成許多個獨立的項目。其理念是,如果不需要在應用程序中使用Spring Boot的各個部分,那么就不應該“拉取整個世界”。這也使不同的Spring Boot項目能夠獨立地發布新版本的代碼。為了簡化開發人員的開發工作,Spring Boot團隊將相關的依賴項目收集到各種“起步”(starter)工具包中。Maven POM的第一部分告訴Maven需要拉取Spring Boot框架的1.4.4版本。

      Maven文件的第二部分和第三部分確定了要拉取Spring Web和Spring Actuator起步工具包。這兩個項目幾乎是所有基于Spring Boot REST服務的核心。讀者會發現,服務中構建功能越多,這些依賴項目的列表就會變得越長。

      此外,Spring Source還提供了Maven插件,可簡化Spring Boot應用程序的構建和部署。第四部分告訴Maven構建腳本安裝最新的Spring Boot Maven插件。此插件包含許多附加任務(如spring-boot:run),可以簡化Maven和Spring Boot之間的交互。

      最后,讀者將看到一條注釋,說明Maven文件的哪些部分已被刪除。為了簡化,本書沒有在代碼清單1-1中包含Spotify Docker插件。

      1.3.2 引導Spring Boot應用程序:編寫引導類

      我們的目標是在Spring Boot中運行一個簡單的微服務,然后重復這個步驟以提供功能。為此,我們需要在許可證服務微服務中創建以下兩個類。

      一個Spring引導類,可被Spring Boot用于啟動和初始化應用程序。

      一個Spring控制器類,用來公開可以被微服務調用的HTTP端點。

      如剛才所見,Spring Boot使用注解來簡化設置和配置服務。在代碼清單2-2中查看引導類時,這一點就變得顯然易見。這個引導類位于src/main/java/com/thoughtmechanix/licenses/Application.

      使用Spring Boot構建微服務(文末福利)(使用springboot的好處)

      java文件。

      代碼清單1-2 @SpringBootApplication注解簡介

      在這段代碼中需要注意的第一件事是@SpringBootApplication的用法。Spring Boot使用這個注解來告訴Spring容器,這個類是在Spring中使用的bean定義的源。在Spring Boot應用程序中,可以通過以下方法定義Spring Bean。

      (1)用@Component、@Service或@Repository注解標簽來標注一個Java類。

      (2)用@Configuration注解標簽來標注一個類,然后為每個我們想要構建的Spring Bean定義一個構造器方法并為方法添加上@Bean標簽。

      在幕后,@SpringBootApplication注解將代碼清單2-2中的Application類標記為配置類,然后開始自動掃描Java類路徑上所有的類以形成其他的Spring Bean。

      第二件需要注意的事是Application類的main()方法。在main()方法中,Spring Application.run(Application.class, args)調用啟動了Spring容器,然后返回了一個Spring?ApplicationContext對象(這里沒有使用ApplicationContext做任何事情,因此它沒有在代碼中展示。)。

      關于@SpringBootApplication注解及其對應的Application類,最容易記住的是,它是整個微服務的引導類。服務的核心初始化邏輯應該放在這個類中。

      1.3.3 構建微服務的入口:Spring Boot控制器

      現在已經有了構建腳本,并實現了一個簡單的Spring Boot引導類,接下來就可以開始編寫第一個代碼來做一些事情。這個代碼就是控制器類。在Spring Boot應用程序中,控制器類公開了服務端點,并將數據從傳入的HTTP請求映射到將處理該請求的Java方法。

      第一個控制器類LicenseSerriceController位于src/main/java/com/thoughtmechanix/licenses/controllers/LicenseServiceController.java中。這個類將公開4個HTTP端點,這些端點將映射到POST、GET、PUT和DELETE動詞。

      讓我們看一下控制器類,看看Spring Boot如何提供一組注解,以保證花最少的努力公開服務端點,使開發人員能夠集中精力構建服務的業務邏輯。我們將從沒有任何類方法的基本控制器類定義開始。代碼清單1-3展示了為許可證服務構建的控制器類。

      代碼清單1-3 標記LicenseServiceController為Spring?RestController

      我們通過查看@RestController注解來開始探索。@RestController是一個類級Java注解,它告訴Spring容器這個Java類將用于基于REST的服務。此注解自動處理以JSON或XML方式傳遞到服務中的數據的序列化(在默認情況下,@RestController類將返回的數據序列化為JSON)。與傳統的Spring?@Controller注解不同,@RestController注解并不需要開發者從控制器類返回ResponseBody類。這一切都由@RestController注解進行處理,它包含了@ResponseBody注解。

      代碼清單1-3中展示的第二個注解是@RequestMapping。可以使用@RequestMapping作為類級注解和方法級注解。@RequestMapping注解用于告訴Spring容器該服務將要公開的HTTP端點。使用類級的@RequestMapping注解時,將為該控制器公開的所有其他端點建立URL的根。

      在代碼清單1-3中,@RequestMapping(value="/v1/organizations/{organizationId}/licenses")使用value屬性為控制器類中公開的所有端點建立URL的根。在此控制器中公開的所有服務端點將以/v1/organizations/{organizationId}/licenses作為其端點的根。{organizationId}是一個占位符,表明如何使用在每個調用中傳遞的organizationId來參數化URL。在URL中使用organizationId可以區分使用服務的不同客戶。

      現在將添加控制器的第一個方法。這一方法將實現REST調用中的GET動詞,并返回單個License類實例,如代碼清單1-4所示(為了便于討論,將實例化一個名為License的Java類)。

      代碼清單1-4 公開一個GET HTTP端點

      這一代碼清單中完成的第一件事是,使用方法級的@RequestMapping注解來標記getLicenses()方法,將兩個參數傳遞給注解,即value和method。通過方法級的@Request Mapping注解,再結合類頂部指定的根級注解,我們將所有傳入該控制器的HTTP請求與端點/v1/organizations/{organizationId}/licences/{licensedId}匹配起來。該注解的第二個參數method指定該方法將匹配的HTTP動詞。在前面的例子中,以RequestMethod. GET枚舉的形式匹配GET方法。

      關于代碼清單 1-4,需要注意的第二件事是getLicenses()方法的參數體中使用了@PathVariable注解。@PathVariable注解用于將在傳入的URL中傳遞的參數值(由{parameterName}語法表示)映射為方法的參數。在代碼清單1-4所示的示例代碼中,將兩個參數organizationId和licenseId映射到方法中的兩個參數級變量:

      現在,可以將我們剛剛創建的東西稱為服務。在命令行窗口中,轉到下載示例代碼的項目目錄,然后執行以下Maven命令:

      一旦按下回車鍵,應該會看到Spring Boot啟動一個嵌入式Tomcat服務器,并開始監聽8080端口。

      服務啟動后就可以直接訪問公開的端點了。因為公開的第一個方法是GET調用,可以使用多種方法來調用這一服務。我的首選方法是使用基于Chrome的工具,如POSTMAN或CURL來調用該服務。圖1-5展示了在http://localhost:8080/v1/organizations/

      e254f8c-c442-4ebe-a82a-e2fc1d1ff78a/licenses/f3831f8c-c338-4ebe-a82a-e2fc1d1ff78a端點上完成的一個GET請求。

      現在我們已經有了一個服務的運行骨架。但從開發的角度來看,這服務還不完整。良好的微服務設計不可避免地將服務分成定義明確的業務邏輯和數據訪問層。

      我們來看看最后一個視角——探索DevOps工程師如何實施服務并將其打包以部署到云中。

      對于DevOps工程師來說,微服務的設計關乎在投入生產后如何管理服務。編寫代碼通常是很簡單的,而保持代碼運行卻是困難的。

      雖然DevOps是一個豐富而新興的IT領域,在本書后面,讀者將基于4條原則開始微服務開發工作并根據這些原則去構建。這些原則具體如下。

      (1)微服務應該是獨立的和可獨立部署的,多個服務實例可以使用單個軟件制品進行啟動和拆卸。

      (2)微服務應該是可配置的。當服務實例啟動時,它應該從中央位置讀取需要配置其自身的數據,或者讓它的配置信息作為環境變量傳遞。配置服務無需人為干預。

      (3)微服務實例需要對客戶端是透明的。客戶端不應該知道服務的確切位置。相反,微服務客戶端應該與服務發現代理通信,該代理將允許應用程序定位微服務的實例,而不必知道微服務的物理位置。

      (4)微服務應該傳達它的健康信息,這是云架構的關鍵部分。一旦微服務實例無法正常運行,客戶端需要繞過不良服務實例。

      這4條原則揭示了存在于微服務開發中的悖論。微服務在規模和范圍上更小,但使用微服務會在應用程序中引入了更多的活動部件,特別是因為微服務在它自己的分布式容器中彼此獨立地分布和運行,引入了高度協調性的同時也更容易為應用程序帶來故障點。

      從DevOps的角度來看,必須解決微服務的運維需求,并將這4條原則轉化為每次構建和部署微服務到環境中時發生的一系列生命周期事件。這4條原則可以映射到以下運維生命周期步驟。

      服務裝配——如何打包和部署服務以保證可重復性和一致性,以便相同的服務代碼和運行時被完全相同地部署?

      服務引導——如何將應用程序和環境特定的配置代碼與運行時代碼分開,以便可以在任何環境中快速啟動和部署微服務實例,而無需對配置微服務進行人為干預?

      服務注冊/發現——部署一個新的微服務實例時,如何讓新的服務實例可以被其他應用程序客戶端發現。

      服務監控——在微服務環境中,由于高可用性需求,同一服務運行多個實例非常常見。從DevOps的角度來看,需要監控微服務實例,并確保繞過微服務中的任何故障,而且狀況不佳的服務實例會被拆卸。

      圖1-6展示了這4個步驟是如何配合在一起的。

      1.4.1 服務裝配:打包和部署微服務

      從DevOps的角度來看,微服務架構背后的一個關鍵概念是可以快速部署微服務的多個實例,以應對變化的應用程序環境(如用戶請求的突然涌入、基礎設施內部的問題等)。

      為了實現這一點,微服務需要作為帶有所有依賴項的單個制品進行打包和安裝,然后可以將這個制品部署到安裝了Java JDK的任何服務器上。這些依賴項還包括承載微服務的運行時引擎(如HTTP服務器或應用程序容器)。

      這種持續構建、打包和部署的過程就是服務裝配(圖1-6中的步驟1)。圖1-7展示了有關服務裝配步驟的其他詳細信息。

      幸運的是,幾乎所有的Java微服務框架都包含可以使用代碼進行打包和部署的運行時引擎。例如,在圖2-7中的Spring Boot示例中,可以使用Maven和Spring Boot構建一個可執行的Java JAR文件,該文件具有嵌入式的Tomcat引擎內置于其中。以下命令行示例將構建許可證服務作為可執行JAR,然后從命令行啟動JAR文件:

      對某些運維團隊來說,將運行時環境嵌入JAR文件中的理念是他們在部署應用程序時的重大轉變。在傳統的J2EE企業組織中,應用程序是被部署到應用程序服務器的。該模型意味著應用程序服務器本身是一個實體,并且通常由一個系統管理員團隊進行管理,這些管理員管理服務器的配置,而與被部署的應用程序無關。

      在部署過程中,應用程序服務器的配置與應用程序之間的分離可能會引入故障點,因為在許多組織中,應用程序服務器的配置不受源控制,并且通過用戶界面和本地管理腳本組合的方式進行管理。這非常容易在應用程序服務器環境中發生配置漂移,并突然導致表面上看起來是隨機中斷的情況。

      將運行時引擎嵌入可部署制品中的做法消除了許多配置漂移的可能性。它還允許將整個制品置于源代碼控制之下,并允許應用程序團隊更好地思考他們的應用程序是如何構建和部署的。

      1.4.2 服務引導:管理微服務的配置

      服務引導(圖1-6中的步驟2)發生在微服務首次啟動并需要加載其應用程序配置信息的時候。圖1-8為引導處理提供了更多的上下文。

      任何應用程序開發人員都知道,有時需要使應用程序的運行時行為可配置。通常這涉及從應用程序部署的屬性文件讀取應用程序的配置數據,或從數據存儲區(如關系數據庫)讀取數據。

      微服務通常會遇到相同類型的配置需求。不同之處在于,在云上運行的微服務應用程序中,可能會運行數百甚至數千個微服務實例。更為復雜的是,這些服務可能分散在全球。由于存在大量的地理位置分散的服務,重新部署服務以獲取新的配置數據變得難以實施。

      將數據存儲在服務器外部的數據存儲中解決了這個問題,但云上的微服務提出了一系列獨特的挑戰。

      (1)配置數據的結構往往是簡單的,通常讀取頻繁但不經常寫入。在這種情況下,使用關系數據庫就是“殺雞用牛刀”,因為關系數據庫旨在管理比一組簡單的鍵值對更復雜的數據模型。

      (2)因為數據是定期訪問的,但是很少更改,所以數據必須具有低延遲的可讀性。

      (3)數據存儲必須具有高可用性,并且靠近讀取數據的服務。配置數據存儲不能完全關閉,否則它將成為應用程序的單點故障。

      1.4.3 服務注冊和發現:客戶端如何與微服務通信

      從微服務消費者的角度來看,微服務應該是位置透明的,因為在基于云的環境中,服務器是短暫的。短暫意味著承載服務的服務器通常比在企業數據中心運行的服務的壽命更短。可以通過分配給運行服務的服務器的全新IP地址來快速啟動和拆除基于云的服務。

      通過堅持將服務視為短暫的可自由處理的對象,微服務架構可以通過運行多個服務實例來實現高度的可伸縮性和可用性。服務需求和彈性可以在需要的情況下盡快進行管理。每個服務都有一個分配給它的唯一和非永久的IP地址。短暫服務的缺點是,隨著服務的不斷出現和消失,手動或手工管理大量的短暫服務容易造成運行中斷。

      微服務實例需要向第三方代理注冊。此注冊過程稱為服務發現(見圖1-6中的步驟3,以及圖1-9中有關此過程的詳細信息)。當微服務實例使用服務發現代理進行注冊時,微服務實例將告訴發現代理兩件事情:服務實例的物理IP地址或域名地址,以及應用程序可以用來查找服務的邏輯名稱。某些服務發現代理還要求能訪問到注冊服務的URL,服務發現代理可以使用此URL來執行健康檢查。

      然后,服務客戶端與發現代理進行通信以查找服務的位置。

      2.4.4 傳達微服務的“健康狀況”

      服務發現代理不只是扮演了一名引導客戶端到服務位置的交通警察的角色。在基于云的微服務應用程序中,通常會有多個服務實例運行,其中某些服務實例遲早會出現一些問題。服務發現代理監視其注冊的每個服務實例的健康狀況,并從其路由表中移除有問題的服務實例,以確保客戶端不會訪問已經發生故障的服務實例。

      在發現微服務后,服務發現代理將繼續監視和ping健康檢查接口,以確保該服務可用。這是圖1-6中的步驟4。圖1-10提供了此步驟的上下文。

      通過構建一致的健康檢查接口,我們可以使用基于云的監控工具來檢測問題并對其進行適當的響應。

      如果服務發現代理發現服務實例存在問題,則可以采取糾正措施,如關閉出現故障的實例或啟動另外的服務實例。

      在使用REST的微服務環境中,構建健康檢查接口的最簡單的方法是公開可返回JSON凈荷和HTTP狀態碼的HTTP端點。在基于非Spring Boot的微服務中,開發人員通常需要編寫一個返回服務健康狀況的端點。

      在Spring Boot中,公開一個端點是很簡單的,只涉及修改Maven構建文件以包含Spring Actuator模塊。Spring Actuator提供了開箱即用的運維端點,可幫助用戶了解和管理服務的健康狀況。要使用Spring Actuator,需要確保在Maven構建文件中包含以下依賴項:

      如果訪問許可證服務上的http://localhost:8080/health端點,則應該會看到返回的健康狀況數據。圖1-11提供了返回數據的示例。

      如圖1-11所示,健康狀況檢查不僅僅是微服務是否在運行的指示器,它還可以提供有關運行微服務實例的服務器狀態的信息,這樣可以獲得更豐富的監控體驗。

      云中的微服務看起來很簡單,但要想成功,卻需要有一個綜合的視角,將架構師、開發人員和DevOps工程師的視角融到一起,形成一個緊密結合的視角。每個視角的關鍵結論概括如下。

      (1)架構師——專注于業務問題的自然輪廓。描述業務問題域,并聽取別人所講述的故事,按照這種方式,篩選出目標備選微服務。還要記住,最好從“粗粒度”的微服務開始,并重構到較小的服務,而不是從一大批小型服務開始。微服務架構像大多數優秀的架構一樣,是按需調整的,而不是預先計劃好的。

      (2)軟件工程師——盡管服務很小,但并不意味著就應該把良好的設計原則拋于腦后。專注于構建分層服務,服務中的每一層都有離散的職責。避免在代碼中構建框架的誘惑,并嘗試使每個微服務完全獨立。過早的框架設計和采用框架可能會在應用程序生命周期的后期產生巨大的維護成本。

      (3)DevOps工程師——服務不存在于真空中。盡早建立服務的生命周期。DevOps視角不僅要關注如何自動化服務的構建和部署,還要關注如何監控服務的健康狀況,并在出現問題時做出反應。實施服務通常需要比編寫業務邏輯更多的工作,也更需要深謀遠慮。

      要想通過微服務獲得成功,需要綜合架構師、軟件開發人員和DevOps的視角。

      微服務是一種強大的架構范型,它有優點和缺點。并非所有應用程序都應該是微服務應用程序。

      從架構師的角度來看,微服務是小型的、獨立的和分布式的。微服務應具有狹窄的邊界,并管理一小組數據。

      從開發人員的角度來看,微服務通常使用REST風格的設計構建,JSON作為服務發送和接收數據的凈荷。

      Spring Boot是構建微服務的理想框架,因為它允許開發人員使用幾個簡單的注解即可構建基于REST的JSON服務。

      從DevOps的角度來看,微服務如何打包、部署和監控至關重要。

      開箱即用。Spring Boot允許用戶用單個可執行JAR文件交付服務。JAR文件中的嵌入式Tomcat服務器承載該服務。

      Spring Boot框架附帶的Spring Actuator會公開有關服務運行健康狀況的信息以及有關服務運行時的信息。

      《Spring微服務實戰》

      [美]約翰?卡內爾(John Carnell)著

      點擊封面購買紙書

      本書詳細介紹了微服務架構下Spring體系(Spring ->Spring Boot->Spring Cloud),幫助 Java 開發人員快速拆分單體應用,并對微服務的全生命流程進行了封裝,大大簡化了開發流程。

      本書以一個名為EagleEye的項目為主線,介紹云、微服務等概念以及Spring Boot和Spring Cloud等諸多Spring項目,并介紹如何將EagleEye項目一步一步地從單體架構重構成微服務架構,最終將這個項目拆分成眾多微服務,讓它們運行在各自的Docker容器中,實現持續集成/持續部署,并最終自動部署到云環境(Amazon)中。針對在重構過程中遇到的各種微服務開發會面臨的典型問題(包括開發、測試和運維等問題),本書介紹了解決這些問題的核心模式,然后在實戰中選擇特定Spring Cloud子項目或其他工具解決這些問題。

      本文轉載自異步社區

      微服務 Spring Boot Spring

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:excel設置表格尺寸的方法步驟詳解(excel表格怎么設置表格尺寸)
      下一篇:重構的原則(關于重構原則)
      相關文章
      亚洲国产精品无码久久九九大片| 亚洲日本在线观看| 亚洲成人免费网址| 亚洲av日韩av无码| 亚洲欧洲无码AV电影在线观看 | 激情小说亚洲图片| 亚洲精品无码不卡在线播放| 亚洲精品无码一区二区| 亚洲一区二区三区国产精华液| 国产午夜亚洲精品| 亚洲AV无码一区二区三区牛牛| 久久综合久久综合亚洲| 亚洲日韩精品无码AV海量| 亚洲色一区二区三区四区| 亚洲天然素人无码专区| 亚洲精品无码中文久久字幕| 国产精品亚洲专区无码WEB | 亚洲AV永久无码精品一福利 | 国产成人人综合亚洲欧美丁香花 | 亚洲免费综合色在线视频| 亚洲日韩精品无码专区| 蜜桃传媒一区二区亚洲AV| 亚洲人成网站999久久久综合| 亚洲av无码专区青青草原| 亚洲AV无码专区在线厂| 亚洲精品成人久久久| 亚洲人成影院在线无码观看| 久久久久亚洲精品男人的天堂| 亚洲精品~无码抽插| 亚洲狠狠综合久久| 亚洲人成网站日本片| 亚洲精品一二三区| 精品久久久久久亚洲综合网| 亚洲人成国产精品无码| 亚洲区小说区激情区图片区| 午夜亚洲AV日韩AV无码大全| 亚洲一级毛片中文字幕| 亚洲精品无码高潮喷水A片软| 无码专区一va亚洲v专区在线| 久久亚洲精品无码播放| 亚洲欧洲国产精品香蕉网|