天天看點

12-微服務與分布式_Spring Cloud(下)

目錄

​​六,feign​​

​​1,簡介​​

​​2,簡單案例​​

​​3,feign-ribbon負載均衡​​

​​4,服務降級​​

​​5,請求壓縮​​

​​6,日志列印​​

​​七,gateway​​

​​1,簡介​​

​​2,入門案例​​

​​3,面向服務的路由​​

​​4,路徑字首處理​​

​​5,過濾器​​

​​5.1 簡介​​

​​5.2 配置全局預設過濾器​​

​​5.3 執行生命周期​​

​​5.4 自定義局部過濾器​​

​​5.5 自定義全局過濾器​​

​​6,其他配置​​

​​6.1 負載均衡和熔斷(了解)​​

​​6.2 Gateway跨域配置​​

​​6.3 Gateway高可用(了解)​​

​​6.4 Gateway與Feign的差別​​

​​八,config​​

​​1,搭建配置中心​​

​​2,使用配置中心配置​​

​​2.1 配置中心微服務的搭建​​

​​2.2 改造使用者微服務 user-service​​

​​九,bus​​

​​1,問題​​

​​2,簡介​​

​​3,應用​​

​​十,體系架構圖​​

六,feign

在前面的學習中,我們使用了Ribbon的負載均衡功能,大大簡化了遠端調用時的代碼:

String baseUrl = "http://user-service/user/"; 
User user = this.restTemplate.getForObject(baseUrl + id, User.class)      

如果就學到這裡,可能以後需要編寫類似的大量重複代碼,格式基本相同,無非參數不一樣。有沒有更優雅的方 式,來對這些代碼再次優化呢? 這就是我們接下來要學的Feign的功能了。

1,簡介

Feign可以把Rest的請求進行隐藏,僞裝成類似SpringMVC的Controller一樣。你不用再自己拼接url,拼接參數等 等操作,一切都交給Feign去做。

項目首頁:​​GitHub - OpenFeign/feign: Feign makes writing java http clients easier​​

2,簡單案例

1,導入依賴

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

2,建立Feign的用戶端

@FeignClient("user-service")
public interface UserClient {

    //http://user-service/user/123 
    @GetMapping("/user/{id}")
    User queryById(@PathVariable("id") Long id);

}      
  • 首先這是一個接口,Feign會通過動态代理,幫我們生成實作類。這點跟Mybatis的mapper很像;
  • @FeignClient ,聲明這是一個Feign用戶端,同時通過 value 屬性指定服務名稱;
  • 接口中的定義方法,完全采用SpringMVC的注解,Feign會根據注解幫我們生成URL,并通路擷取結果;
  • @GetMapping中的/user,請不要忘記;因為Feign需要拼接可通路的位址;

3,編寫新的控制器類 ConsumerFeignController ,使用UserClient通路

@RestController
@RequestMapping("/cf")
public class ConsumerFeignController {

    @Autowired
    private UserClient userClient;

    @GetMapping("/{id}")
    public User queryById(@PathVariable Long id){
        return userClient.queryById(id);
    }
}      

4,開啟Feign功能

在 ConsumerApplication 啟動類上,添加注解,開啟Feign功能

@SpringCloudApplication
@EnableFeignClients //開啟feign功能 
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }

    // Feign中已經自動內建了Ribbon負載均衡,是以不需要自己定義RestTemplate進行負載均衡的配置。
    // 下面的代碼可以注釋掉
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}      

5,測試

通路接口:http://localhost:8080/cf/2

3,feign-ribbon負載均衡

Feign中本身已經內建了Ribbon依賴和自動配置:

12-微服務與分布式_Spring Cloud(下)

是以不需要額外引入依賴,也不需要再注冊 RestTemplate 對象。

Fegin内置的ribbon預設設定了請求逾時時長,預設是1000,我們可以通過手動配置來修改這個逾時時長:

ribbon: 
    ReadTimeout: 2000 # 讀取逾時時長 
    ConnectTimeout: 1000 # 建立連結的逾時時長

# 或者為某一個具體service指定
user-service
    ribbon: 
        ReadTimeout: 2000 # 讀取逾時時長 
        ConnectTimeout: 1000 # 建立連結的逾時時長      

因為ribbon内部有重試機制,一旦逾時,會自動重新發起請求。如果不希望重試,可以添加配置:

修改 consumer-demo\src\main\resources\application.yml 添加如下配置 :

ribbon: 
    ConnectTimeout: 1000 # 連接配接逾時時長 
    ReadTimeout: 2000 # 資料通信逾時時長 
    MaxAutoRetries: 0 # 目前伺服器的重試次數 
    MaxAutoRetriesNextServer: 0 # 重試多少次服務 
    OkToRetryOnAllOperations: false # 是否對所有的請求方式都重試      

4,服務降級

Feign預設也有對Hystrix的內建:

12-微服務與分布式_Spring Cloud(下)

隻不過,預設情況下是關閉的。需要通過下面的參數來開啟:

修改 consumer-demo\src\main\resources\application.yml 添加如下配置

feign: 
    hystrix: 
        enabled: true # 開啟Feign的熔斷功能      

1,首先,要定義一個類,實作剛才編寫的UserFeignClient,作為fallback的處理類

package com.lxs.consumer.client.fallback;
import com.lxs.consumer.client.UserClient;
import com.lxs.consumer.pojo.User;
import org.springframework.stereotype.Component;

@Component
public class UserClientFallback implements UserClient {

    @Override
    public User queryById(Long id) {
        User user = new User();
        user.setId(id);
        user.setName("使用者異常");
        return user;
    }
}      

2,然後在UserClient中,指定剛才編寫的實作類

@FeignClient(value = "user-service", fallback = UserClientFallback.class) 
public interface UserFeignClient { 
    @GetMapping("/user/{id}") 
    User queryUserById(@PathVariable("id") Long id); 
}      

3,重新開機測試

重新開機啟動 consumer-demo 并關閉 user-service 服務,然後在頁面通路:http://localhost:8080/cf/7

12-微服務與分布式_Spring Cloud(下)

5,請求壓縮

Spring Cloud Feign 支援對請求和響應進行GZIP壓縮,以減少通信過程中的性能損耗。通過下面的參數即可開啟請 求與響應的壓縮功能:

feign:
   compression:
       request:
           enabled: true # 開啟請求壓縮
       response:
           enabled: true # 開啟響應壓縮      

同時,我們也可以對請求的資料類型,以及觸發壓縮的大小下限進行設定

feign: 
    compression: 
        request: 
            enabled: true # 開啟請求壓縮 
            mime-types: text/html,application/xml,application/json # 設定壓縮的資料類型 
            min-request-size: 2048 # 設定觸發壓縮的大小下限      

注:上面的資料類型、壓縮大小下限均為預設值。

6,日志列印

通過 logging.level.lxs.xx=debug 來設定日志級别。然而這個對Fegin用戶端而言不會産生效果。因為 @FeignClient 注解修改的用戶端在被代理時,都會建立一個新的Fegin.Logger執行個體。我們需要額外指定這個日志的 級别才可以。

1,在 consumer-demo 的配置檔案中設定com.xxy包下的日志級别都為 debug 修改 consumer- demo\src\main\resources\application.yml 添加如下配置:

logging: 
    level: 
        com.xxy: debug      

2,編寫配置類,定義日志級别

import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignConfig {

    @Bean
    Logger.Level feignLoggerLevel(){
        //記錄所有請求和響應的明細,包括頭資訊、請求體、中繼資料 
        return Logger.Level.FULL;
    }
}      

這裡指定的Level級别是FULL,Feign支援4種級别:

  • NONE:不記錄任何日志資訊,這是預設值。
  • BASIC:僅記錄請求的方法,URL以及響應狀态碼和執行時間
  • HEADERS:在BASIC的基礎上,額外記錄了請求和響應的頭資訊
  • FULL:記錄所有請求和響應的明細,包括頭資訊、請求體、中繼資料。

3,在 consumer-demo 的 UserClient 接口類上的@FeignClient注解中指定配置類

别忘了去掉user-service的休眠時間

@FeignClient(value = "user-service", fallback = UserClientFallback.class, configuration = FeignConfig.class)

public interface UserClient {
    @GetMapping("/user/{id}")
    User queryById(@PathVariable("id") Long id);

}      

4,重新開機項目,即可看到每次通路的日志

12-微服務與分布式_Spring Cloud(下)

七,gateway

1,簡介

Spring Cloud Gateway元件的核心是一系列的過濾器,通過這些過濾器可以将用戶端發送的請求轉發(路由)到對應的微服務。

Spring Cloud Gateway是加在整個微服務最前沿的防火牆和代理器,隐藏微服務結點IP端口資訊,進而加強安全保護。Spring Cloud Gateway本身也是一個微服務,需要注冊到Eureka服務注冊中心。

網關的核心功能是:過濾和路由

  • Spring Cloud Gateway是Spring官網基于Spring 5.0、 Spring Boot 2.0、Project Reactor等技術開發的網關服務。
  • Spring Cloud Gateway基于Filter鍊提供網關基本功能:安全、監控/埋點、限流等。
  • Spring Cloud Gateway為微服務架構提供簡單、有效且統一的API路由管理方式。
  • Spring Cloud Gateway是替代Netflflix Zuul的一套解決方案。
12-微服務與分布式_Spring Cloud(下)

不管是來自于用戶端(PC或移動端)的請求,還是服務内部調用。一切對服務的請求都可經過網關,然後再 由網關來實作 鑒權、動态路由等等操作。Gateway就是我們服務的統一入口。

路由(route) 路由資訊的組成:由一個ID、一個目的URL、一組斷言工廠、一組Filter組成。如果路由斷言為真,說明請求URL和配置路由比對。

斷言(Predicate) Spring Cloud Gateway中的斷言函數輸入類型是Spring 5.0架構中的ServerWebExchange。Spring Cloud Gateway的斷言函數允許開發者去定義比對來自于HTTP Request中的任何資訊比如請求頭和參數。

過濾器(Filter) 一個标準的Spring WebFilter。 Spring Cloud Gateway中的Filter分為兩種類型的Filter,分别是Gateway Filter和Global Filter。過濾器Filter将會對請求和響應進行修改處理

2,入門案例

通過網關系統lxs-gateway将包含有 /user 的請求 路由到 http://127.0.0.1:9091/user/使用者id

1,建立工程

12-微服務與分布式_Spring Cloud(下)

2,打開 lxs-springcloud\lxs-gateway\pom.xml 檔案修改為如下

<?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 HTTP://maven.apache.org/xsd/maven-
4.0.0.xsd">

<parent>
    <artifactId>lxs-springcloud</artifactId>
    <groupId>com.lxs</groupId>
    <version>1.0-SNAPSHOT</version>
</parent>

<modelVersion>4.0.0</modelVersion>

<artifactId>lxs-gateway</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>
</project>      

2,編寫啟動類

在lxs-gateway中建立 com.lxs.gateway.GatewayApplication 啟動類

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

3,編寫配置

建立 lxs-gateway\src\main\resources\application.yml 檔案,内容如下:

server: 
    port: 10010 
spring: 
    application: 
        name: 
            api-gateway 
eureka: 
    client: 
        service-url: 
            defaultZone: HTTP://127.0.0.1:10086/eureka 
    instance: 
        prefer-ip-address: true      

需要用網關來代理 user-service 服務,先看一下控制台中的服務狀态 :

12-微服務與分布式_Spring Cloud(下)

修改 lxs-gateway\src\main\resources\application.yml 檔案為:

server: 
    port: 10010 
spring: 
    application: 
        name: 
            api-gateway 
    cloud: 
        gateway: 
            routes: 
                # 路由id,可以随意寫 
                - id: user-service-route 
                # 代理的服務位址 
                uri: HTTP://127.0.0.1:9091 
                # 路由斷言,可以配置映射路徑 
                predicates: 
                    - Path=/user/** 
eureka: 
    client: 
        service-url: 
            defaultZone: HTTP://127.0.0.1:10086/eureka 
    instance: 
        prefer-ip-address: true      

 将符合 Path 規則的一切請求,都代理到 uri 參數指定的位址 本例中,我們将路徑中包含有 /user/** 開頭的請求, 代理到http://127.0.0.1:9091

4,啟動測試

通路的路徑中需要加上配置規則的映射路徑,我們通路:http://localhost:10010/user/7

12-微服務與分布式_Spring Cloud(下)

3,面向服務的路由

在剛才的路由規則中,把路徑對應的服務位址寫死了!如果同一服務有多個執行個體的話,這樣做顯然不合理。 應該根 據服務的名稱,去Eureka注冊中心查找 服務對應的所有執行個體清單,然後進行動态路由!

1,修改映射配置,通過服務名稱擷取

修改 lxs-gateway\src\main\resources\application.yml 檔案如下:

server: 
    port: 10010 
spring: 
    application: 
        name: 
            api-gateway 
    cloud: 
        gateway: 
            routes: 
                # 路由id,可以随意寫 
                - id: user-service-route 
                # 代理的服務位址 
                # uri: HTTP://127.0.0.1:9091 
                uri: lb://user-service
                # 路由斷言,可以配置映射路徑 
                predicates: 
                    - Path=/user/** 
eureka: 
    client: 
        service-url: 
            defaultZone: HTTP://127.0.0.1:10086/eureka 
    instance: 
        prefer-ip-address: true      

路由配置中uri所用的協定為lb時(以uri: lb://user-service為例。lb:loadBalance),gateway将使用 LoadBalancerClient把 user-service通過eureka解析為實際的主機和端口,并進行ribbon負載均衡。

2,測試

再次啟動 lxs-gateway ,這次gateway進行代理時,會利用Ribbon進行負載均衡通路: http://localhost:10010/user/8 日志中可以看到使用了負載均衡器:

12-微服務與分布式_Spring Cloud(下)

4,路徑字首處理

用戶端的請求位址與微服務的服務位址如果不一緻的時候,可以通過配置路徑過濾器實作路徑字首的添加和 去除。

提供服務的位址:http://127.0.0.1:9091/user/8

添加字首:對請求位址添加字首路徑之後再作為代理的服務位址;

  • http://127.0.0.1:10010/8 --> http://127.0.0.1:9091/user/8 添加字首路徑/user;

去除字首:将請求位址中路徑去除一些字首路徑之後再作為代理的服務位址;

  • http://127.0.0.1:10010/api/user/8 --> http://127.0.0.1:9091/user/8 去除字首路徑/api;

1,添加字首

在gateway中可以通過配置路由的過濾器PrefixPath,實作映射路徑中位址的添加;

修改 lxs-gateway\src\main\resources\application.yml 檔案:

12-微服務與分布式_Spring Cloud(下)
12-微服務與分布式_Spring Cloud(下)

2,去除字首

在gateway中可以通過配置路由的過濾器StripPrefix,實作映射路徑中位址的去除;

修改 lxs-gateway\src\main\resources\application.yml 檔案: 

12-微服務與分布式_Spring Cloud(下)

通過 StripPrefix=1 來指定了路由要去掉的字首個數。如:路徑 /api/user/1 将會被代理到 /user/1 。 也就是:

  • StripPrefix=1 http://localhost:10010/api/user/8 --》http://localhost:9091/user/8 
  • StripPrefix=2 http://localhost:10010/api/user/8 --》http://localhost:9091/8

5,過濾器

5.1 簡介

Gateway作為網關的其中一個重要功能,就是實作請求的鑒權。而這個動作往往是通過網關提供的過濾器來實作的。前面的 路由字首 章節中的功能也是使用過濾器實作的。

Gateway自帶過濾器有幾十個,常見自帶過濾器有:

12-微服務與分布式_Spring Cloud(下)
12-微服務與分布式_Spring Cloud(下)
  • 局部過濾器:通過 spring.cloud.gateway.routes.fifilters 配置在具體路由下,隻作用在目前路由上;如果配置spring.cloud.gateway.default-fifilters 上會對所有路由生效也算是全局的過濾器;但是這些過濾器 的實作上都是要實作GatewayFilterFactory接口。
  • 全局過濾器:不需要在配置檔案中配置,作用在所有的路由上;實作 GlobalFilter 接口即可。

詳細的說明參考 ​​Spring Cloud Gateway​​

5.2 配置全局預設過濾器

這些自帶的過濾器可以和使用 路由字首 章節中的用法類似,也可以将這些過濾器配置成不隻是針對某個路由;而 是可以對所有路由生效,也就是配置預設過濾器

12-微服務與分布式_Spring Cloud(下)

上述配置後,再通路 http://localhost:10010/api/user/7 的話;那麼可以從其響應中檢視到如下資訊:

12-微服務與分布式_Spring Cloud(下)

5.3 執行生命周期

Spring Cloud Gateway 的 Filter 的生命周期也類似Spring MVC的攔截器,有兩個:“pre” 和 “post”。“pre”和 “post” 分别會在請求被執行前調用和被執行後調用

12-微服務與分布式_Spring Cloud(下)

這裡的 pre 和 post 可以通過過濾器的 GatewayFilterChain 執行fifilter方法前後來實作 

常見的應用場景如下: 

  • 請求鑒權:一般 GatewayFilterChain 執行fifilter方法前,如果發現沒有通路權限,直接就傳回空。 
  • 異常處理:一般 GatewayFilterChain 執行fifilter方法後,記錄異常并傳回。 
  • 服務調用時長統計: GatewayFilterChain 執行fifilter方法前後根據時間統計。 

5.4 自定義局部過濾器

在過濾器(MyParamGatewayFilterFactory)中将​​http://localhost:10010/api/user/8?name=lxs​​中的參數name的值擷取到并輸出到控制台;并且參數名是可變的,也就是不一定每次都是name;需要可以通過配置過濾器的時候做到配置參數名。

在application.yml中對某個路由配置過濾器,該過濾器可以在控制台輸出配置檔案中指定名稱的請求參數的值。

1,編寫過濾器

自定義過濾器的命名應該為:***GatewayFilterFactory

import org.springframework.cloud.gateway.filter.GatewayFilter; 
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; 
import org.springframework.HTTP.server.reactive.ServerHTTPRequest; 
import org.springframework.stereotype.Component; 
import java.util.Arrays; 
import java.util.List;

@Component 
public class MyParamGatewayFilterFactory extends AbstractGatewayFilterFactory<MyParamGatewayFilterFactory.Config> {
    static final String PARAM_NAME = "param";
    public MyParamGatewayFilterFactory() {
        super(Config.class);
    }

    public List<String> shortcutFieldOrder() {
        return Arrays.asList(PARAM_NAME);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            // http://localhost:10010/api/user/8?name=lxs config.param ==> name 
            //擷取請求參數中param對應的參數名 的參數值 
            ServerHTTPRequest request = exchange.getRequest();
            if(request.getQueryParams().containsKey(config.param)){
                request.getQueryParams().get(config.param).forEach(value -> System.out.printf("------------局部過濾器--------%s = %s------", config.param, value)); 
            }
            return chain.filter(exchange);
        };
    }

    public static class Config{
        //對應在配置過濾器的時候指定的參數名 
        private String param;
        public String getParam() {
            return param;
        }

        public void setParam(String param) {
            this.param = param;
        }
    } 
}      
12-微服務與分布式_Spring Cloud(下)

測試通路:http://localhost:10010/api/user/7?name=lxs檢查背景是否輸出name和lxs;

但是若通路 http://localhost:10010/api/user/7?name2=kaikeba 則是不會輸出的

5.5 自定義全局過濾器

編寫全局過濾器,在過濾器中檢查請求中是否攜帶token請求頭。如果token請求頭存在則放行;如果token為空或者不存在則設定傳回的狀态碼為:未授權也不再執行下去。

在lxs-gateway工程編寫全局過濾器類MyGlobalFilter

@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("--------------全局過濾器MyGlobalFilter------------------");
        String token = exchange.getRequest().getHeaders().getFirst("token");
        if(StringUtils.isBlank(token)){
            //設定響應狀态碼為未授權 
            exchange.getResponse().setStatusCode(HTTPStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {//值越小越先執行 
        return 1;
    }
}      

通路 http://localhost:10010/api/user/7

12-微服務與分布式_Spring Cloud(下)

通路 http://localhost:10010/api/user/7?token=abc 

12-微服務與分布式_Spring Cloud(下)

6,其他配置

6.1 負載均衡和熔斷(了解)

Gateway中預設就已經內建了Ribbon負載均衡和Hystrix熔斷機制。但是所有的逾時政策都是走的預設值,比如熔 斷逾時時間隻有1S,很容易就觸發了。是以建議手動進行配置: 

hystrix: 
    command: 
        default: 
            execution: 
                isolation: 
                    thread: 
                        timeoutInMilliseconds: 6000 #服務降級逾時時間,預設1S 

ribbon: 
    ConnectTimeout: 1000 # 連接配接逾時時長 
    ReadTimeout: 2000 # 資料通信逾時時長 
    MaxAutoRetries: 0 # 目前伺服器的重試次數 
    MaxAutoRetriesNextServer: 0 # 重試多少次服務      

6.2 Gateway跨域配置

一般網關都是所有微服務的統一入口,必然在被調用的時候會出現跨域問題。 

跨域:在js請求通路中,如果通路的位址與目前伺服器的域名、ip或者端口号不一緻則稱為跨域請求。若不解決則不能擷取到對應位址的傳回結果。 

如:從在http://localhost:9090中的js通路 http://localhost:9000的資料,因為端口不同,是以也是跨域請求。 

在通路Spring Cloud Gateway網關伺服器的時候,出現跨域問題的話;可以在網關伺服器中通過配置解決,允許哪 些服務是可以跨域請求的;具體配置如下: 

12-微服務與分布式_Spring Cloud(下)

上述配置表示:可以允許來自 http://docs.spring.io 的get請求方式擷取服務資料。 

allowedOrigins 指定允許通路的伺服器位址,如:http://localhost:10000 也是可以的。 

'[/**]' 表示對所有通路到網關伺服器的請求位址 

官網具體說明:​​10. CORS Configuration (spring.io)​​

6.3 Gateway高可用(了解)

啟動多個Gateway服務,自動注冊到Eureka,形成叢集。如果是服務内部通路,通路Gateway,自動負載均衡,沒問題。 

但是,Gateway更多是外部通路,PC端、移動端等。它們無法通過Eureka進行負載均衡,那麼該怎麼辦? 此時, 可以使用其它的服務網關,來對Gateway進行代理。比如:Nginx

6.4 Gateway與Feign的差別

Gateway 作為整個應用的流量入口,接收所有的請求,如PC、移動端等,并且将不同的請求轉- 發至不同的處理微服務子產品,其作用可視為nginx;大部分情況下用作權限鑒定、服務端流量控制;  

Feign 則是将目前微服務的部分服務接口暴露出來,并且主要用于各個微服務之間的服務調用;

八,config

在分布式系統中,由于服務數量非常多,配置檔案分散在不同的微服務項目中,管理不友善。為了友善配置檔案集 中管理,需要分布式配置中心元件。在Spring Cloud中,提供了Spring Cloud Config,它支援配置檔案放在配置服務的本地,也支援放在遠端Git倉庫(GitHub、碼雲)。 

使用Spring Cloud Confifig配置中心後的架構如下圖:

12-微服務與分布式_Spring Cloud(下)

配置中心本質上也是一個微服務,同樣需要注冊到Eureka服務注冊中心!

1,搭建配置中心

1,建立遠端倉庫

首先要使用碼雲上的私有遠端git倉庫需要先注冊帳号;請先自行通路網站并注冊帳号,然後使用帳号登入碼雲控制 台并建立公開倉庫

12-微服務與分布式_Spring Cloud(下)
12-微服務與分布式_Spring Cloud(下)

2,建立配置檔案

在建立的倉庫中建立需要被統一配置管理的配置檔案。

配置檔案的命名方式:{application}-{profifile}.yml 或 {application}-{profifile}.properties

  • application為應用名稱
  • profifile用于區分開發環境,測試環境、生産環境等

如user-dev.yml,表示使用者微服務開發環境下使用的配置檔案。

這裡将user-service工程的配置檔案application.yml檔案的内容複制作為user-dev.yml檔案的内容,具體配置如下

12-微服務與分布式_Spring Cloud(下)

3,建立完user-dev.yml配置檔案之後,gitee中的倉庫如下:

12-微服務與分布式_Spring Cloud(下)

2,使用配置中心配置

2.1 配置中心微服務的搭建

1,建立配置中心微服務工程

12-微服務與分布式_Spring Cloud(下)

2,添加依賴,修改 config-server\pom.xml 如下

12-微服務與分布式_Spring Cloud(下)

 3,建立配置中心工程 config-server 的啟動類

12-微服務與分布式_Spring Cloud(下)

4,配置檔案

12-微服務與分布式_Spring Cloud(下)

注意上述的 spring.cloud.config.server.git.uri 則是在碼雲建立的倉庫位址;

5,啟動測試

啟動eureka注冊中心和配置中心;然後通路http://localhost:12000/user-dev.yml ,檢視能否輸出在碼雲存儲管理 的user-dev.yml檔案。并且可以在gitee上修改user-dev.yml然後重新整理上述測試位址也能及時到最新資料

12-微服務與分布式_Spring Cloud(下)

2.2 改造使用者微服務 user-service

前面已經完成了配置中心微服務的搭建,下面我們就需要改造一下使用者微服務 user-service ,配置檔案資訊不再由 微服務項目提供,而是從配置中心擷取。如下對 user-service 工程進行改造。

1,在pom中添加依賴

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

2,修改配置

  • 删除 user-service 工程的 user-service\src\main\resources\application.yml 檔案(因為該檔案從配置中心擷取)
  • 建立 user-service 工程 user-service\src\main\resources\bootstrap.yml 配置檔案
12-微服務與分布式_Spring Cloud(下)

bootstrap.yml檔案也是Spring Boot的預設配置檔案,而且其加載的時間相比于application.yml更早。

application.yml和bootstrap.yml雖然都是Spring Boot的預設配置檔案,但是定位卻不相同。

bootstrap.yml可以了解成系統級别的一些參數配置,這些參數一般是不會變動的。application.yml 可以用來定義應用級别的參數,如果搭配 spring cloud config 使用,application.yml 裡面定義的檔案可以實作動态替換。

總結就是,bootstrap.yml檔案相當于項目啟動時的引導檔案,内容相對固定。application.yml檔案是微服務的一些正常配置參數,變化比較頻繁。

3,啟動測試

啟動注冊中心 eureka-server 、配置中心 config-server 、使用者服務 user-service ,如果啟動沒有報錯其實已經 使 用上配置中心内容,可以到注冊中心檢視,也可以檢驗 user-service 的服務。

12-微服務與分布式_Spring Cloud(下)

九,bus

1,問題

前面已經完成了将微服務中的配置檔案集中存儲在遠端Git倉庫,并且通過配置中心微服務從Git倉庫拉取配置文 件, 當使用者微服務啟動時會連接配接配置中心擷取配置資訊進而啟動使用者微服務。 如果我們更新Git倉庫中的配置檔案,那使用者微服務是否可以及時接收到新的配置資訊并更新呢

1,修改git中配置檔案

修改在碼雲上的user-dev.yml檔案,添加一個屬性test.name 。

12-微服務與分布式_Spring Cloud(下)

2,修改 user-service 工程中的處理器類;

12-微服務與分布式_Spring Cloud(下)

3,啟動測試

依次啟動注冊中心 eureka-server 、配置中心 config-server 、使用者服務 user-service ;然後修改Git倉庫中的配 置資訊,通路使用者微服務,檢視輸出内容。

結論:通過檢視使用者微服務控制台的輸出結果可以發現,我們對于Git倉庫中配置檔案的修改并沒有及時更新到用 戶微服務,隻有重新開機使用者微服務才能生效。

如果想在不重新開機微服務的情況下更新配置該如何實作呢? 可以使用Spring Cloud Bus來實作配置的自動更新。

需要注意的是Spring Cloud Bus底層是基于RabbitMQ實作的,預設使用本地的消息隊列服務,是以需要提前 啟動本地RabbitMQ服務(安裝RabbitMQ以後才有)

2,簡介

Spring Cloud Bus是用輕量的消息代理将分布式的節點連接配接起來,可以用于廣播配置檔案的更改或者服務的監控管 理。也就是消息總線可以為微服務做監控,也可以實作應用程式之間互相通信。 Spring Cloud Bus可選的消息代理 有RabbitMQ和Kafka。

12-微服務與分布式_Spring Cloud(下)

3,應用

1,改造配置中心

在 config-server 項目的pom.xml檔案中加入Spring Cloud Bus相關依賴

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

<dependency> 
    <groupId>org.springframework.cloud</groupId> 
    <artifactId>spring-cloud-stream-binder-rabbit</artifactId> 
</dependency>      
12-微服務與分布式_Spring Cloud(下)

2,改造使用者服務

在使用者微服務 user-service 項目的pom.xml中加入Spring Cloud Bus相關依賴

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

<dependency> 
    <groupId>org.springframework.cloud</groupId> 
    <artifactId>spring-cloud-stream-binder-rabbit</artifactId> 
</dependency> 

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-actuator</artifactId> 
</dependency>      
12-微服務與分布式_Spring Cloud(下)
12-微服務與分布式_Spring Cloud(下)

3,測試

前面已經完成了配置中心微服務和使用者微服務的改造,下面來測試一下,當我們修改了Git倉庫中的配置檔案,用 戶微服務是否能夠在不重新開機的情況下自動更新配置資訊。 測試步驟:

  • 第一步:依次啟動注冊中心 eureka-server 、配置中心 confifig-server 、使用者服務 user-service 
  • 第二步:通路使用者微服務http://localhost:9091/user/7;檢視IDEA控制台輸出結果 
  • 第三步:修改Git倉庫中配置檔案 user-dev.yml 的 test.name 内容 
  • 第四步:使用Postman或者RESTClient工具發送POST方式請求通路位址 http://127.0.0.1:12000/actuator/bus-refresh 
  • 第五步:通路使用者微服務系統控制台檢視輸出結果
  • Postman或者RESTClient是一個可以模拟浏覽器發送各種請求(POST、GET、PUT、DELETE等)的工具 ;
  • 請求位址http://127.0.0.1:12000/actuator/bus-refresh中 /actuator是固定的
  • 請求http://127.0.0.1:12000/actuator/bus-refresh位址的作用是通路配置中心的消息總線服務,消息總線服務接收到請求後會向消息隊列中發送消息,各個微服務會監聽消息隊列。當微服務接收到隊列中的消息後,會重新從配置中心擷取最新的配置資訊 ;

十,體系架構圖