Spring Cloud 詳細入門系列(一)
在入門前,第一件事是瞭解全貌。
首先,讓我們先大概知悉 Spring Cloud 能為我們做到什麼。
從官網、各類部落格、以及相關技術類論壇中提煉了下述比較關鍵的作用,這也是它大放異彩的基本要素:
- 微服務框架,提供全套的分散式系統解決方案,比較傳統的技術,會更加穩定且具有容錯性;
- 只作整合封裝(挺多開源框架與元件,包括對 SpringBoot 的深度整合,繼承了其優秀的“約定大於配置”,能通過註解以及 yml 進行配置);
- 對開發者友好,十分容易上手,如配置、斷路機制、選舉、分散式 session、狀態管理等常規處理提供了簡便的操作,便於上手。
- 對 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),我發至網路僅為分享(發現數篇文章被翻譯了五六種外國語言了,有些需要充值才能解鎖),勿當作牟利的工具噢。