實例解讀:如何基於Java構建實際可用的微服務?

編程語言 JSON XML 設計模式 IT168企業級 2017-08-02

“微服務架構”是現在編程中很流行的概念,未來能和最新趨勢保持同步,我也一直在學習瞭解這個架構,如果具體點說,我一直在尋找一種使用Spring在Java中實現微服務架構的方法。

為什麼我會有這個想法,這是有一定的背景的:我們公司很好但是卻有一個過時的技術堆棧,基本上沒有使用Java 8或者微服務器。所以我想要了解關於微服務器的事情,必須自己去收集學習,為此我創建了一個待辦事項系統,記錄我的學習經歷以供將來參考!

實例解讀:如何基於Java構建實際可用的微服務?

概述

本文的目的是為不同微服務提供源代碼演練,不會深入解讀概念和工具,主要是介紹一個包含用於開發微服務的模式、工具和技術的應用示例。

既然是一個參考應用程序,我會使它儘量簡單,源碼易於理解!本文中,這個待辦事項系統應用程序由8個部分組成:

  • Reminder

  • User

  • Service discovery server

  • Mailer

  • OAuth Server

  • System integration test

  • API Gateway

  • Web application client

系統如何與Microservices交互

實例解讀:如何基於Java構建實際可用的微服務?

上圖中顯示了系統與所有微服務器的交互,用戶訪問使用Angular 2編寫的Web應用程序。然後連接到OAuth授權服務器,OAuth授權服務器將是可以分配用戶和權限的中心點。此服務器將返回一個JSON Web令牌,其中包含客戶端及其權限的信息以及格式範圍。在用戶認證並具有令牌之後,Web應用程序與API網關通信。通過JWT來驗證它是否來自授權服務器,然後調用微服務器並構建響應。

OAuth服務器使用用戶服務來獲取用戶的身份驗證詳細信息。此外,API網關使用OAuth服務器來獲取用戶的信息。

Remainder Service由ToDo功能來提供,,ToDo服務有一個計劃工作來檢查並通過電子郵件通知用戶,電子郵件由郵件服務發送,該事件使用Kafka的事件提醒服務觸發。

系統集成測試是一個Java應用程序,負責到達提醒服務的端點。

連接微服務

在微服務體系結構中,我們必須處理許多在不同IP和端口上運行的微服務器。因此,我們需要找到一種無需硬編碼來管理每個地址的方式。

這就需要用到Netflix Eureka,它是客戶端服務發現,允許服務自動查找和相互通信。我們在系統中使用了Spring Cloud Eureka,如果Eureka查找到服務運行的位置,我們就可以添加實例並應用負載平衡來在微服務器之間分配傳入的應用流量。

在系統中,我們使用Netflix Ribbon作為客戶端負載均衡器,實現容錯,並通過冗餘增加可靠性和可用性。我們使用Netflix Foreign編寫聲明性REST客戶端,並集成Ribbon和Eureka來提供負載平衡HTTP客戶端。

我們的系統中存在一些依賴。我們正在使用Netflix Hystrix斷路器將應用程序與依賴性故障隔離開來。它有助於阻止級聯故障,並允許快速恢復或添加後備。Hystrix為每個依賴關係維護一個線程池,如果線程池耗盡,它會拒絕請求。它還提供斷路器功能,可以停止對依賴關係的所有請求。當請求失敗,拒絕或超時時,還可以實現備用邏輯。

認證

開發任何類型的系統時,安全性都是非常重要的,微服務架構也沒什麼不同。當“如何保持微服務的安全性?”這個問題出現時,我的第一個答案是OAuth2。OAuth2絕對是一個很好的解決方案:它是一種眾所周知的授權技術,廣泛應用於Google,Facebook和Github。

當然沒有Spring Security的情況下,是不可能談論安全的。。在討論分佈式系統的安全性時,Spring Security和OAuth2是顯而易見的選擇。

不過,我們在安全問題上還增加了一個元素:JSON Web Token(JWT)。如果僅使用OAuth,我們需要一個OAuth授權服務器來驗證用戶,生成令牌,並充當資源服務器的端點,詢問該令牌是否有效以及授權的權限。與授權服務器相比,這需要兩倍的請求。而JWT提供了一種在訪問令牌中傳輸權限和用戶數據的簡單方法,一旦所有數據都已經在令牌字符串中,資源服務器就不需要請求令牌檢查。所有信息都被序列化為JSON,用base64編碼,最後用私有RSA密鑰簽名。

您可以查看OAuth2授權服務器(OAuth-server)和資源服務器(API Gateway)的代碼實現。

REST

在系統中,我們有兩種交互方式:同步和異步。異步,我們使用了分佈式事件與Kafka,遵循發佈/訂閱模型。同步,我們支持了JSON和XML的REST風格。

Martin Fowler認為RESTful可以分為四個級別,level 0-level 3。我們的微服務處於level 2,為了簡單起見,這裡不使用HATEOAS設計模式實現超媒體控件。

因為我們使用了Spring Cloud,所以必須實現開箱即用的可擴展性模式,將其放在HTTP連接中,例如:斷路器,負載平衡,連接池,超時和重試等。

分佈式事件

如上所述,我們通過使用Kafka 進行提醒服務和 Mailer服務之間的通信,並異步地與其他Microservices進行通信。在提醒服務中,我們有一個計劃任務來檢查提醒時間,併發布RemainderFound事件。Mailer服務中將會有一個訂閱的事件,向用戶發送電子郵件。

Event sourcing和 CQRS

單片應用通常具有單個關係數據庫。我們可以使用ACID交易。因此,如果出現問題,我們的應用程序可以簡單地開始一個事務,更改多個行,並提交事務,如果錯誤的話,還可以恢復到之前。不幸的是,處理微服務架構中的數據訪問要複雜得多。這些數據分佈在不同的數據庫中,跨多個服務實施業務交易是一個很大的挑戰。

在“ToDo”項目中,我們使用事件來處理跨多個服務的業務事務。 您可以查看在Mailer服務中應用的CQRS實施事件。 可以看到如何分離讀和寫,輕鬆地縮放每個部分。 我們使用關係數據庫作為事件存儲,然後使用Kafka分發事件。 當然我們需要將這兩個動作定義為原子操作並避免存儲事件,這樣就不會導致JVM崩潰。 不使用Kafka作為事件存儲,是因為從關係數據庫構建聚合更簡單。

未來的計劃

您可能也注意到這個項目中尚且還有很多事情尚未解決,這是一個開發中的項目,未來我們會添加更多的東西,例如Spring雲配置,Docker容器,與Jenkins的持續集成,Spring Sleuth的分佈式跟蹤,ELK的日誌管理等。

相關推薦

推薦中...