狂神說springcloud筆記p14-p22


參考博文:(5條消息) [狂神說Java]SpringCloud筆記_笶生的博客-CSDN博客

(5條消息) 狂神說SpringCloud學習筆記(附帶源碼和筆記)_學不死就往死里學-CSDN博客

 

8. Hystrix:服務熔斷
分布式系統面臨的問題

復雜分布式體系結構中的應用程序有數十個依賴關系,每個依賴關系在某些時候將不可避免失敗!

8.1 服務雪崩
​ 多個微服務之間調用的時候,假設微服務A調用微服務B和微服務C,微服務B和微服務C又調用其他的微服務,這就是所謂的“扇出”,如果扇出的鏈路上某個微服務的調用響應時間過長,或者不可用,對微服務A的調用就會占用越來越多的系統資源,進而引起系統崩潰,所謂的“雪崩效應”。

 

 

 

 

​ 對於高流量的應用來說,單一的后端依賴可能會導致所有服務器上的所有資源都在幾十秒內飽和。比失敗更糟糕的是,這些應用程序還可能導致服務之間的延遲增加,備份隊列,線程和其他系統資源緊張,導致整個系統發生更多的級聯故障,這些都表示需要對故障和延遲進行隔離和管理,以達到單個依賴關系的失敗而不影響整個應用程序或系統運行。

​ 我們需要,棄車保帥!

 

 

 

 

8.2 什么是Hystrix?
​ Hystrix是一個應用於處理分布式系統的延遲和容錯的開源庫,在分布式系統里,許多依賴不可避免的會調用失敗,比如超時,異常等,Hystrix 能夠保證在一個依賴出問題的情況下,不會導致整個體系服務失敗,避免級聯故障,以提高分布式系統的彈性。

​ “斷路器”本身是一種開關裝置,當某個服務單元發生故障之后,通過斷路器的故障監控 (類似熔斷保險絲) ,向調用方返回一個服務預期的,可處理的備選響應 (FallBack) ,而不是長時間的等待或者拋出調用方法無法處理的異常,這樣就可以保證了服務調用方的線程不會被長時間,不必要的占用,從而避免了故障在分布式系統中的蔓延,乃至雪崩。



8.3 Hystrix能干嘛?

  • 服務降級
  • 服務熔斷
  • 服務限流
  • 接近實時的監控

當一切正常時,請求流可以如下所示:

 

 

 

 當許多后端系統中有一個潛在阻塞服務時,它可以阻止整個用戶請求:

 

 

隨着大容量通信量的增加,單個后端依賴項的潛在性會導致所有服務器上的所有資源在幾秒鍾內飽和。

應用程序中通過網絡或客戶端庫可能導致網絡請求的每個點都是潛在故障的來源。比失敗更糟糕的是,這些應用程序還可能導致服務之間的延遲增加,從而備份隊列、線程和其他系統資源,從而導致更多跨系統的級聯故障。

 

 當使用Hystrix包裝每個基礎依賴項時,上面的圖表中所示的體系結構會發生類似於以下關系圖的變化。每個依賴項是相互隔離的,限制在延遲發生時它可以填充的資源中,並包含在回退邏輯中,該邏輯決定在依賴項中發生任何類型的故障時要做出什么樣的響應:

 

 

官網資料:https://github.com/Netflix/Hystrix/wiki

8.4 服務熔斷
什么是服務熔斷?
​ 熔斷機制是賭贏雪崩效應的一種微服務鏈路保護機制。

​ 當扇出鏈路的某個微服務不可用或者響應時間太長時,會進行服務的降級,進而熔斷該節點微服務的調用,快速返回錯誤的響應信息。檢測到該節點微服務調用響應正常后恢復調用鏈路。在SpringCloud框架里熔斷機制通過Hystrix實現。Hystrix會監控微服務間調用的狀況,當失敗的調用到一定閥值缺省是5秒內20次調用失敗,就會啟動熔斷機制。熔斷機制的注解是:@HystrixCommand。

服務熔斷解決如下問題:

當所依賴的對象不穩定時,能夠起到快速失敗的目的;
快速失敗后,能夠根據一定的算法動態試探所依賴對象是否恢復。
入門案例
新建springcloud-provider-dept-hystrix-8001模塊並拷貝springcloud-provider-dept–8001內的pom.xml、resource和Java代碼進行初始化並調整。

導入hystrix依賴

<!--hystrix-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>

調整yml配置文件

server:
  port: 8004

mybatis:
  mapper-locations: classpath:mybatis/mapper/*.xml
  type-aliases-package: com.bupt.pojo
  configuration-properties: classpath:mybatis/mybatis-config.xml

spring:
  application:
    name: springcloud-provider-dept
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/db01?useUnicode=true&characterEncoding=UTF-8&useSSL=true&serverTimezone=UTC
    username: root
    password: root
# Eureka配置:配置服務注冊中心地址
eureka:
  client:
    service-url:
      # 注冊中心地址7001-7003
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  instance:
    instance-id: springcloud-provider-dept-8004 #修改Eureka上的默認描述信息
    prefer-ip-address: true #改為true后默認顯示的是ip地址而不再是localhost

info:
  app.name: wulei-springcloud
  company.name: blog.wulei2921625957.com

prefer-ip-address: false:

在這里插入圖片描述

prefer-ip-address: true:

在這里插入圖片描述

修改controller

package com.bupt.Controller;

import com.bupt.DeptService.DeptServiceImpl;
import com.bupt.pojo.Dept;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

//提供Restfull服務!!
@RestController
public class DeptController {

    @Autowired
    private DeptServiceImpl deptService;

    @RequestMapping("/dept/add")
    public boolean addDept(@RequestBody Dept dept) {
        System.out.println(dept);
        return deptService.addDept(dept);
    }

    /**
     * 根據id查詢部門信息
     * 如果根據id查詢出現異常,則走hystrixGet這段備選代碼
     * @param id
     * @return
     */
    @HystrixCommand(fallbackMethod = "hystrixGet")
    @RequestMapping("/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id){
        Dept dept = deptService.queryById(id);
        if(dept == null){
            //因為觸發了這個異常才會調用下面的備選方案
        throw new RuntimeException("這個id=>"+id+",不存在該用戶,或信息無法找到~");
        }
        return dept;
    }
    //根據id查詢備選方案(熔斷)
    public Dept hystrixGet(@PathVariable("id") Long id){
        return new Dept().setDeptno(id).setDname("這個id=>"+id+",沒有對應的信息,null---@Hystrix~")
                .setDb_source("mysql中不存在這個數據庫");
    }

//
//    @GetMapping("/dept/get/{id}")
//    public Dept getDept(@PathVariable("id") Long id) {
//        Dept dept = deptService.queryById(id);
//        if (dept == null) {
//            throw new RuntimeException("Fail");
//        }
//        return dept;
//    }

    @GetMapping("/dept/list")
    public List<Dept> queryAll() {
        return deptService.queryall();
    }

}

為主啟動類添加對熔斷的支持注解@EnableCircuitBreaker

package com.bupt;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;

//@EnableEurekaClient
@SpringBootApplication
@EnableCircuitBreaker
public class DeptProvider_8004 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProvider_8004.class,args);
    }
}

測試:

使用熔斷后,當訪問一個不存在的id時,前台頁展示數據如下:

在這里插入圖片描述

而不適用熔斷的springcloud-provider-dept–8001模塊訪問相同地址會出現下面狀況:

在這里插入圖片描述

因此,為了避免因某個微服務后台出現異常或錯誤而導致整個應用或網頁報錯,使用熔斷是必要的

8.5 服務降級
什么是服務降級?
​ 服務降級是指 當服務器壓力劇增的情況下,根據實際業務情況及流量,對一些服務和頁面有策略的不處理,或換種簡單的方式處理,從而釋放服務器資源以保證核心業務正常運作或高效運作。說白了,就是盡可能的把系統資源讓給優先級高的服務。

資源有限,而請求是無限的。如果在並發高峰期,不做服務降級處理,一方面肯定會影響整體服務的性能,嚴重的話可能會導致宕機某些重要的服務不可用。所以,一般在高峰期,為了保證核心功能服務的可用性,都要對某些服務降級處理。比如當雙11活動時,把交易無關的服務統統降級,如查看螞蟻深林,查看歷史訂單等等。

服務降級主要用於什么場景呢?當整個微服務架構整體的負載超出了預設的上限閾值或即將到來的流量預計將會超過預設的閾值時,為了保證重要或基本的服務能正常運行,可以將一些 不重要 或 不緊急 的服務或任務進行服務的 延遲使用 或 暫停使用。

降級的方式可以根據業務來,可以延遲服務,比如延遲給用戶增加積分,只是放到一個緩存中,等服務平穩之后再執行 ;或者在粒度范圍內關閉服務,比如關閉相關文章的推薦。

 

服務降級,當服務器壓力劇增的情況下,根據當前業務情況及流量對一些服務和頁面有策略的降級,以此釋放服務器資源以保證核心任務的正常運行。比如電商平台,在針對618、雙11等高峰情形下采用部分服務不出現或者延時出現的情形。

服務熔斷:針對服務器的,某個服務連接超時或者異常的時候,引起熔斷
服務降級:針對客戶端,從整體網站請求負載考慮,當某個服務熔斷或則關閉時,服務不在被調用,此時在客

由上圖可得,當某一時間內服務A的訪問量暴增,而B和C的訪問量較少,為了緩解A服務的壓力,這時候需要B和C暫時關閉一些服務功能,去承擔A的部分服務,從而為A分擔壓力,叫做服務降級。

服務降級需要考慮的問題
1)那些服務是核心服務,哪些服務是非核心服務
2)那些服務可以支持降級,那些服務不能支持降級,降級策略是什么
3)除服務降級之外是否存在更復雜的業務放通場景,策略是什么?
自動降級分類
1)超時降級:主要配置好超時時間和超時重試次數和機制,並使用異步機制探測回復情況

2)失敗次數降級:主要是一些不穩定的api,當失敗調用次數達到一定閥值自動降級,同樣要使用異步機制探測回復情況

3)故障降級:比如要調用的遠程服務掛掉了(網絡故障、DNS故障、http服務返回錯誤的狀態碼、rpc服務拋出異常),則可以直接降級。降級后的處理方案有:默認值(比如庫存服務掛了,返回默認現貨)、兜底數據(比如廣告掛了,返回提前准備好的一些靜態頁面)、緩存(之前暫存的一些緩存數據)

4)限流降級:秒殺或者搶購一些限購商品時,此時可能會因為訪問量太大而導致系統崩潰,此時會使用限流來進行限制訪問量,當達到限流閥值,后續請求會被降級;降級后的處理方案可以是:排隊頁面(將用戶導流到排隊頁面等一會重試)、無貨(直接告知用戶沒貨了)、錯誤頁(如活動太火爆了,稍后重試)。

入門案例
在springcloud-api模塊下的service包中新建降級配置類DeptClientServiceFallBackFactory.java,當然在本程序聲明這個服務類和對應的FallbackFactory類直接使用也可以。就不需要引入另一個模塊的內容了。

 

 

/**
 * @Auther: csp1999
 * @Date: 2020/05/20/9:18
 * @Description: Hystrix服務降級 ~
 */
@Component
public class DeptClientServiceFallBackFactory implements FallbackFactory {

    @Override
    public DeptClientService create(Throwable cause) {
        return new DeptClientService() {
            @Override
            public Dept queryById(Long id) {
                return new Dept()
                        .setDeptno(id)
                        .setDname("id=>" + id + "沒有對應的信息,客戶端提供了降級的信息,這個服務現在已經被關閉")
                        .setDb_source("沒有數據~");
            }
            @Override
            public List<Dept> queryAll() {
                return null;
            }

            @Override
            public Boolean addDept(Dept dept) {
                return false;
            }
        };
    }
}

在DeptClientService中指定降級配置類DeptClientServiceFallBackFactory

@Component //注冊到spring容器中
//@FeignClient:微服務客戶端注解,value:指定微服務的名字,這樣就可以使Feign客戶端直接找到對應的微服務
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallBackFactory.class)//fallbackFactory指定降級配置類
public interface DeptClientService {

    @GetMapping("/dept/get/{id}")
    public Dept queryById(@PathVariable("id") Long id);

    @GetMapping("/dept/list")
    public List<Dept> queryAll();

    @GetMapping("/dept/add")
    public Boolean addDept(Dept dept);
}

在springcloud-consumer-dept-feign模塊中開啟降級:

server:
  port: 80

# Eureka配置
eureka:
  client:
    register-with-eureka: false # 不向 Eureka注冊自己
    service-url: # 從三個注冊中心中隨機取一個去訪問
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/

# 開啟降級feign.hystrix
feign:
  hystrix:
    enabled: true

啟動7001項目、啟動8001項目(正常的,不是Hystrix的那個)、然后再啟動feign的80項目

正常訪問 http://localhost/consumer/dept/get/1

 

 

訪問一個不存在的數據

 

 

把8001服務提供者關閉,再次訪問http://localhost/consumer/dept/get/1

 

 

說明了什么?說明了服務熔斷是被動的,服務降級是手動的,但是開啟服務降級后,沒有關閉服務,訪問一個不存在的數據,也會返回一個客戶端自定義的返回結果,當把服務關閉后,訪問任何請求都是有客戶端自定義的結果。

 

8.6 服務熔斷和降級的區別
服務熔斷—>服務端:某個服務超時或異常,引起熔斷~,類似於保險絲(自我熔斷)
服務降級—>客戶端:從整體網站請求負載考慮,當某個服務熔斷或者關閉之后,服務將不再被調用,此時在客戶端,我們可以准備一個 FallBackFactory ,返回一個默認的值(缺省值)。會導致整體的服務下降,但是好歹能用,比直接掛掉強。
觸發原因不太一樣,服務熔斷一般是某個服務(下游服務)故障引起,而服務降級一般是從整體負荷考慮;管理目標的層次不太一樣,熔斷其實是一個框架級的處理,每個微服務都需要(無層級之分),而降級一般需要對業務有層級之分(比如降級一般是從最外圍服務開始)
實現方式不太一樣,服務降級具有代碼侵入性(由控制器完成/或自動降級),熔斷一般稱為自我熔斷。
熔斷,降級,限流:

限流:限制並發的請求訪問量,超過閾值則拒絕;

降級:服務分優先級,犧牲非核心服務(不可用),保證核心服務穩定;從整體負荷考慮;

熔斷:依賴的下游服務故障觸發熔斷,避免引發本系統崩潰;系統自動執行和恢復

8.7 Dashboard 流監控

 

 

新建springcloud-consumer-hystrix-dashboard模塊

 

添加依賴

<!--Hystrix依賴-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>
<!--dashboard依賴-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>
<!--Ribbon-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>
<!--Eureka-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>
<!--實體類+web-->
<dependency>
    <groupId>com.haust</groupId>
    <artifactId>springcloud-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--熱部署-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
</dependency>

主啟動類

@SpringBootApplication
// 開啟Dashboard
@EnableHystrixDashboard
public class DeptConsumerDashboard_9001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumerDashboard_9001.class,args);
    }
}

給springcloud-provider-dept-hystrix-8001模塊下的主啟動類添加如下代碼,添加監控

@SpringBootApplication
@EnableEurekaClient //EnableEurekaClient 客戶端的啟動類,在服務啟動后自動向注冊中心注冊服務
public class DeptProvider_8001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProvider_8001.class,args);
    }

    //增加一個 Servlet
    @Bean
    public ServletRegistrationBean hystrixMetricsStreamServlet(){
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
        //訪問該頁面就是監控頁面
        registrationBean.addUrlMappings("/actuator/hystrix.stream");
       
        return registrationBean;
    }
}

訪問:http://localhost:9001/hystrix

在這里插入圖片描述

進入監控頁面:

在這里插入圖片描述

現在監控頁面搭載完成

我們要如何監控呢?監控什么呢?

我們監控的是實現了熔斷支持的類(主啟動類上加了@EnableCircuitBreaker注解),這里我們剛好有一個項目springcloud-provider-dept-hystrix-8001,還有一個前提,服務類必須添加actuator依賴

然后我們修改springcloud-provider-dept-hystrix-8001項目的主啟動類,添加一個Servlet,為了配合監控使用

啟動7001項目,啟動9001項目,啟動hystrix的8001項目,然后訪問http://localhost:8001/dept/get/1,有返回數據即可

然后訪問http://localhost:8001/actuator/hystrix.stream,會得到一些數據流

 

 

然后http://localhost:9001/hystrix,填入以下信息即可

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

在這里插入圖片描述

在這里插入圖片描述
在這里插入圖片描述

 

9. Zull路由網關
概述
什么是zuul?

​ Zull包含了對請求的路由(用來跳轉的)和過濾兩個最主要功能:

​ 其中路由功能負責將外部請求轉發到具體的微服務實例上,是實現外部訪問統一入口的基礎,而過濾器功能則負責對請求的處理過程進行干預,是實現請求校驗,服務聚合等功能的基礎。Zuul和Eureka進行整合,將Zuul自身注冊為Eureka服務治理下的應用,同時從Eureka中獲得其他服務的消息,也即以后的訪問微服務都是通過Zuul跳轉后獲得。

 

注意:Zuul 服務最終還是會注冊進 Eureka

提供:代理 + 路由 + 過濾 三大功能!

Zuul 能干嘛?

路由
過濾
官方文檔:https://github.com/Netflix/zuul/

入門案例
新建springcloud-zuul模塊(下面是在8001上直接加入zuul),並導入依賴

<dependencies>
    <!--導入zuul依賴-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-zuul</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    <!--Hystrix依賴-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-hystrix</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    <!--dashboard依賴-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-hystrix-dashboar</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    <!--Ribbon-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-ribbon</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    <!--Eureka-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    <!--實體類+web-->
    <dependency>
        <groupId>com.haust</groupId>
        <artifactId>springcloud-api</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--熱部署-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
    </dependency>
</dependencies>

application.yml

server:
  port: 8001

mybatis:
  mapper-locations: classpath:mybatis/mapper/*.xml
  type-aliases-package: com.bupt.pojo
  configuration-properties: classpath:mybatis/mybatis-config.xml

spring:
  application:
    name: springcloud-provider-dept
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/db01?useUnicode=true&characterEncoding=UTF-8&useSSL=true&serverTimezone=UTC
    username: root
    password: root
# Eureka配置:配置服務注冊中心地址
eureka:
  client:
    service-url:
      # 注冊中心地址7001-7003
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  instance:
    instance-id: springcloud-provider-dept-8001 #修改Eureka上的默認描述信息

info:
  app.name: wulei-springcloud
  company.name: blog.wulei2921625957.com

zuul:
  routes:
    mydept.serviceId: springcloud-provider-dept
    mydept.path: /mydept/**

  ignored-services: "*"
  prefix: /bupt

主啟動類

package com.bupt;

import com.netflix.hystrix.HystrixMetrics;
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;

//@EnableEurekaClient
@SpringBootApplication
@EnableZuulProxy
public class DeptProvider_8001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProvider_8001.class,args);
    }

    @Bean
    public ServletRegistrationBean hystrixMetricsStreamServlet(){
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
        //訪問該頁面就是監控頁面
        registrationBean.addUrlMappings("/actuator/hystrix.stream");

        return registrationBean;
    }

}

測試:

 

 

 

可以看出Zull路由網關被注冊到Eureka注冊中心中了!

 

 

 

上圖是沒有經過Zull路由網關配置時,服務接口訪問的路由,可以看出直接用微服務(服務提供方)名稱去訪問,這樣不安全,不能將微服務名稱暴露!

所以經過Zull路由網關配置后,訪問的路由為:

 

 

 

我們看到,微服務名稱被替換並隱藏,換成了我們自定義的微服務名稱mydept,同時加上了前綴haust,這樣就做到了對路由fan訪問的加密處理!

詳情參考springcloud中文社區zuul組件 :https://www.springcloud.cc/spring-cloud-greenwich.html#_router_and_filter_zuul

 

9. Spring Cloud Config 分布式配置
Dalston.RELEASE

Spring Cloud Config為分布式系統中的外部配置提供服務器和客戶端支持。使用Config Server,您可以在所有環境中管理應用程序的外部屬性。客戶端和服務器上的概念映射與Spring Environment和PropertySource抽象相同,因此它們與Spring應用程序非常契合,但可以與任何以任何語言運行的應用程序一起使用。隨着應用程序通過從開發人員到測試和生產的部署流程,您可以管理這些環境之間的配置,並確定應用程序具有遷移時需要運行的一切。服務器存儲后端的默認實現使用git,因此它輕松支持標簽版本的配置環境,以及可以訪問用於管理內容的各種工具。很容易添加替代實現,並使用Spring配置將其插入。

概述
分布式系統面臨的–配置文件問題

微服務意味着要將單體應用中的業務拆分成一個個子服務,每個服務的粒度相對較小,因此系統中會出現大量的服務,由於每個服務都需要必要的配置信息才能運行,所以一套集中式的,動態的配置管理設施是必不可少的。spring cloud提供了configServer來解決這個問題,我們每一個微服務自己帶着一個application.yml,那上百個的配置文件修改起來,令人頭疼!

什么是SpringCloud config分布式配置中心?

 

spring cloud config 為微服務架構中的微服務提供集中化的外部支持,配置服務器為各個不同微服務應用的所有環節提供了一個中心化的外部配置。

spring cloud config 分為服務端和客戶端兩部分。

服務端也稱為 分布式配置中心,它是一個獨立的微服務應用,用來連接配置服務器並為客戶端提供獲取配置信息,加密,解密信息等訪問接口。

客戶端則是通過指定的配置中心來管理應用資源,以及與業務相關的配置內容,並在啟動的時候從配置中心獲取和加載配置信息。配置服務器默認采用git來存儲配置信息,這樣就有助於對環境配置進行版本管理。並且可用通過git客戶端工具來方便的管理和訪問配置內容。

spring cloud config 分布式配置中心能干嘛?

集中式管理配置文件
不同環境,不同配置,動態化的配置更新,分環境部署,比如 /dev /test /prod /beta /release
運行期間動態調整配置,不再需要在每個服務部署的機器上編寫配置文件,服務會向配置中心統一拉取配置自己的信息
當配置發生變動時,服務不需要重啟,即可感知到配置的變化,並應用新的配置
將配置信息以REST接口的形式暴露
spring cloud config 分布式配置中心與GitHub整合

由於spring cloud config 默認使用git來存儲配置文件 (也有其他方式,比如自持SVN 和本地文件),但是最推薦的還是git ,而且使用的是 http / https 訪問的形式。

入門案例

服務端

新建springcloud-config-server-3344模塊導入pom.xml依賴

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>
    </dependencies>

resource下創建application.yml配置文件,Spring Cloud Config服務器從git存儲庫(必須提供)為遠程客戶端提供配置:

server:
  port: 3344 spring: application: name: springcloud-config-server cloud: config: server: git: uri: https://gitee.com/henuliulei/bupt_springcloud_git_server.git  #eureka: # client: # register-with-eureka: false # fetch-registry: false

Config_Server_3344

package com.bupt;

import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.config.server.EnableConfigServer; @SpringBootApplication @EnableConfigServer //開啟注解 public class Config_Server_3344 { public static void main(String[] args) { SpringApplication.run(Config_Server_3344.class, args); } }

然后你碼雲或者Githup里面要有一個 application.yml 文件

# 這個3344項目只是為了讀取配置,不干別的事,我這里配了 2 套環境為了測試,

spring:
  profiles: dev
  application:
    name: springcloud-config-dev --- spring: profiles: test application: name: springcloud-config-test

然后

所以上面項目里面的配置文件的uri就是這個倉庫的https鏈接

啟動3344項目,訪問

http://localhost:3344/application-dev.yml
http://localhost:3344/application-test.yml
http://localhost:3344/application/dev/master
http://localhost:3344/master/application-dev.yml

 

其中“應用程序”作為SpringApplication中的spring.config.name注入(即常規的Spring Boot應用程序中通常是“應用程序”),“配置文件”是活動配置文件(或逗號分隔列表的屬性),“label”是可選的git標簽(默認為“master”)。

測試訪問http://localhost:3344/application-dev.yml

 

測試訪問 http://localhost:3344/application/test/master

 

測試訪問 http://localhost:3344/master/application-dev.yml

 

如果測試訪問不存在的配置則不顯示 如:http://localhost:3344/master/application-aaa.yml

客戶端

將本地git倉庫springcloud-config文件夾下新建的config-client.yml提交到碼雲倉庫:

在這里插入圖片描述

新建一個springcloud-config-client-3355模塊,並導入依賴

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>


    </dependencies>

resources下創建application.yml和bootstrap.yml配置文件

bootstrap.yml是系統級別的配置

#系統級別的配置
spring:
  cloud:
    config:
      name: config-client profile: test label: master uri: http://localhost:3344

application.yml是用戶級別的配置

# 用戶級別的配置
spring:
  application:
    name: springcloud-config-client

創建controller包下的ConfigClientController.java用於測試

@RestController
public class ConfigClientController { @Value("${spring.application.name}") private String applicationName; //獲取微服務名稱  @Value("${eureka.client.service-url.defaultZone}") private String eurekaServer; //獲取Eureka服務  @Value("${server.port}") private String port; //獲取服務端的端口號  @RequestMapping("/config") public String getConfig(){ return "applicationName:"+applicationName + "eurekaServer:"+eurekaServer + "port:"+port; } }

主啟動類

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

測試:

啟動服務端Config_server_3344 再啟動客戶端ConfigClient

訪問:http://localhost:8201/config/

 

 

 

 

 

 

 

 

 

小案例

本地新建config-dept.yml和config-eureka.yml並提交到碼雲倉庫

 

 

 

 

 

 

 

 

 

 

 

這里配置文件內容不再列舉直接到代碼中看把。

新建springcloud-config-eureka-7001模塊,並將原來的springcloud-eureka-7001模塊下的內容拷貝的該模塊。

1.清空該模塊的application.yml配置,並新建bootstrap.yml連接遠程配置

 

 

 

 

spring:
  cloud:
    config:
      name: config-eureka # 倉庫中的配置文件名稱 label: master profile: dev uri: http://localhost:3344

2.在pom.xml中添加spring cloud config依賴

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <!--config-->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-config -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>

    </dependencies>

在application中添加

spring:
  application:
    name: springcloud-config-eureka-7001

3.主啟動類

@SpringBootApplication
@EnableEurekaServer //EnableEurekaServer 服務端的啟動類,可以接受別人注冊進來~
public class ConfigEurekaServer_7001 { public static void main(String[] args) { SpringApplication.run(ConfigEurekaServer_7001.class,args); } }

4.測試

第一步:啟動 Config_Server_3344,並訪問 http://localhost:3344/master/config-eureka-dev.yml 測試


第二部:啟動ConfigEurekaServer_7001,訪問 http://localhost:7001/ 測試

顯示上圖則成功

新建springcloud-config-dept-8001模塊並拷貝springcloud-provider-dept-8001的內容

同理導入spring cloud config依賴、清空application.yml 、新建bootstrap.yml配置文件並配置

 

 

 

 

<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.bupt</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-netflix-ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</version>
        </dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>

spring:
  application:
    name: springcloud-config-dept-8001
s
pring: cloud: config: name: config-provider label: master profile: dev uri: http://localhost:3344
package com.bupt;

import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; //@EnableEurekaClient @SpringBootApplication public class DeptProvider_8002 { public static void main(String[] args) { SpringApplication.run(DeptProvider_8002.class,args); } }

 

一定別忘了這個依賴

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>

 

 

 

 

 

小結

  • Spring Cloud Config 說白了就是把配置文件放到雲端托管,而且有利於多人合作開發
  • 如果在項目啟動后更改了雲端的配置文件,要重啟項目(直接build???)

項目總結構

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM