1. 程式人生 > 其它 >Spring Cloud 詳細入門系列(一)

Spring Cloud 詳細入門系列(一)

仔細讀完,可掌握 Spring Cloud EureKa 服務註冊與發現的基本流程,以及多註冊中心叢集配置的基本要素。

在入門前,第一件事是瞭解全貌。

首先,讓我們先大概知悉 Spring Cloud 能為我們做到什麼。

從官網、各類部落格、以及相關技術類論壇中提煉了下述比較關鍵的作用,這也是它大放異彩的基本要素:

  1. 微服務框架,提供全套的分散式系統解決方案,比較傳統的技術,會更加穩定且具有容錯性;
  2. 只作整合封裝(挺多開源框架與元件,包括對 SpringBoot 的深度整合,繼承了其優秀的“約定大於配置”,能通過註解以及 yml 進行配置)
  3. 對開發者友好,十分容易上手,如配置、斷路機制、選舉、分散式 session、狀態管理等常規處理提供了簡便的操作,便於上手。
  4. 對 IDE 其實也友好,只要支援 Spring Boot,基本上也能開發 Spring Cloud,例如我的 VsCode 就可以進行使用。

第三點最為重要,決定了這項技術是否是通用的,或者是僅適用小部分組織,目前來看,它甚至適用於個人開發。

瞭解 Spring Cloud 的基礎概念「重要」

截至至此隨筆的釋出日期,目前的Spring Cloud有著下述的基本概念,先嚐試理清楚它們之間的關係,然後逐個實踐,這樣有助於你繼續瞭解此框架。

  • EureKa(服務註冊與發現)
  • Config(分散式統一管理配置)
  • Zuul(服務閘道器)
  • Ribbon(客戶端負載均衡器)
  • Feign(宣告 Web 服務客戶端)
  • Hystrix(斷路器「熔斷器」

上述概念僅需記憶中文即可,因為除了核心服務外,其餘都是類似於積木的存在,是可被替換的,例如服務閘道器 Spring Cloud Zuul,也可能被替換為 Spring Cloud Gateway,故此特別說明;

嗯。。怎麼說呢,積木的形狀是確切的,但是顏色我們管不著,所以只需要記住形狀就可以。

那麼,它們之間的關係是怎樣的呢?

圖來自網路,大概講解一下:

整體來說,就像是一個有序的機構:既有招待 client 的服務員,指引他們到各個分工明確的視窗辦理業務,也有保安針對某視窗排隊人數過多的情況進行處理,比如讓新來的人先去其它視窗,這個視窗先不開放。。

而這個機構的名字就叫做“服務註冊與發現”,內部是各類服務,有序且分工明確。機構之間能產生互動,即叢集,在此篇隨機也有提及,如雙註冊服務中心,當然你也能套娃,三個四個五個也是看你需求了。

現在你不會發懵了吧,起碼瞭解了大概的流程、以及 Spring Cloud 究竟是幹啥的,如果不瞭解,請先放下你的中指,然後再多看一遍。

開始實踐:服務註冊與發現

ps:其餘本篇不介紹,接下來也僅有 EureKa 的實踐和說明,比如雙註冊,多註冊的形式,假設你想了解閘道器之類的其它“積木”,那麼你開啟錯隨筆了,可以看看首頁是否有此係列的續篇,如果沒有的話就下次一定。

筆者僅學習了半天,並實踐完成,過程中一次通過,花了些時間寫了隨筆,如果有錯誤麻煩你在評論區留言,我會進行修改。

在開始之前,你應該時刻注意“版本號”的依賴,事實上,學習的開始最應該注意的就是這些細節了,否則你一定會遇到報錯。

另外,已經假設你初始化了 Spring Boot 的框架環境,通常各種 IDE 都具備新建 Spring Boot 專案。

可進入官網檢視粗略的依賴情況,每個版本號又會細分很多種,可以選擇相鄰日期來推測合適的依賴。

https://spring.io/projects/spring-cloud

我的 VsCode 會顯示相應的釋出日期,這能有效地提示依賴情況:

此篇文章所使用的依賴為:Spring Boot 2.3.12.RELEASE,對應 Spring Cloud Hoxton.SR12,其依賴如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.12.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.dome</groupId>
	<artifactId>backend</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>backend</name>
	<description>Demo project for Spring Boot</description>

	<!-- 指定 JDK 版本 -->
  <properties>
    <java.version>1.8</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

	<dependencies>
      <!-- 框架類 -->
	  <dependency>
	    <groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
	  <dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-devtools</artifactId>
		<scope>runtime</scope>
		<optional>true</optional>
	  </dependency>
      <dependency>
	    <groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-configuration-processor</artifactId>
		<optional>true</optional>
	  </dependency>
	  <dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	  </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>4.3.9.RELEASE</version>
    </dependency>
    <!--引入springcloud的euekea server依賴-->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
	</dependencies>

  <!-- 指定下載源和使用 SpringCloud 版本 -->
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Hoxton.SR12</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

</project>

搞定依賴關係後,就可以進入下一步操作,此時你的專案結構大致有以下幾個關鍵檔案:

  • ApplicationStartup.java (包含用於啟動應用的主函式,名稱不必在意,隨便敲的)
  • pom.xml(依賴管理)
  • application.yml(應用配置)

上述三個檔案是最為重要的核心部件,它們分別在:

  • ApplicationStartup 放置在 src/main/java/com/dome/backend 目錄下,當然這個是IDE生成的,我只是舉個例子,IDE 對此檔案命名可能為:BackendApplication.java ——假設你的名稱空間最後是 backend 的話。
  • pom.xml 通常在專案的根目錄,與 src 同級
  • application.yml 通常可新建資料夾並納入編譯區供程式使用,而大部分 IDE 會預設於 src/resources 目錄下放置

瞭解完關鍵檔案後,接下來,我們僅需對它們進行簡單的處理(pom.xml 略,上面有了),就可以得到一個 Spring Cloud 的基本結構了。

pom.xml 處理完畢後,IDE 會自動下載依賴 jar 包,所以你可以直接在 .java 檔案中直接引用,所以,讓我們先從 ApplicationStartup.java 檔案(強調,可能為其它名字,不信你看看上述說明)開始吧。

對此啟動類的處理,僅需加上一行程式碼即可。

package com.dome.backend;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class ApplicationStartup {

	public static void main(String[] args) {
		SpringApplication.run(BackendApplication.class, args);
	}

}

是的,相比較 IDE 為 SpringBoot 生成的啟動類程式碼,僅多加了註解:@EnableEurekaServer

那麼這個註解有什麼作用呢?好問題,篇幅過長,不想解釋,大概理解為:

它的作用是一個標識,同理,還有一個叫做 @EnableEurekaClient,另外的作用是,它會呼叫數個類,比如 EurekaServerAutoConfiguration、EurekaServerInitializerConfiguration,前者用於配置,如其中的方法:@ConditionalOnBean({Marker.class}) 去裝載適用於 Eureka 服務端主要功能的 Bean,後者主要是初始化 EureKa 的實現類,以生命週期回撥方法去初始化 EureKa。

只是粗略瞭解,所以有錯誤你可以指出,我會記錄並改掉此問題。

接下來配置 yml,如下:

server:
  port: 8080

eureka:
  client:
    # 是否要將本身註冊至 EureKa Server 上,預設為 true,但是當前我們不是使用叢集,本身即為服務,故設定為 false
    register-with-eureka: false
    # 是否從 EureKa Server 中獲取註冊資訊,預設為 true,很遺憾,本身即為服務,並不需要從其它 EureKa Server 節點同步資訊,故設定為 false
    fetch-registry: false
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  instance:
    hostname: node1

spring:
  application:
    # 本應用名稱,叢集時,此處較為重要
    name: eureka-server
  profiles:
    active: node1

該註釋的都註釋了,就講一下 ${eureka.instance.hostname} 之類的吧,你可以理解為,它會自動地到配置檔案中尋找對應的節點裡的值進行讀取,具體就不講解了,你也可以換成 http://node1:8080/eureka/

其次是 node1 是什麼呢?好問題,其實在同一臺機器上,ip 地址是固定的(127.0.0.1),假設你使用了雙節點服務註冊與發現的話,那你就用不了副本了,具體情況可以在其餘部落格中找到,篇幅問題不作講解,僅貼結果:

你可以看見,即便註冊了,也是不可用的。

這就是使用相同ip,不同埠的配置,且適配了使用 IP 的形式:prefer-ip-address: true,但是如果有多臺伺服器,使用 ip 應該是較為理想的方案(沒試過,若有實踐可以在評論區給大家參考噢)。

所以,你需要在 hosts 檔案中進行下述配置:

127.0.0.1 node1
127.0.0.1 node2

node2 是為了下文作鋪墊,可以先配置,當然你願意的話,也能加到 node[N],例如 node123456789

完成上述配置後,就可以啟動你的應用程式了!

接下來,在瀏覽器輸入:node1:8080,就能看到下述介面:

你已經掌握了 Spring Cloud EureKa 服務註冊與發現的基本流程,接下來我們將嘗試多註冊中心的叢集配置

Spring Cloud 已經幫我們做到最簡化了,這也是它的優勢,也是開發者們樂於見到的,沒有人會拒絕簡單而有效的事物,不是嗎?

OK,將你的原始碼複製一份,第一份(原先)命名為 EureKa-1,當然你也可以按自己的喜好命名,第二份命名為 EureKa-2。

接下來,你只需要改動 application.yml 配置檔案即可,簡單幾行變動就可以達到叢集的目的。

Eureka-1 的 yml 如下:

server:
  port: 8080

eureka:
  client:
    # 是否要將本身註冊至 EureKa Server 上,預設為 true,兩個以上為團伙作案,故為 true
    register-with-eureka: true
    # 是否從 EureKa Server 中獲取註冊資訊,預設為 true,兩個以上為團伙作案,故設定為 true
    fetch-registry: true
    service-url:
      defaultZone: http://node2:8081/eureka/
  instance:
    hostname: node1

spring:
  application:
    # 本應用名稱,叢集時,此處較為重要
    name: eureka-server
  profiles:
    active: node1

EureKa-2 的 yml 如下:

server:
  port: 8080

eureka:
  client:
    # 是否要將本身註冊至 EureKa Server 上,預設為 true,兩個以上為團伙作案,故為 true
    register-with-eureka: true
    # 是否從 EureKa Server 中獲取註冊資訊,預設為 true,兩個以上為團伙作案,故設定為 true
    fetch-registry: true
    service-url:
      defaultZone: http://node1:8080/eureka/
  instance:
    hostname: node2

spring:
  application:
    # 本應用名稱,叢集時,此處較為重要
    name: eureka-server
  profiles:
    active: node2

在雙註冊的情況下,你會發現僅僅變動了三個屬性就可以達到“團伙作案”的效果,至於為什麼如此,你可以先實踐後再接著往下看,先上一張效果圖:

嗯,可以看見底部的 registered-replicas 以及 available-replicas 是有內容的,說明它們互相註冊成功了,至於 matrix2 ,只是我把 node 換成了計算機名 matrix 而已,先不必管這些細節。

接下來,你僅需瞭解 yml 中的 defaultZone 屬性即可,其它幾個都進行備註了,不過你也可以通過搜尋引擎(比如 Bing,Google)瞭解,何況我還有註釋

那麼,defaultZone 屬性,是什麼作用呢?答案是:註冊 EureKa 的地址,假設有多臺,那麼你需要以“,”(英文逗號)隔開

例如 A 伺服器註冊到 B、C、D 伺服器,而 B 伺服器註冊到 A、C、D 伺服器中

假設 A 宕機了,那麼並不會影響到 B 服務,因為 B 服務還註冊了 C 、D,即便 C、D 都崩了,還有 B 自身,它自己也是一個服務。

讓我們模擬一下雙註冊服務下,其中一個崩掉的情況:

可以看到,未停機的 EureKa-2 會每隔一定的時間段嘗試連線停機的 EureKa-1,接下來,我們開啟介面看看(EureKa-1):

如期所料,無法訪問,那麼我們轉而去 EureKa-2 的介面看看:

正常使用,但 EureKa-1 被移到不可用中。那麼,接下來的流量請求,就都會壓到 EureKa-2 這個服務了,這也是叢集的好處,一臺崩了,還有另外一臺頂著不是嗎?

但是這樣未免。。太過暴力,假設最後一臺沒了,是不是就會損失客戶了呢?肯定是有解決方案的,所以,敬請期待此係列後續講解~

至此,你掌握了什麼?

  • Spring Cloud EureKa 服務註冊與發現的基本流程
  • 多註冊中心叢集配置的基本要素

寫於 2021-07-13

座標:廣州

轉載請聯絡博主,否則視為侵犯著作權,或者留下轉載地址(http://www.cnblogs.com/chongsaid),我發至網路僅為分享(發現數篇文章被翻譯了五六種外國語言了,有些需要充值才能解鎖),勿當作牟利的工具噢。