04-Consul服務註冊與發現

长名06發表於2024-09-28

1.為什麼要引入服務註冊中心

1.1 原因

public static final String PAYMENT_SRV_URL = "http://localhost:8001";//硬編碼

微服務所在的IP地址和埠號硬編碼到訂單微服務中,會存在非常多的問題

(1)如果訂單微服務和支付微服務的IP地址或者埠號發生了變化,則支付微服務將變得不可用,需要同步修改訂單微服務中呼叫支付微服務的IP地址和埠號。

(2)如果系統中提供了多個訂單微服務和支付微服務,則無法實現微服務的負載均衡功能。

(3)如果系統需要支援更高的併發,需要部署更多的訂單微服務和支付微服務,硬編碼訂單微服務則後續的維護會變得異常複雜。

所以,在微服務開發的過程中,需要引入服務治理功能,實現微服務之間的動態註冊與發現,從此刻開始我們正式進入SpringCloud實戰。

1.2 註冊中心在SpringCloud體系的位置

2.為什麼不再使用Eureka

2.1 Enreka停更維護

https://github.com/Netflix/eureka/wiki

2.2 註冊中心獨立且和微服務功能解耦

目前主流服務中心,希望單獨隔離出來而不是作為一個獨立微服務嵌入到系統中。

按照Netflix之前的思路,註冊中心Eureka也是作為一個微服務且需要程式設計師自己開發部署(cloud2020的教程,eureka需要單獨引入依賴,做為一個服務啟動)。

實際情況,希望微服務和註冊中心分離解耦,註冊中心和業務無關的,不要混為一談。提供類似tomcat一樣獨立的元件,微服務註冊上去使用,是個成品。

.3 阿里巴巴Nacos的崛起

一個整合了Service discovery and configuration management的獨立元件。在配置檔案的持久化上,使用起來比Consul要簡單。後面教程會講解到。

3.Consul簡介

3.1 是什麼

3.1.1 consul官網地址

https://www.consul.io/

3.1.2 What is Consul?

Consul 是一套開源的分散式服務發現和配置管理系統,由HashiCorp公司用Go語言開發。

提供了微服務系統中的服務治理、配置中心、控制匯流排等功能。這些功能中的每一個都可以根據需要單獨使用,也可以一起使用以構建全方位的服務網格,總之Consul提供了一種完整的服務網格解決方案。它具有很多優點。包括: 基於raft協議,比較簡潔; 支援健康檢查, 同時支援HTTPDNS協議支援跨資料中心的 WAN叢集,提供圖形介面 跨平臺,支援 Linux、Mac、Windows。

https://developer.hashicorp.com/consul/docs/intro

3.1.3 禁止使用問題

HashiCorp是一家非常知名的基礎軟體提供商,很多人可能沒聽過它的名字,但是其旗下的6款主流軟體,Terraform、Consul、Vagrant、Nomad、Vault,Packer 相信不少程式設計師都聽說或使用過,尤其是Consul使用者不盡其數。截止目前為止,從HashiCorp官網上的宣告來看,開源專案其實還是“安全”的,被禁用的只是Vault企業版(並且原因是Vault產品目前使用的加密演算法在中國不符合法規,另一方面是美國出口管制法在涉及加密相關軟體上也有相應規定。因此這兩項原因使得HashiCorp不得不在宣告中說明風險)而非其他所有開源產品(Terraform、Consul等)。因此,大家可以暫時放下心來,放心使用!

3.1.4 Spring Cloud Consul

https://docs.spring.io/spring-cloud-consul/reference/index.html

3.2 能幹嘛

3.2.1 服務發現

提供HTTP和DNS兩種發現方式。

3.2.2 健康檢測

支援多種方式,HTTP,TCP,Docker,Shell指令碼定製化監控。

3.2.3 KV儲存

Key,Value的儲存方式。

3.2.4 多資料中心

Consul多資料中心

3.2.5 視覺化WEB介面

3.3 下載地址

https://developer.hashicorp.com/consul/install

3.4 快速開始

https://docs.spring.io/spring-cloud-consul/reference/quickstart.html

4.下載並執行Consul

下載,注意選擇版本,和對應作業系統,以及如果是,Windows下的CPU架構。

找到下載檔案,移動到合適的目錄,解壓即可,因為是一個可執行的consul.exe檔案

#檢視版本資訊,注意在consul.exe目錄下執行
D:\Develop\consul>consul -version

開發者模式啟動

D:\Develop\consul>consul agent -dev

透過http://localhost:8500,訪問頁面

5.服務註冊與發現

5.1 服務提供者8001

支付服務provider8001註冊進consul

5.1.1 引入依賴
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-discovery</artifactId>
    <exclusions>
        <!--這個因為包含了多餘的日誌依賴,這個是排除的。否則控制檯,會有警告資訊。-->
        <exclusion>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

為什麼這麼引入,見官網

5.1.2 配置檔案修改
spring:
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        service-name: ${spring.application.name} 
5.1.3 主啟動

@EnableDiscoveryClient註解,開啟服務發現(作為一個服務,註冊到consul,也可以從consul中,獲取其他服務的ip和埠資訊)。

5.2 服務消費者80

5.2.1 引入依賴
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-discovery</artifactId>
    <exclusions>
        <!--這個因為包含了多餘的日誌依賴,這個是排除的。否則控制檯,會有警告資訊。-->
        <exclusion>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>
5.2.2 修改配置
server:
  port: 8080

spring:
  application:
    name: cloud-consumer-order
  ####Spring Cloud Consul for Service Discovery
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        prefer-ip-address: true #優先使用服務ip進行註冊
        service-name: ${spring.application.name}
5.2.3 主啟動

@EnableDiscoveryClient註解,開啟服務發現。

5.2.4 Controller類修改
@RestController
@RequestMapping("/consumer")
public class OrderController {

    //public static final String PAYMENT_SRV_URL = "http://localhost:8001";//硬編碼

    public static final String PAYMENT_SRV_URL = "http://cloud-payment-service";//服務註冊中心上的微服務名稱

    @Resource
    private RestTemplate restTemplate;
	
    ...
}
5.2.5 啟動測試

5.2.6 修改RestTemplateConfig類
@Configuration
public class RestTemplateConfig {

    @Bean
    @LoadBalanced//新增的,因為註冊中心 ,必須要有負載均衡。
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

}

5.3 註冊中心異同點

5.3.1 CAP理論

C:Consistency(強一致性)

A:Availablility(可用性)

P:Partition tolerance(分割槽容錯性)

5.3.2 經典CAP圖


中介軟體,一般能支援CAP中的兩項特性,就不錯了。

5.3.3 AP(Eureka/Nacos)

AP架構

當網路分割槽出現後,為了保證可用性,系統B可以返回舊值,保證系統的可用性。

當資料出現不一致時,雖然A, B上的註冊資訊不完全相同,但每個Eureka節點依然能夠正常對外提供服務,這會出現查詢服務資訊時如果請求A查不到,但請求B就能查到。如此保證了可用性但犧牲了一致性結論:違背了一致性C的要求,只滿足可用性和分割槽容錯,即AP。

5.3.4 CP(Zookerper/Consul)

CP架構

當網路分割槽出現後,為了保證一致性,就必須拒接請求,否則無法保證一致性,Consul 遵循CAP原理中的CP原則,保證了強一致性和分割槽容錯性,且使用的是Raft演算法,比zookeeper使用的Paxos演算法更加簡單。雖然保證了強一致性,但是可用性就相應下降了,例如服務註冊的時間會稍長一些,因為 Consul 的 raft 協議要求必須過半數的節點都寫入成功才認為註冊成功 ;在leader掛掉了之後,重新選舉出leader之前會導致Consul 服務不可用。結論:違背了可用性A的要求,只滿足一致性和分割槽容錯,即CP。

6.服務配置與重新整理

6.1 分散式系統面臨的->配置問題

微服務意味著要將單體應用中的業務拆分成一個個子服務,每個服務的粒度相對較小,因此係統中會出現大量的服務。由於每個服務都需要必要的配置資訊才能執行,所以一套集中式的、動態的配置管理設施是必不可少的。比如某些配置檔案中的內容大部分都是相同的,只有個別的配置項不同。就拿資料庫配置來說吧,如果每個微服務使用的技術棧都是相同的,則每個微服務中關於資料庫的配置幾乎都是相同的,有時候主機遷移了,我希望一次修改,處處生效。

當下我們每一個微服務自己帶著一個application.yml,上百個配置檔案的管理....../(ㄒoㄒ)/~~

6.2 官網說明

Consul可作為註冊中心和配置中心。

作為配置中心介紹。

6.3 服務使用配置中心

既然可以使用全域性配置資訊,直接註冊進Consul伺服器,從Consul獲取。但是要遵守Consul的配置規則要求。

6.3.1 引入依賴
<!--SpringCloud consul config-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-config</artifactId>
    <exclusions>
        <exclusion>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

為什麼需要引入註冊中心,和bootstrap依賴。見官網

6.3.2 修改配置

Consul配置規則說明

You can change the data key using spring.cloud.consul.config.data-key.可以使用該屬性key修改配置檔案和其分組間使用的分隔符。

例如Consul中預設','作為分隔符,application,dev.yml 設定了屬性為'-' ,就可以使用該方式,application-dev.yml。

新增bootstrap.yml配置檔案

applicaiton.yml是使用者級的資源配置項。

bootstrap.yml是系統級的,優先順序更加高。

Spring Cloud會建立一個“Bootstrap Context”,作為Spring應用的Application Context的父上下文。初始化的時候,Bootstrap Context負責從外部源載入配置屬性並解析配置。這兩個上下文共享一個從外部獲取的Environment

Bootstrap屬性有高優先順序,預設情況下,它們不會被本地配置覆蓋。 Bootstrap contextApplication Context有著不同的約定,所以新增了一個bootstrap.yml檔案,保證Bootstrap ContextApplication Context配置的分離。

applicaiton.yml檔案改為bootstrap.yml,這是很關鍵的或者兩者共存。因為bootstrap.yml是比applicaiton.yml先載入的。bootstrap.yml優先順序高於applicaiton.ymlymlproperties只是檔名字尾,以及配置是,相同字首的key是否省略不同(寫法上),優先順序方面無區別。

6.3.3 配置檔案內容

bootstrap.yml

spring:
  application:
    name: cloud-payment-service
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        service-name: ${spring.application.name}
      config:
        profile-separator: '-' # default value is ",",we update '-'
        format: YAML

applicaiton.yml

server:
  port: 8001

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3307/db2024?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
    username: xxx
    password: xxx
  profiles:
    active:  # 多環境配置載入內容dev/prod,不寫就是預設default配置


# ========================mybatis===================
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.atguigu.cloud.entities
  configuration:
    map-underscore-to-camel-case: true
6.3.4 consul伺服器Key/Value配置填寫

1.參考規則

config/cloud-payment-service/data //沒寫就是預設default
config/cloud-payment-service-dev/data
config/cloud-payment-service-prod/data

2.建立config資料夾,以/結尾

開啟,consul的web管理介面,Key/value選單,Create按鈕新建即可。

3.在config資料夾下建立其他3個資料夾,以/結尾

4.在上述3個資料夾下分別建立data內容,data不再是資料夾

6.3.5 測試配置中心配置的方法
    @Value("${server.port}")
    private String port;

    @GetMapping(value = "/get/info")
    private String getInfoByConsul(@Value("${info}") String info) {//要和data檔案中寫入的配置資訊相同
        return "Info: " + info + "\t" + "port: " + port;
    }

透過修改application.yml裡面的啟用配置部分,進行內容的驗證。

6.3.6 測試

6.3.7 使用ConfigUtil靜態獲取系統配置的類

一般情況下,開發時,都會使用一個工具類靜態的獲取系統配置,見博文

6.4 動態重新整理

在周陽老師影片中,修改了data中的配置內容,不會立刻刷洗,但是我學習,操作過程中,會自動重新整理,且不用配置或者,在主啟動類上加@RefreshScope註解。

周洋老師影片中,需要在主啟動類,加@RefreshScope註解,修改spring.cloud.consul.config.watch.wait-time配置,改項配置預設值是55秒。

6.5 思考

存在問題,在Key/Value新增的配置,在consul重啟後,就沒了。Consul的配置持久化...

只是為了記錄自己的學習歷程,且本人水平有限,不對之處,請指正。

相關文章