日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

Spring Boot與微服務

微服務架構是當下構建互聯網應用的主流架構。在Spring家族中,專門有著用于構建微服務架構的Spring Cloud框架。而Spring Cloud框架本身則是構建在Spring Boot之上。

在本節中,我們將討論Spring Boot與SpringCloud的關系,并給出Spring微服務架構的案例分析。

微服務架構簡介

微服務架構是一種架構模式,區別于其他系統架構的構建方式和技術方案,微服務架構具有其固有特點。微服務架構的提出者Martin Fowler在其文章“Microservices”中定義了服務組件化、去中心化、基礎設施自動化等多個微服務架構特點,正是這些特點為我們使用微服務架構進行系統設計提供了主要的切入點。

從實施角度來講,我們可以基于這些微服務架構的特點提煉出構建微服務架構三大要素,即服務建模、技術體系和研發過程。

微服務架構設計首要的切入點在于服務建模,因為微服務架構與傳統SOA等技術架構的本質區別就是其服務的粒度不同,以及服務本身有面向業務和組件化的特性。針對服務建模,我們首先需要明確服務的類別以及服務與業務之間的關系,盡可能明確領域的邊界。對服務建模,推薦使用領域驅動設計(DomAIn Driven Design,DDD)方法,通過識別領域中的各個子域、判斷這些子域是否獨立、考慮子域與子域的交互關系,明確各個限界上下文(Boundary Context)之間的邊界。

微服務架構的第二大要素就是它的技術體系,這也是我們學習微服務架構的主體內容。同樣,不同的開發技術和框架都會基于自身的設計理念給出各自的技術體系類型及其實現方式。一個完整的微服務架構,通常需要包括服務通信、服務治理、服務路由、服務容錯、服務網關、服務配置、服務安全和服務監控等核心技術體系,如圖13-3所示。

圖13-3 微服務架構的核心技術體系

過程轉變與技術體系建設有密切關聯,所以對于微服務架構而言,最后一個要素就是研發過程。Martin Fowler在介紹微服務架構時,同樣也提出了“圍繞業務功能組織團隊”的研發管理理念。

本書關注Spring Boot及其生態系統,因此,我們的重點還是如何基于Spring家族來開發微服務架構。在Spring家族中,為開發人員提供了開發微服務架構整套解決方案的就是Spring Cloud框架。

Spring Cloud與Spring Boot

Spring Cloud具備一個天生的優勢,它是Spring家庭的一員,而Spring在JAVA EE開發領域的強大地位給Spring Cloud起到很好的推動作用。同時,Spring Cloud基于Spring Boot構建,而Spring Boot已經成為Java EE領域中最流行的開發框架,用來簡化Spring應用程序的框架搭建和開發過程。

在微服務架構中,我們將通過Spring Boot來開發單個微服務。同樣作為Spring家族的新成員,Spring Boot提供了令人興奮的特性,這些特性主要體現在開發過程的簡單化,包括支持快速構建項目、不依賴外部容器獨立運行、開發部署效率高以及與云平臺天然集成等,我們已經在前面的章節中對這些功能特性做了詳細的介紹。而在微服務架構中,Spring Cloud構建在Spring Boot之上,繼承了Spring Boot簡單配置和快速開發的特點,讓原本復雜的架構工作變得相對容易上手。

技術組件的完備性是Spring Cloud的主要優勢。Spring Cloud是一系列框架的有序集合。它利用Spring Boot開發的便利性巧妙地簡化了微服務系統基礎設施的開發過程,如服務發現注冊、API網關、配置中心、消息總線、負載均衡、熔斷器、數據監控等都可以使用Spring Boot的開發風格做到一鍵啟動和部署。

在對微服務的各項技術組件進行設計和實現的過程中,Spring Cloud也有一些自己的特色。一方面,它對微服務架構開發所需的技術組件進行了抽象,提供了符合開發需求的獨立組件,包括用于配置中心的Spring CloudConfig、用于API網關的Spring Cloud Gateway等。另一方面,Spring Cloud也沒有重復造輪子,它將目前各家公司比較成熟、經得起實踐考驗的服務框架組合起來,使用Spring Boot開發風格進行了再次封裝。這部分主要指的是Spring Cloud.NETflix組件。Spring Cloud Netflix基于Spring Boot集成了Netflix OSS中的諸多核心組件,其中與服務治理相關的除了用于服務注冊和發現的Eureka之外,實際上還有用于實現客戶端負載均衡的Ribbon和用于實現聲明式REST客戶端的Feign等。Netflix OSS、Spring Boot、Spring CloudNetflix以及Spring Cloud之間的關系如圖13-4所示。

圖13-4 Spring Cloud、Spring Cloud Netflix、Spring Boot與Netflix OSS之間的關系

Spring Cloud屏蔽了微服務架構開發所需的復雜的配置和實現過程,最終給開發者提供了一套易理解、易部署和易維護的開發工具包。SpringCloud中的組件非常多,本書不對圖13-4中的所有組件詳細講解,而是通過一個案例來展示Spring Cloud的使用方法,這就是接下來的內容。

 Spring微服務架構案例分析

本節將基于Spring Boot和Spring Cloud來演示微服務系統的構建過程,我們將結合案例重點介紹注冊中心、配置中心以及API網關這三個核心的微服務技術組件,以及如何在這三個技術組件的基礎上完成整個微服務系統的實現。

1. 案例業務場景和服務拆分

現在,讓我們構建一個精簡但又完整的系統來展示微服務架構的設計理念和常見實現技術。本案例的業務場景是訂單管理,需要對互聯網應用中最常見的商品、訂單業務做抽象。現實環境中訂單業務可以非常復雜,該案例的目的在于介紹系統實現的技術體系,不在于介紹具體業務邏輯,所以在業務領域建模上做了高度抽象和簡化。

按照實施微服務架構的基本思路,服務識別和拆分是案例分析的第一步。案例包含的業務場景比較簡單,主要針對用戶的下單操作。在提交訂單的過程中,我們需要對商品和用戶信息進行驗證。因此,我們可以把該過程對應的系統分成三個服務,即商品服務(goods-service)、訂單服務(order-service)和用戶服務(user-service)。

以上三個微服務構成了案例的業務服務,而若要構建一個完整的微服務系統,我們還需要引入其他基礎設施類服務,這些服務從不同的角度為實現微服務架構提供支持。在本書中,我們重點介紹注冊中心、配置中心和API網關這三個基礎設施類服務。無論是業務服務、還是基礎設施類服務,本質上它們都是一個Spring Boot應用程序。

2. 注冊中心

基于Spring Cloud實現注冊中心的方式有多種。在本文中,我們將采用Spring Cloud Netflix中的Eureka來構建用于服務發現和服務注冊的注冊中

心。Eureka同時具備服務器端組件和客戶端組件,其中客戶端組件內嵌在各個業務微服務中;而服務器端組件則是獨立的,所以需要構建一個Eureka服務,并將這個服務命名為eureka-server。

我們創建一個Spring Boot應用程序,并在該應用程序的pom文件中添加Eureka服務器端組件依賴包,如代碼清單13-23所示。

代碼清單13-23 Eureka服務器端依賴包

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-netflix-eureka

server</artifactId>

</dependency>

引入Maven依賴之后就可以創建Spring Boot的啟動類,在示例代碼中,我們把該啟動類命名為EurekaServerApplication,如代碼清單13-24所示。

代碼清單13-24 EurekaServerApplication類代碼

@SpringBootApplication

@EnableEurekaServerpublic class EurekaServerApplication {

public static void main(String[] args) {

SpringApplication.run(EurekaServerApplication.class, args);

}

}

請注意,在上面的代碼中,我們在啟動類上加了一個@EnableEurekaServer注解。在Spring Cloud中,包含@EnableEurekaServer注解的服務意味著就是一個Eureka服務器組件。

構建eureka-server的另一件事情是對Spring Boot的配置文件進行處理,并添加如代碼清單13-25所示的配置項。

代碼清單13-25 eureka-server配置

eureka:

client:

registerWithEureka: false

fetchRegistry: false

serviceUrl:

defaultZone: http://localhost:8761

在這些配置項中,我們看到了三個以eureka.client開頭的客戶端配置項,分別是register-WithEureka、fetchRegistry和serviceUrl。從配置項的命名上不難看出,registerWithEureka用于指定是否把當前的客戶端實例注冊到Eureka服務器中,而fetchRegistry則指定是否從Eureka服務器上拉取服務注冊信息。這兩個配置項默認都是true,但這里都將其設置為false。而最后的serviceUrl配置項用于設置服務地址。

3. 配置中心

與Eureka一樣,基于Spring Cloud Config構建的配置中心同樣存在服務器端組件和客戶端組件,其服務器端組件也需要構建一個獨立的配置服務。我們將這個服務命名為config-server,并在pom文件中引入spring-cloudconfig-server和
spring-cloud-starter-config這兩個Maven依賴,其中前者包含了用于構建配置服務器的各種組件,如代碼清單13-26所示。

代碼清單13-26 Spring Cloud Config服務器依賴包

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-config-server</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-config</artifactId>

</dependency>

接下來我們在新建的config-server工程中添加一個Bootstrap類ConfigServerApplication,如代碼清單13-27所示。

代碼清單13-27 ConfigServerApplication類代碼

@SpringCloudApplication

@EnableConfigServer

public class ConfigServerApplication {

public static void main(String[] args) {

SpringApplication.run(ConfigServerApplication.class, args);

}

}

除了熟悉的@SpringCloudApplication注解之外,我們還看到這里添加了一個新的注解@EnableConfigServer。有了這個注解,配置服務器就可以將所存儲的配置信息轉化為RESTful接口數據供各個業務微服務在分布式環境下使用。

同樣,在config-server工程的配置文件中,我們也需要添加與配置中心相關的配置項,如代碼清單13-28所示。

代碼清單13-28 config-server配置

spring:

cloud:

config:

server:

native:

searchLocations: classpath: config/

classpath: config/userservice,

classpath: config/goodsservice,

classpath: config/orderservice

可以看到,這里通過searchLocations配置項設置了Spring CloudConfig從本地文件系統中讀取配置文件的目錄,分別是config目錄下的userservice、goodsservice和orderservice這三個子目錄。請注意這三個子目錄的名稱必須與各個服務自身的名稱完全一致。然后我們在這三個子目錄下面都放入以服務名稱命名的針對不同運行環境的.yml配置文件。

4. API網關

對于API服務而言,無論是使用Spring Cloud Netflix中的Zuul還是使用Spring自建的Spring Cloud Gateway,都需要構建一個獨立的服務來承接路由、安全和監控等各種功能。這里,我們以Spring Cloud Gateway為例構建一個獨立的gateway-server服務。在技術上,Spring Cloud Gateway基于最新的Spring 5和Spring Boot 2,以及用于響應式編程的Project Reactor框架,提供響應式、非阻塞式I/O模型,所以Spring Cloud Gateway為開發人員提供了更好的性能支持。要想在微服務架構中引入Spring Cloud Gateway,我們同樣需要構建一個獨立的Spring Boot應用程序,并在Maven中添加如代碼清單13-29所示的依賴項。

代碼清單13-29 Spring Cloud Gateway依賴包

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-gateway</artifactId>

</dependency>

按照約定,我們把這個獨立的微服務命名為gateway-server,然后在作為Bootstrap類的GatewayApplication上添加@EnableDiscoveryClient注解即可,如代碼清單13-30所示。

代碼清單13-30 GatewayApplication類代碼

@SpringBootApplication

@EnableDiscoveryClient

public class GatewayApplication {

public static void main(String[] args) {

SpringApplication.run(GatewayApplication.class, args);

}

}

Spring Cloud Gateway中的核心概念有兩個,一個是過濾器,一個是謂詞(Predicate)。Spring Cloud Gateway中的過濾器用于在響應HTTP請求之前或之后修改請求本身及對應的響應結果。而所謂謂詞,本質上是一種判斷條件,用于將HTTP請求與路由進行匹配。接下來,我們通過一個完整的路由配置來展示謂詞和過濾器規則的配置方法,如代碼清單13-31所示。

代碼清單13-31 gateway-server配置

spring:

cloud:

gateway:

discovery:

locator:

enabled: true

routes:

- id: user-route

uri: lb://userservice

predicates:

- Path=/user/**

- id: goods-route

uri: lb://goodsservice

predicates:

- Path=/good/**

- id: order-route

uri: lb://orderservice

predicates:

- Path=/order/**

在上述配置中,有幾個注意點。首先我們使用id配置項為三個業務服務指定了路由信息的規則編號,分別為user-route、goods-route和orderroute。而uri配置項中的lb代表負載均衡LoadBalance,也就是說在訪問URL指定的服務名稱時需要集成負載均衡機制。請注意lb配置項中指定的服務名稱需要與保存在Eureka中的服務名稱完全一致。然后我們使用了謂詞來對請求路徑進行匹配,例如這里的Path=/order/**代表所有以/order開頭的請求都將被路由到這條路徑中。

5. 業務服務整合

接下來,我們基于前面構建的基礎設施服務來實現各個業務服務。我們知道,各個業務服務本質上都是一個Spring Boot應用程序。在這些SpringBoot應用程序中,首先需要引入Spring Cloud組件,如代碼清單13-32所示。

代碼清單13-32 Spring Cloud依賴包

<dependencies>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-dependencies</artifactId>

<version>2020.0.3</version>

<type>pom</type>

<scope>import</scope>

</dependency>

</dependencies>

同時,作為微服務系統中的單個微服務,這些Spring Boot應用程序都應該注冊到Eureka注冊中心,并完成與配置中心的集成。因此,在pom文件中,我們也需要添加如代碼清單13-33所示的依賴項。

代碼清單13-33 注冊中心和配置中心客戶端依賴包

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-netflix-eureka

client</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-config</artifactId>

</dependency>

<dependency> <groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-config-client</artifactId>

</dependency>

對應地,在配置文件中,我們也需要分別添加對注冊中心和配置中心的引用,如代碼清單13-34所示。

代碼清單13-34 注冊中心和配置中心客戶端配置項

eureka:

instance:

preferIpAddress: true

client:

registerWithEureka: true

fetchRegistry: true

serviceUrl:

defaultZone: http://localhost:8761/eureka/

spring:

cloud:

config:

enabled: true

uri: http://localhost:8888

現在,order-service、user-service和goods-service這三個業務服務都融入了微服務架構的體系中,接下來要做的就是根據業務邏輯實現業務服務之間的整合。在案例中,我們以最典型的下訂單業務流程為例,給出在微服務架構下業務服務之間整合的實現過程。

通常,在用戶下訂單的過程中,我們需要傳入用戶信息以及商品信息,然后系統通過校驗用戶信息和商品信息的正確性來決定是否生成一個合法的訂單。在這個過程中,order-service需要基于REST API完成與user-service和goods-service之間的遠程交互,如圖13-5所示。

圖13-5 業務服務交互關系圖

在order-service中,我們將暴露一個用于生成訂單的HTTP端點,如代碼清單13-35所示。

代碼清單13-35 OrderController中的HTTP端點

@RestController

@RequestMapping(value = "orders")

public class OrderController {

@Autowired

OrderService orderService;

@GetMapping(value = "/{userId}/{goodsCode}")

public Order addOrder(@PathVariable("userId") String userId,

@PathVariable("goodsCode") String goodsCode) {

return orderService.generateOrder(userId, goodsCode);

}

}

可以看到,在上述addOrder()方法中,我們傳入用戶的ID以及商品的編號,并調用OrderService來生成訂單。在OrderService中,負責具體生成訂單信息的generateOrder()方法如代碼清單13-36所示。

代碼清單13-36 OrderService中的generateOrder()方法實現代碼

public Order generateOrder(String userId, String goodsCode) {

Order order = new Order();

//獲取遠程Goods信息

GoodMapper goods = getGoodsFromRemote(goodsCode);

if (goods == null) {

return order;

}

//獲取遠程User信息

UserMapper user = getUserFromRemote(userId);

if (user == null) {

return order;

}

order.setOrderNumber("DemoOrderNumber");

order.setDeliveryAddress("DemoDeliveryAddress");

order.setUserId(userId);

order.setGoodsName(goods.getName());

order.setCreateTime(new Date());

orderRepository.save(order);

return order;

}

上述方法的執行流程非常明確,我們分別通過getGoodsFromRemote()和getUserFromRemote()方法遠程獲取商品信息和用戶信息。這個過程就涉及微服務之間的相互調用。這里以getUserFromRemote()方法為例,來看對應的UserRestTemplateClient遠程訪問工具類的實現過程,如代碼清單13-37所示。

代碼清單13-37 UserRestTemplateClient類實現代碼

@Service

public class UserRestTemplateClient {

@Autowired RestTemplate restTemplate;

public UserMapper getUserById(String userId) {

ResponseEntity<UserMapper> result =

restTemplate.exchange("http://userservice/users/{userId}",

HttpMethod.GET, null, UserMapper.class, userId);

return result.getBody();

}

public UserMapper getUserByUserName(String userName) {

ResponseEntity<UserMapper> result =

restTemplate.exchange("http://userservice/users/userName/{userName}",

HttpMethod.GET, null, UserMapper.class, userName);

UserMapper user = result.getBody();

return user;

}

}

這里我們通過RestTemplate發起HTTP請求并獲取響應結果,整個遠程調用過程與第4章介紹的內容完全一致。唯一的區別在于這里請求URL使用的并不是一個具體的IP地址,而是對應微服務的服務名userservice。能夠實現這一效果的原因是Spring Cloud可以對默認的RestTemplate做改造,如代碼清單13-38所示。

代碼清單13-38 添加了@LoadBalanced注解的RestTemplate

@Bean

@LoadBalanced

public RestTemplate getRestTemplate(){

return new RestTemplate();

}

可以看到,我們在創建的RestTemplate上添加了一個@LoadBalanced注解。@LoadBalanced注解用于修飾發起HTTP請求的RestTemplate工具類,在該工具類中自動與注冊中心集成,并嵌入客戶端負載均衡功能。這樣,開發人員不需要針對負載均衡做任何特殊的開發或配置,就能實現基于服務名進行遠程方法調用。

請注意,上述實現方式中我們并沒有集成API網關功能。想要發揮SpringCloud Gateway所引入的服務路由機制,基于前面配置的路由規則,我們可以采用如代碼清單13-39所示的實現方式。

代碼清單13-39 通過API網關執行遠程服務調用的實現代碼

public UserMapper getUserById(String userId) {

ResponseEntity<UserMapper> result =

restTemplate.exchange("http://gatewayservice/user/users/{userId}",

HttpMethod.GET, null, UserMapper.class, userId);

return result.getBody();

}

本文給大家講解的內容是監控和擴展:SpringBoot生態體系及擴展,Spring Boot與微服務

分享到:
標簽:SpringBoot
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定