上篇文章總結了《深入實踐Spring Boot》的第一部分,這篇文章介紹第二部分:分散式應用開發,以及怎麼構建一個高效能的服務平臺。
主要從以下幾個方面總結:
- Spring Boot SSO
- 使用分散式檔案系統
- 雲應用開發
- 構建高效能的服務平臺
Spring Boot SSO
上篇文章提到了安全設計,使用Spring Security進行使用者驗證和許可權驗證,但一個企業級的應用系統可能存在很多應用系統,每個應用系統都需要設計安全管理,但不可能為每一個應用系統都設計一套安全管理,這樣不但耗時耗力,而且要做重複的工作,也不適宜建立統一的使用者中心。
可以使用單點登入SSO的方式建立一個登入認證系統,並且實現對使用者的統一管理。本章在使用Spring Security安全管理的基礎上,再結合OAuth2認證授權協議來實現的,它不但適用於大型的分散式管理系統,也適用於為第三方提供統一的使用者管理和認證的平臺。
作者給出了一個完整的例項,以模組化的設計方式進行實現,整個demo的程式碼可以在github上檢視。(github.com/chenfromsz/…)
demo說明
我在本地執行了demo,通過chrome檢視了系統間跳轉的過程,先說明下模組的劃分,然後看下執行效果。
專案 | 工程 | 型別 | 功能 |
---|---|---|---|
資料庫管理模組 | mysql | 程式整合 | 資料庫管理 |
安全配置模組 | security | 程式整合 | 安全策略配置和許可權管理 |
登入認證模組 | login | Web應用 | SSO登入認證(80) |
共享資源模組 | resource | Web應用 | 共享資源(8083) |
客戶端應用1 | web1 | Web應用 | 客戶端1(8081) |
客戶端應用2 | web2 | Web應用 | 客戶端2(8082) |
訪問首頁時,跳轉到登入頁面,輸入正確的賬號、密碼、驗證碼。 登入成功後,跳轉到首頁:
訪問web1系統、web2系統時不需要重新登入,會自動登入:
「登入認證模組」主要包括驗證使用者賬號、整合OAuth2服務端端功能。
「安全配置模組」是一個公共模組,整合了SSO客戶端的安全策略配置和許可權管理功能,供客戶端引用。
「資料庫管理模組」是一個公共模組,主要提供資料庫的訪問功能,供其他模組使用。
「共享資源模組」提供了一個簡單的公共服務,2個客戶端應用可通過spring-cloud-zuul直接呼叫。
後面會重點介紹下登入認證模組,其他模組比較簡單,不再過多介紹。
模組化設計可以提高程式碼的複用性,避免重複開發,例項中的「資料庫管理模組」和「安全配置模組」可以被其他模組共用,減少大部分重複工作。 作者的這種設計方式值得我們學習,在以後的系統設計中,應多借鑑這種方式。
登入認證模組
我畫了一個流程圖,先了解下使用者認證、許可權驗證的基本過程:
整個處理流程,Spring Security都幫我們自動實現了,我們只需要對賬號中心資料來源、許可權中心資料來源進行配置和擴充套件,另外,可以對登入頁面進行擴充套件,配置許可權管理規則、防攻擊策略、記住登入狀態。
為了實現多個系統只需登入一次,需要整合OAuth2。新增spring-cloud-starter-oauth2依賴,編寫一個配置類,繼承AuthorizationServerConfigurerAdapter,並宣告下@EnableAuthrizationServer來啟用OAuth2的認證伺服器功能。
OAuth2有很多授權機制,本例中使用authorization_code機制,具體配置就不過多說明了,可以參考下面的幾篇文章:
[1] 初步理解Spring Security並實踐 [2] security OAuth2.0 提供者實現原理 [3] jwt token介紹 [4] security OAuth2.0 jwt完美整合例子
使用分散式檔案系統
有這樣一個問題,如果上傳檔案,如上傳圖片,應該怎樣儲存,儲存在哪裡?
傳統的做法一般都儲存在Web伺服器所在機器中。但隨著業務的日益發展,可能上傳的檔案會累積越來越多,單臺機器往往會不堪重負,再加上一些負載均衡的配置和服務,需要分散式檔案系統解決。
在諸多分散式的檔案系統中,FastDFS是比較優秀的分散式檔案系統。FastDFS是一個完全開源的分散式檔案系統,使用比較簡單方便,而且效能也很優秀,儲存容量和訪問效能可按需求進行線性橫向擴充套件。
FastDFS服務端和客戶端的安排、配置、管理都比較簡單,書中描述的也比較詳細,就不在此贅述了。
雲應用開發
Spring Cloud 是一套雲應用開發工具集,為分散式的微服務開發提供了一整套簡單易用的使用工具。Spring Cloud主要包括配置管理、服務發現、動態路由、負載均衡、斷路器、安全管理、事件匯流排、分散式訊息等元件的開發工具包。
Spring Cloud與Spring Boot 關係密切,能夠臻於完美的幾何使用。
本章重點介紹了配置服務、發現服務、動態路由和斷路器、監控服務。
配置服務
一個專案工程總是需要一些配置,比如,要配置伺服器的埠、訪問資料庫的引數等。一個大型的分散式系統可能存在很多這樣需要配置的專案工程,配置管理是一個龐大的工程,需要一個單獨的系統專門管理各個專案的配置。
通過Spring Cloud的配置管理,只需建立一個簡單的工程,就可以實現分散式配置管理服務,同時還支援線上更新。
第一步,配置管理伺服器 引入spring-cloud-config-server依賴,建立一個主程式:
@SpringBootApplication
@EnableConfigServer
@EnableDiscoveryClient
public class ConfigApplication{
public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class, args);
}
}
複製程式碼
配置檔案的儲存目前支援使用本地儲存、Git以及Subversion等方式。以Git方式為例,說明本地配置檔案:
spring:
cloud:
config:
server:
git:
uri: https://github.com/chenfromsz/spring-cloud-config-repo
rabbitmq:
addresses: ${vcap.services.${PREFIX:}rabbitmq.credentials.uri:amqp://${RABBITMQ_HOST:192.168.1.215}:${RABBITMQ_PORT:5672}}
username: alan
password: alan
複製程式碼
服務端會自動從指定的git地址獲取配置資訊。raabitmq的配置用於通知客戶端應用配置更新。
第二步,配置管理的客戶端 需要在工程中引入spring-cloud-starter-config依賴,使用配置管理服務之後,如果本地的配置檔案與配置管理伺服器的配置檔案有相同的配置項,將優先使用配置管理伺服器的配置項。
客戶端的配置檔案bookstrap.yml如下:
spring:
application:
name: data
profiles:
active: development
cloud:
config:
uri: http://localhost:8888
rabbitmq:
addresses: amqp://192.168.1.214:5672
username: alan
password: alan
複製程式碼
其中,name用來指定應用的名稱和配置檔案的名稱,uri設定配置服務服務端的地址和埠,profiles為使用配置檔名稱的字尾部分,用於繫結不同的線上環境。
第三步,使用配置 如果配置檔案中有cloud.config.test配置項,可以這樣使用
@Value("${cloud.config.test:World!}") String msg;
複製程式碼
另外,可以使用spring-cloud-bus-amqp依賴,通過事件匯流排的方式,實現線上更新所有客戶端的配置。
發現服務
在分散式系統中,可能存在很多應用和服務,各個服務瀆職自主地管理自身的資料。服務與服務之間,需要互相共享一些資料,傳統的方式需要自己編寫一些介面程式,還需要使用複雜的配置來實現,使用Spring Cloud可以輕易做到這些。
第一步,建立發現伺服器 引入spring-cloud-starter-eureka-server依賴,建立一個簡單的主程式即可:
@SpringBootApplication
@EnableEurekaServer
public class DiscoveryApplication {
public static void main(String[] args) {
SpringApplication.run(DiscoveryApplication.class, args);
}
}
複製程式碼
第二步,建立客戶端 引入spring-cloud-starter-eurake依賴,主程式中加入@EnableDiscoveryClient啟用發現服務的客戶端。
配置檔案如下:
eureka:
instance:
hostname: discovery
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://192.168.1.221:${server.port}/eureka/
複製程式碼
動態路由和斷路器
如何在服務間相互呼叫呢,可以使用動態路由、斷路器和故障容錯等功能。
引入spring-cloud-starter-zuul、spring-cloud-starter-hystrix依賴,新增@EnableZuulProxy和@EnableHystrix註解即可。
為了便於測試,可以通過共享Rest資源將repository的類直接暴露出來,很神奇吧,如下:
@RepositoryRestResource(collectionResourceRel="users",path="users")
public interface UserRepository extends GraphRepository<User> {
User findByName(@Param("name") String name);
@Query("MATCH (u:User) WHERE u.name =~ ('(?i).*'+{name}+'.*') RETURN u")
Collection<User> findByNameContaining(@Param("name") String name);
}
複製程式碼
可以通過http://localhost/users , http://localhost/users/123 之類的方式訪問。
通過以下3種方式呼叫其他服務對外暴露的介面:
- JavaScript:前端直接呼叫
- RestTemplate:後端呼叫
- FeignClient:特殊方式
以RestTemplate為例說明一個服務呼叫data服務的例子:
@Autowired @LoadBalanced
RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "getUserFallback")
public User getUserByName(String name) {
Map<String, Object> params = new HashMap<>();
params.put("name", name);
User user = restTemplate.getForObject("http://data/user/findByName?name={name}", User.class, params);
return user;
}
複製程式碼
上面例子中使用了@HystrixCommand用於實現斷路器,當一個系統服務突然出現故障時,會自動阻斷對服務的訪問和呼叫,轉而呼叫備用方法。
監控服務
分散式服務系統中執行著很多服務,必須有一個管理機制和方法,能夠一目瞭然地隨時瞭解各個服務的執行情況及其健康指數。
使用Spring Cloud的監控服務,可以實時監控應用的執行情況。使用很簡單,引入spring-cloud-starter-hystrix-dashboard依賴,建立一個主程式即可:
@SpringBootApplication
@Controller
@EnableHystrixDashboard
public class HystrixApplication{
@RequestMapping("/")
public String home() {
return "forward:/hystrix";
}
public static void main(String[] args) {
SpringApplication.run(HystrixApplication.class, args);
}
}
複製程式碼
具體監控指標可參看官網文件。
構建高效能的服務平臺
使用Spring Cloud開發的微服務,其獨立而又相對隔離的特性,與Docker的理念有異曲同工之妙,所以使用Docker釋出微服務,能夠發揮其最大的優勢,並且可以非常輕易地構建一個高效能和高可用的服務平臺。
Docker可以很方便地建立和管理映象,以及管理已經生成的和正在執行的容器。映象是一種檔案儲存方式,可以把許多檔案做成一個映象檔案。容器是映象執行的一個例項,執行一個映象,就會生成一個容器,容器生成之後,就可以在容器中管理應用系統了。
Docker的安裝和釋出服務,網上的資料很多,這裡就不贅述了。
另外,可以使用其他一些服務管理工具來構建高效能和高可用的服務平臺。docker-compose工具是Docker容器管理工具集,可以很方便地用來建立和重建容器、執行啟動和停止容器等管理操作,以及檢視整個服務體系的執行情況和輸出日誌等。使用docker-compose工具,只要一條指令就能啟動整個分散式服務體系。
通過本篇文章的介紹,大家可以感受到Spring Cloud在構建分散式應用時提供的便捷性,減少了大量的工作量。同時為我們考慮了方方面面,增強了系統的穩定性、高效能。 作者把所有程式碼都上傳到github,大家可以直接執行demo深入瞭解。 [1] Spring Boot SSO:https://github.com/chenfromsz/spring-boot-sso [2] 雲應用開發:https://github.com/chenfromsz/spring-boot-cloud