• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • SpringCloud詳細筆記2

    SpringCloud

    • 案例代碼

    https://github.com/ZengjxRsingstar/springcloud2/blob/master/README.md
    在這里插入圖片描述

    1 SpringCloudFeign

    1.2 Feign簡介

    Feign [fe?n] 譯文 偽裝。Feign是一個聲明式WebService客戶端。使用Feign能讓編寫WebService客戶端更加簡單,它的使用方法是定義一個接口,然后在上面添加注解。不再需要拼接URL,參數等操作。
    項目主頁:https://github.com/OpenFeign/feign
    ? 集成Ribbon的負載均衡功能
    ? 集成了Hystrix的熔斷器功能
    ? 支持請求壓縮
    ? 大大簡化了遠程調用的代碼,同時功能還增強啦
    ? Feign以更加優雅的方式編寫遠程調用代碼,并簡化重復代碼

    1.3 實現步驟

    使用Feign替代RestTemplate發送Rest請求。

    實現步驟:

    1. 導入feign依賴
    2. 編寫Feign客戶端接口
    3. 消費者啟動引導類開啟Feign功能注解
    4. 訪問接口測試

    1.3.1

    1.3.2 導入依賴

    在user-consumer中添加spring-cloud-starter-openfeign依賴
    <!--配置feign-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    

    1.3.3 創建Feign客戶端

    在user-consumer中創建com.zengjx.feign.UserClient接口,代碼如下:

    @FeignClient(value = "user-provider")  //聲明Feign的客戶端,value:填寫生產者的名稱
    public interface UserClient {
    
        //注意:此處的請求地址一定要和生產者請求的地址一樣
        @RequestMapping("{id}")
        public User findById(@PathVariable("id")Integer id);
    }
    
    

    解釋:
    Feign會通過動態代理,幫我們生成實現類。
    注解@FeignClient聲明Feign的客戶端,注解value指明服務名稱
    接口定義的方法,采用SpringMVC的注解。Feign會根據注解幫我們生成URL地址
    注解@RequestMapping中的/user,不要忘記同時建議不要放在類的頭部。因為Feign需要拼接可訪問地址

    1.3.4 編寫控制層

    在user-consumer中創建com.zengjx.controller.ConsumerFeignController,在Controller中使用@Autowired注入FeignClient,代碼如下
    @RestController
    @RequestMapping(“feign”)
    public class ConsumerFeignController {
    @Autowired
    private UserClient userClient;

    @RequestMapping("{id}")
    public User findById(@PathVariable(value = "id")Integer id){
        return userClient.findByUserId(id);
    }
    

    }

    1.3.5 開啟Feign

    修改user-consumer的啟動類,在啟動類上添加@EnableFeignClients注解,開啟Feign,代碼如下:

    **@SpringBootApplication
    @EnableDiscoveryClient  //開啟eureka發現功能
    @EnableCircuitBreaker   //開啟熔斷器
    @EnableFeignClients  //開啟Feign客戶端**
    public class UserConsumerApplication {
        public static void main(String[] args) {
            SpringApplication.run(UserConsumerApplication.class,args);
        }
        /***
         * 將RestTemplate的實例放到Spring容器中
         * @return
         */
        @Bean
        @LoadBalanced  //開啟負載均衡
        public RestTemplate restTemplate(){
            return new RestTemplate();
        }
    }
    

    1.3.6 測試

    啟動相關工程,請求http://localhost:18082/feign/2 效果如下:
    端口可以調整:
    在這里插入圖片描述

    1.4 負載均衡

    Feign自身已經集成了Ribbon,因此使用Feign的時候,不需要額外引入依賴。

    Feign內置的ribbon默認設置了請求超時時長,默認是1000,可以修改
    ribbon內部有重試機制,一旦超時,會自動重新發起請求。如果不希望重試可以關閉配置:
    修改服務地址輪詢策略,默認是輪詢,配置之后變隨機

    user-provider:
      ribbon:
        #輪詢
        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
        #隨機算法
        #NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
        ConnectTimeout: 10000 # 連接超時時間
        ReadTimeout: 2000 # 數據讀取超時時間
        MaxAutoRetries: 1 # 最大重試次數(第一個服務)
        MaxAutoRetriesNextServer: 0 # 最大重試下一個服務次數(集群的情況才會用到)
        OkToRetryOnAllOperations: false # 無論是請求超時或者socket read timeout都進行重試,一般設置為false
    

    1.5 熔斷器支持

    Feign默認也有對Hystrix的集成

    實現步驟:

    1. 在配置文件application.yml中開啟feign熔斷器支持
    2. 編寫FallBack處理類,實現FeignClient客戶端
    3. 在@FeignClient注解中,指定FallBack處理類。
    4. 測試

    1.5.1 開啟Hystrix

    在配置文件application.yml中開啟feign熔斷器支持:默認關閉

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

    1.5.2 熔斷降級類創建

    在user-consumer,創建類com.zengjx.feign.fallback.UserClientFallback,實現剛才編寫的UserClient,作為FallBack的處理類,代碼如下:

    @Component
    public class UserClientFallback implements UserClient {
        /**
         * 服務降級實現
         * @param id
         * @return
         */
        @Override
        public User findById(Integer id) {
            User user = new User();
            user.setUsername("Fallback,Feign服務降級。。。");
            return user;
        }
    }
    

    1.5.3 指定Fallback處理類

    在@FeignClient注解中,指定FallBack處理類

    
    
    @FeignClient(value = "user-provider",fallback = UserClientFallback.class)  //聲明Feign的客戶端,value:填寫生產者的名稱
    public interface UserClient {
    
        //注意:此處的請求地址一定要和生產者請求的地址一樣
        @RequestMapping("/user/{id}")
        public User findById(@PathVariable("id")Integer id);
    }
    
    

    1.5.3.1 遇到的錯誤

    Eureka 重啟
    接口跟controller 方法一致。
    錯誤記錄:
    錯誤位置:@RequestMapping("user")  
    public interface UserClient
    正確的是寫在方法上:
    public interface UserClient {
    //@RequestMapping("/user/{id}")
    /**
     * @ClassName HelloController
     * @Description TODO
     * @Author zengjx
     * @Company zengjx
     * @Date 2019/11/4  15:32
     * @Version V1.0
     */
    @FeignClient(value = "user-provider",
          fallback = UserClientFallBack.class
    //        configuration = FeignConfig.class  //配置feign配置信息
    )
    @RequestMapping("user")
    public interface UserClient {
     @RequestMapping("/{id}")
    //@RequestMapping("/user/{id}")
     User findUserById(@PathVariable(value ="id") Integer  id);
    }
    

    報錯信息:
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘requestMappingHandlerMapping’ defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map ‘zengjx.feign.UserClient’ method
    public abstract zengjx.domain.User zengjx.feign.UserClient.findUserById(java.lang.Integer)
    to { /user/{id}}: There is already ‘userClientFallBack’ bean method

    1.5.4 測試

    關閉服務生產者,請求http://localhost:18082/feign/1 ,效果如下:

    在這里插入圖片描述

    1.6 請求壓縮

    壓縮前:
    在這里插入圖片描述
    壓縮后: 節省空間
    在這里插入圖片描述
    SpringCloudFeign支持對請求和響應進行GZIP壓縮,以減少通信過程中的性能損耗。
    通過配置開啟請求與響應的壓縮功能:

    feign:
      hystrix:
        enabled: true # 開啟Feign的熔斷功能
      compression:
        request:
          enabled: true # 開啟請求壓縮
        response:
          enabled: true # 開啟響應壓縮
    也可以對請求的數據類型,以及觸發壓縮的大小下限進行設置
    feign:
      hystrix:
        enabled: true # 開啟Feign的熔斷功能
      compression:
        request:
          enabled: true # 開啟請求壓縮
          mime-types: text/html,application/xml,application/json # 設置壓縮的數據類型
          min-request-size: 2048 # 設置觸發壓縮的大小下限
          #以上數據類型,壓縮大小下限均為默認值
        response:
          enabled: true # 開啟響應壓縮
    

    1.7 Feign的日志級別配置

    通過loggin.level.xx=debug來設置日志級別。然而這個對Feign客戶端不會產生效果。因為@FeignClient注解修飾的客戶端在被代理時,都會創建一個新的Feign.Logger實例。我們需要額外通過配置類的方式指定這個日志的級別才可以。

    實現步驟:

    1. 在application.yml配置文件中開啟日志級別配置
    2. 編寫配置類,定義日志級別bean。
    3. 在接口的@FeignClient中指定配置類
    4. 重啟項目,測試訪問

    1.7.1 普通日志等級配置

    
    在user-consumer的配置文件中設置com.zengjx包下的日志級別都為debug
    #配置普通日志級別
    logging:
      level:
        com.zengjx: debug
    
    
    

    1.7.2 Feign日志等級配置

    在user-consumer中創建com.itheima.feign.conf.FeignConfig,定義日志級別

    @Configuration
    public class FeignConfig {
    
        /***
         * 日志級別
         */
        @Bean
        public Logger.Level feignLoggerLevel(){
            /**
             *  NONE:不記錄任何日志,默認值
             *     BASIC:僅記錄請求的方法,URL以及響應狀態碼和執行時間
             *     HEADERS:在BASIC基礎上,額外記錄了請求和響應的頭信息
             *     FULL:記錄所有請求和響應的明細,包括頭信息、請求體、元數據
             */
            return Logger.Level.FULL;
        }
    }
    
    

    1.7.3 指定配置類

    修改user-consumer的com.zengjx.feign.UserClient指定上面的配置類,代碼如下:
    //聲明Feign的客戶端,value:填寫生產者的名稱
    @FeignClient(value = “user-provider”,
    fallback = UserClientFallback.class, //配置熔斷器
    configuration = FeignConfig.class //配置日志級別
    )
    public interface UserClient {

    //注意:此處的請求地址一定要和生產者請求的地址一樣
    @RequestMapping("/user/{id}")
    public User findById(@PathVariable("id")Integer id);
    

    }

    1.7.4 重啟項目,即可看到每次訪問的日志

    1.8 小結

    ? Feign的作用:不再使用拼接URL的方式實現遠程調用,以接口調用的方式實現遠程調用,簡化了遠程調用的實現方式,增強了遠程調用的功能,例如:增加了負載均衡、熔斷、壓縮、日志啟用。
    ? 掌握Feign的使用過程
    properties
    1.引入Feign依賴包
    2.創建Feign接口,feign接口中需要指定調用的服務名字
    3.使用@EnabledFeignClients啟用Feign功能
    ? 掌握Feign的負載均衡配置
    properties
    在配置文件中配置
    {spring.application.name}負載均衡屬性配置
    ? 掌握Feign的熔斷配置
    properties
    1.在application.yml中開啟Hystrix
    2.給Feign接口創建一個實現類
    3.給Feign指定fallback類
    ? 掌握Feign的壓縮配置
    properties
    在application.yml中指定壓縮屬性即可
    ? 掌握Feign的日志配置
    properties
    1.在application.yml中開啟普通日志等級
    2.創建一個類,定義Feign日志等級
    3.在Feign接口中指定定義日志的配置

    2 網關 Spring Cloud Gateway

    2.1 目標

    ? 網關的作用
    ? 會配置動態路由
    ? 會配置過濾器
    ? 能自定義全局過濾器

    2.2 Gateway 簡介

    Spring Cloud Gateway 是Spring Cloud團隊的一個全新項目,基于Spring 5.0、SpringBoot2.0、Project Reactor 等技術開發的網關。旨在為微服務架構提供一種簡單有效統一的API路由管理方式。

    Spring Cloud Gateway 作為SpringCloud生態系統中的網關,目標是替代Netflix Zuul。Gateway不僅提供統一路由方式,并且基于Filter鏈的方式提供網關的基本功能。例如:安全,監控/指標,和限流。

    本身也是一個微服務,需要注冊到Eureka。
    網關的核心功能:過濾、路由
    ? 路由(route)
    ? 斷言Predicate函數:路由轉發規則
    ? 過濾器(Filter)

    2.3

    實現步驟:

    1. 創建gateway-service普通Maven工程
    2. 編寫基礎配置
    3. 編寫路由規則,配置靜態路由策略
    4. 啟動網關服務進行測試

    2.3.1 創建一個子工程gateway_service

    <?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>springcloud_parent</artifactId>
            <groupId>com.zengjx</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>gateway_service</artifactId>
        <dependencies>
    <!--    網關   -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
            </dependency>
            <!-- Eureka客戶端 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
    
        </dependencies>
    
    </project>
    

    2.3.2 創建啟動引導類

    創建啟動類com.zengjx.GatewayApplication,代碼如下:
    @SpringBootApplication
    @EnableDiscoveryClient// 開啟Eureka客戶端發現功能
    public class GatewayApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(GatewayApplication.class,args);
        }
    }
    
    
    

    2.3.3 application.yml配置

    # 注釋版本
    server:
      port: 18084
    spring:
      application:
        name: api-gateway # 應用名
    # Eureka服務中心配置
    eureka:
      client:
        service-url:
          # 注冊Eureka Server集群
          defaultZone: http://127.0.0.1:7001/eureka
    
    

    2.3.4 啟動引導類,查看Eureka控制臺

    在這里插入圖片描述

    2.4 路由配置

    通過網關配置一個路由功能,用戶訪問網關的時候,如果用戶請求的路徑是以/user開始,則路由到user-provider服務去,修改application.yml配置即可實現,配置如下:

    # 注釋版本
    server:
      port: 18084
    spring:
      application:
        name: api-gateway # 應用名
      cloud:
        gateway:
          routes:
            #id唯一標識,可自定義
            - id: user-service-route
              #路由的服務地址
              uri: http://localhost:18081
              # 路由斷言:路由攔截規則
              predicates:
                - Path=/user/**
    # Eureka服務中心配置
    eureka:
      client:
        service-url:
          # 注冊Eureka Server集群
          defaultZone: http://127.0.0.1:7001/eureka
    
    

    測試:
    啟動GatewayApplication測試 18084 是gateway 的配置文件配置的端口。
    訪問http://localhost:18084/user/2 會訪問user-provider服務,效果如下
    在這里插入圖片描述
    在這里插入圖片描述

    2.5 動態路由

    在這里插入圖片描述
    根據服務名稱**,去Eureka注冊中心查找服務對應的所有實例列表,然后進行動態路由!

    修改映射配置:通過服務名稱獲取,修改application.yml

    spring:
      application:
        name: api-gateway # 應用名
      cloud:
        gateway:
          routes:
            #id唯一標識,可自定義
            - id: user-service-route
              #路由的服務地址
              #lb協議表示從Eureka注冊中心獲取服務請求地址
              #user-provider訪問的服務名稱。
              #路由地址如果通過lb協議加服務名稱時,會自動使用負載均衡訪問對應服務
              uri: lb://user-provider
              # 路由斷言:路由攔截規則
              predicates:
                - Path=/user/**
    
    

    路由配置中uri所用的協議為lb時,gateway將把user-provider解析為實際的主機和端口,并通過Ribbon進行負載均衡。

    2.6 過濾器

    過濾器作為Gateway的重要功能。常用于請求鑒權、服務調用時長統計、修改請求或響應header、限流、去除路徑.

    2.6.1 過濾器的分類

    默認過濾器:出廠自帶,實現好了拿來就用,不需要實現
    全局默認過濾器
    局部默認過濾器
    自定義過濾器:根據需求自己實現,實現后需配置,然后才能用哦。
    全局過濾器:作用在所有路由上。
    局部過濾器:配置在具體路由下,只作用在當前路由上。
    默認過濾器幾十個,常見如下:
    過濾器名稱 說明
    AddRequestHeader 對匹配上的請求加上Header
    AddRequestParameters 對匹配上的請求路由
    AddResponseHeader 對從網關返回的響應添加Header
    StripPrefix 對匹配上的請求路徑去除前綴
    詳細說明官方說明鏈接
    https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.1.RELEASE/single/spring-cloud-gateway.html#_gatewayfilter_factories

    2.6.2 默認過濾器配置

    默認過濾器有兩個:全局默認過濾器和局部默認過濾器。

    2.6.2.1 全局過濾器

    全局過濾器:對輸出響應頭設置屬性
    對輸出的響應設置其頭部屬性名稱為X-Response-Default-MyName,值為zengjx
    修改配置文件

    spring:
      application:
        name: api-gateway # 應用名
      cloud:
        gateway:
          routes:
            #id唯一標識,可自定義
            - id: user-service-route
              #路由的服務地址
              #lb協議表示從Eureka注冊中心獲取服務請求地址
              #user-provider訪問的服務名稱。
              #路由地址如果通過lb協議加服務名稱時,會自動使用負載均衡訪問對應服務
              uri: lb://user-provider
              # 路由斷言:路由攔截規則
              predicates:
                - Path=/user/**
          #默認過濾器配置
          default-filters:
            # 往響應過濾器中加入響應頭信息
            - AddResponseHeader=X-Response-Default-MyName,zengjx
    
    

    查看瀏覽器響應頭信息!
    在這里插入圖片描述

    2.6.2.2 局部過濾器

    通過局部默認過濾器,修改請求路徑。局部過濾器在這里介紹兩種:添加路徑前綴、去除路徑前綴。

    2.6.2.2.1 添加路徑前綴

    在gateway中可以通過配置路由的過濾器PrefixPath 實現映射路徑中的前綴
    配置請求地址添加路徑前綴過濾器

    spring:
      application:
        name: api-gateway # 應用名
      cloud:
        gateway:
          routes:
            #id唯一標識,可自定義
            - id: user-service-route
              #路由的服務地址
              #lb協議表示從Eureka注冊中心獲取服務請求地址
              #user-provider訪問的服務名稱。
              #路由地址如果通過lb協議加服務名稱時,會自動使用負載均衡訪問對應服務
              uri: lb://user-provider
              # 路由斷言:路由攔截規則
              predicates:
                #- Path=/user/**
                #注意:要想接下來的前綴過濾器生效,此處攔截規則為所有url:/**
                - Path=/**
              filters:
                - PrefixPath=/user  # 給當前路由所有請求,添加"/user"前綴
    
          #默認過濾器配置
          default-filters:
            # 往響應過濾器中加入響應頭信息
            - AddResponseHeader=X-Response-Default-MyName,zengjx
    
    

    注意: 需要修改#- Path=/user/** 為- Path=/**
    路由地址信息:
    配置 訪問地址 路由地址
    PrefixPath=/user http://localhost:18084/2 http://localhost:18084/ user/2
    測試:瀏覽器訪問:http://localhost:18084/2 發現也可以查到用戶信息

    2.6.2.2.2 去除路徑前綴

    在gateway中通過配置路由過濾器StripPrefix,實現映射路徑中地址的去除。通過StripPrefix=1來指定路由要去掉的前綴個數。如:路徑/api/user/1將會被路由到/user/1。

    配置去除路徑前綴過濾器

    spring:
      application:
        name: api-gateway # 應用名
      cloud:
        gateway:
          routes:
            #id唯一標識,可自定義
            - id: user-service-route
              #路由的服務地址
              #lb協議表示從Eureka注冊中心獲取服務請求地址
              #user-provider訪問的服務名稱。
              #路由地址如果通過lb協議加服務名稱時,會自動使用負載均衡訪問對應服務
              uri: lb://user-provider
              # 路由斷言:路由攔截規則
              predicates:
                #- Path=/user/**
                #注意:要想接下來的前綴過濾器生效,此處攔截規則為所有url:/**
                - Path=/**
              filters:  #注意:PrefixPath與StripPrefix過濾器不要一起使用,一起使用等于沒配置過濾器
                #- PrefixPath=/user  # 給當前路由所有請求,添加"/user"前綴
                - StripPrefix=1  # 去除路徑前綴過濾器,一個"/"識別為一個路徑
          #默認過濾器配置
          default-filters:
            # 往響應過濾器中加入響應頭信息
            - AddResponseHeader=X-Response-Default-MyName,zengjx
    
    

    測試:
    瀏覽器訪問:http://localhost:18084/api/2 發現也可以查到用戶信息
    http://localhost:18085/add/user/1/
    在這里插入圖片描述
    路由地址信息:
    配置 訪問地址 路由地址
    StripPrefix=1 http://localhost:18084/api/user/2 http://localhost:18081/user/2
    StripPrefix=2 http://localhost:18084/api/r/user/2 http://localhost:18081/user/2

    2.6.3 自定義過濾器案例

    自定義過濾器也有兩個:全局自定義全局過濾器和自定義局部過濾器。
    自定義全局過濾器的案例:模擬登陸校驗。
    基本邏輯:如果請求中有token參數,則認為請求有效放行,如果沒有則攔截提示授權無效

    2.6.3.1 自定義全局過濾器

    實現步驟:
    1.在gateway-service工程編寫全局過濾器類實現GlobalFilter,Ordered
    2.編寫業務邏輯代碼
    3.訪問接口測試,加token和不加token。
    在gateway-service中創建com.zengjx.filter.LoginGlobalFilter全局過濾器類,代碼如下:

    @Component
    public class LoginGlobalFilter implements GlobalFilter, Ordered {
        /***
         * 過濾攔截
         * @param exchange
         * @param chain
         * @return
         */
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            //獲取請求參數token
            String token = exchange.getRequest().getQueryParams().getFirst("token");
            //如果沒有傳入token
            if(StringUtils.isEmpty(token)){
                //設置返回狀態碼-400參數異常
                exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
                //結束請求
                return exchange.getResponse().setComplete();
            }
            //傳入了token,放行
            return chain.filter(exchange);
        }
    
        /***
         * 定義過濾器執行順序
         * 返回值越小,越靠前執行
         * @return
         */
        @Override
        public int getOrder() {
            return 0;
        }
    }
    
    

    測試:不攜帶token http://localhost:18084/api/user/find/2效果如下:
    在這里插入圖片描述
    測試:攜帶token http://localhost:18084/api/user/2?token=abc 此時可以正常訪問。

    2.6.3.2 自定義局部過濾器(了解)

    自定義局部過濾器,該過濾器在控制臺輸出配置文件中指定名稱的請求參數及參數的值

    實現步驟:

    1. 在gateway-service中編寫MyParamGatewayFilterFactory類
    2. 實現業務代碼:循環請求參數中是否包含name,如果包含則輸出參數值
    3. 修改配置文件
    4. 訪問請求測試,帶name參數

    在gateway_service中編寫MyParamGatewayFilterFactory類,此類不需要大家掌握,可以直接復制項目使用
    /**

    • 自定義局部過濾器
    • 注意的點:{
    • 類名必須是:前綴+GatewayFilterFactory
      
    • 必須有構造函數
      
    • 必須要有個內部類:Config
      
    • 處理當前排序方法:shortcutFieldOrder
      
    • 處理過濾器邏輯:apply
      
    • }
      */
    
    @Component
    public class MyParamGatewayFilterFactory extends AbstractGatewayFilterFactory<MyParamGatewayFilterFactory.Config> {
        /**
         * 定義需要處理的參數
         */
        public static final String PARAM_NAME = "name";
    
        /****
         * 處理過程
         * @return
         */
        @Override
        public GatewayFilter apply(MyParamGatewayFilterFactory.Config config) {
            return new GatewayFilter() {
                @Override
                public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                    String name = exchange.getRequest().getQueryParams().getFirst("name");
                    if(!StringUtils.isEmpty(name)){
                        System.out.println("名字參數:"+name);
                    }
                    return chain.filter(exchange);
                }
            };
        }
    
        /***
         * 構造函數
         */
        public MyParamGatewayFilterFactory() {
            super(MyParamGatewayFilterFactory.Config.class);
        }
    
        /***
         * 處理字段的排序
         * @return
         */
        @Override
        public List<String> shortcutFieldOrder() {
            return Arrays.asList(PARAM_NAME);
        }
    
        /****
         * 需要處理的參數
         * name:和處理的參數名字保持一致
         */
        public static class Config {
            private String name;
    
            public String getName() {
                return name;
            }
            public void setName(String name) {
                this.name = name;
            }
        }
    }
    

    修改application.yml配置文件 - MyParam=name

    spring:
      application:
        name: api-gateway # 應用名
      cloud:
        gateway:
          routes:
            #id唯一標識,可自定義
            - id: user-service-route
              #路由的服務地址
              #lb協議表示從Eureka注冊中心獲取服務請求地址
              #user-provider訪問的服務名稱。
              #路由地址如果通過lb協議加服務名稱時,會自動使用負載均衡訪問對應服務
              uri: lb://user-provider
              # 路由斷言:路由攔截規則
              predicates:
                #- Path=/user/**
                #注意:要想接下來的前綴過濾器生效,此處攔截規則為所有url:/**
                - Path=/**
              filters:  #注意:PrefixPath與StripPrefix過濾器不要一起使用,一起使用等于沒配置過濾器
                #- PrefixPath=/user  # 給當前路由所有請求,添加"/user"前綴
                - StripPrefix=1  # 去除路徑前綴過濾器,一個"/"識別為一個路徑
                #配置自定義局部過濾器,此處的名字與過濾器聲明時的前綴一致
                - MyParam=name
          #默認過濾器配置
          default-filters:
            # 往響應過濾器中加入響應頭信息
            - AddResponseHeader=X-Response-Default-MyName,zengjx
    

    測試訪問,檢查后臺是否輸出name和itcast;訪問http://localhost:18084/api/user/find/2?name=itheima&token=aaa 會輸出。

    2.6.4 微服務架構加入Gateway后

    不管是來自客戶端的請求,還是服務內部調用。一切對服務的請求都可經過網關。
    網關實現鑒權、動態路由等等操作。
    Gateway就是我們服務的統一入口
    在這里插入圖片描述

    2.7 小結

    ? 網關的作用
    properties
    1.為微服務架構提供一種簡單有效統一的API路由管理方式
    2.可以在網關中實現微服務鑒權、安全控制、請求監控、限流
    ? 會配置動態路由
    properties
    使用lb配置,能根據服務名字動態請求。
    ? 會配置過濾器
    properties
    默認過濾器:default-filters:
    ? 能自定義全局過濾器
    properties
    編寫過濾器類,實現GlobalFilter和Ordered,在filter方法中實現過濾。

    3 配置中心 Spring Cloud Config

    3.1 目標
    ? 了解配置中心的作用
    ? 能配置Git倉庫
    ? 能搭建配置中心
    ? 修改微服務,從配置中心獲取修改的配置
    3.2 Config簡介
    分布式系統中,由于服務數量非常多,配置文件分散在不同微服務項目中,管理極其不方便。為了方便配置文件集中管理,需要分布式配置中心組件。在Spring Cloud中,提供了Spring Cloud Config,它支持配置文件放在配置服務的本地,也支持配置文件放在遠程倉庫Git(GitHub、碼云)。配置中心本質上是一個微服務,同樣需要注冊到Eureka服務中心!
    在這里插入圖片描述
    3.3 Git配置管理
    3.3.1 遠程Git倉庫
    知名的Git遠程倉庫有國外的GitHub和國內的碼云(gitee);
    GitHub主服務在外網,訪問經常不穩定,如果希望服務穩定,可以使用碼云;
    碼云訪問地址:http://gitee.com 測試地址:https://gitee.com/zengjx/config.git

    3.3.2 創建遠程倉庫
    首先使用碼云上的git倉庫需要先注冊賬戶。
    賬戶注冊完成,然后使用賬戶登錄碼云控制臺并創建公開倉庫
    在這里插入圖片描述
    配置倉庫 名稱和路徑
    在這里插入圖片描述

    3.3.3 創建配置文件

    在新建的倉庫中創建需要被統一配置管理的配置文件
    在這里插入圖片描述

    3.3.3.4文件命名有規則:

    配置文件的命名方式:{application}-{profile}.yml或{application}-{profile}.properties
    application為應用名稱
    profile用于區分開發環境dev,測試環境test,生產環境pro等
    開發環境 user-dev.yml
    測試環境 user-test.yml
    生產環境 user-pro.yml

    在這里插入圖片描述
    創建一個user-provider-dev.yml文件
    將user-provider工程里的配置文件application.yml內容復制進去。

    server:
      port: 18081
    spring:
      datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        username: root
        password: root
        url: jdbc:mysql://127.0.0.1:3306/springcloud?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
      application:
        name: user-provider #服務的名字,不同的應用,名字不同,如果是集群,名字需要相同
    
    #指定eureka服務地址
    eureka:
      client:
        service-url:
          # EurekaServer的地址
          defaultZone: http://localhost:7001/eureka
        # 每隔30獲取服務列表(只讀備份)
        registry-fetch-interval-seconds: 30
    
      instance:
        #指定IP地址
        ip-address: 127.0.0.1
        #訪問服務的時候,推薦使用IP
        prefer-ip-address: true
        #租約到期,服務時效時間,默認值90秒
        lease-expiration-duration-in-seconds: 150
        #租約續約間隔時間,默認30秒
        lease-renewal-interval-in-seconds: 30
    
    
    

    創建完user-provider-dev.yml配置文件之后,gitee中的倉庫如下:
    在這里插入圖片描述
    3.3.3.5 遇到訪問碼云沒有權限
    問題:
    沒有權限:
    在這里插入圖片描述

    設置為公開:

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

    rg.eclipse.jgit.api.errors.TransportException: https://gitee.com/zengjx/config.git: Authentication is required but no CredentialsProvider has been registered

    4 【異常】org.eclipse.jgit.api.errors.TransportException: [email protected]/base-config-center.git: channel is not opened.
    一、異常原因
    連不上git倉庫,可能原因有:
    1.)git倉庫不存在
    2)連接git倉庫超時
    原因是;上面碼云倉庫設置為公開后沒有點擊保存:
    rg.eclipse.jgit.api.errors.TransportException: https://gitee.com/zengjx/config.git: Authentication is required but no CredentialsProvider has been registered

    4 【異常】org.eclipse.jgit.api.errors.TransportException: [email protected]/base-config-center.git: channel is not opened.

    在這里插入圖片描述

    4.1 搭建配置中心微服務

    實現步驟:

    1. 創建配置中心SpringBoot項目config_server
    2. 配置坐標依賴
    3. 啟動類添加開啟配置中心服務注解
    4. 配置服務中心application.yml文件
    5. 啟動測試
      4.1.1 創建工程 conf_server
    
    ```java
    <?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>springcloud_parent</artifactId>
            <groupId>com.zengjx</groupId>
            <version>0.0.1-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>conf_server</artifactId>
    
        <dependencies>
            <!-- Eureka客戶端 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
            <!--配置中心-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-config-server</artifactId>
            </dependency>
        </dependencies>
    </project>
    
    

    4.1.3 application.yml配置文件

    
    ```java
    # 注釋版本
    server:
      port: 18085 # 端口號
    spring:
      application:
        name: config-server # 應用名
      cloud:
        config:
          server:
            git:
              # 配置gitee的倉庫地址
              uri: https://gitee.com/StevenBlake/conf.git
    # Eureka服務中心配置
    eureka:
      client:
        service-url:
          # 注冊Eureka Server集群
          defaultZone: http://127.0.0.1:7001/eureka
    # com.itheima 包下的日志級別都為Debug
    logging:
      level:
        com: debug
    
    

    4.1.4 測試

    啟動config-server,訪問http://localhost:18085/user-provider-dev.yml ,效果如下

    ![在這里插入圖片描述](https://img-blog.csdnimg.cn/20191105171152999.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L29EaWFuWmkxMjM0NTY3,size_16,color_FFFFFF,t_70)
    可以查看到碼云上的文件數據,并且可以在gitee上修改user-dev.yml,然后刷新上述測試地址也能及時更新數據。
    
    ## 4.2	服務去獲取配置中心配置
    目標:改造user-provider工程,配置文件不再由微服務項目提供,而是從配置中心獲取。
    目標:改造user-provider工程,配置文件不再由微服務項目提供,而是從配置中心獲取。
    
    實現步驟:
    1. 添加配置中心客戶端啟動依賴
    2. 修改服務提供者的配置文件
    3. 啟動服務
    4. 測試效果
    4.2.1.1	添加依賴
    
    ```java
    <!--spring cloud 配置中心-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-config</artifactId>
    </dependency>
    

    4.2.1.2 修改配置
    刪除user-provider工程的application.yml文件
    創建user-provider工程bootstrap.yml配置文件,配置內容如下

    # 注釋版本
    spring:
      cloud:
        config:
          name: user-provider # 與遠程倉庫中的配置文件的application保持一致,{application}-{profile}.yml
          profile: dev # 遠程倉庫中的配置文件的profile保持一致
          label: master # 遠程倉庫中的版本保持一致
          discovery:
            enabled: true # 使用配置中心
            service-id: config-server # 配置中心服務id
    #向Eureka服務中心集群注冊服務
    eureka:
      client:
        service-url:
          defaultZone: http://127.0.0.1:7001/eureka
    
    

    關于application.yml和bootstrap.yml文件的說明:

    • bootstrap.yml文件是SpringBoot的默認配置文件,而且其加載時間相比于application.yml更早。
    • bootstrap.yml和application.yml都是默認配置文件,但定位不同
      • bootstrap.yml可以理解成系統級別的一些參數配置,一般不會變動
      • application.yml用來定義應用級別的參數
    • 搭配spring-cloud-config使用application.yml的配置可以動態替換。
    • bootstrap.yml相當于項目啟動的引導文件,內容相對固定
    • application.yml文件是微服務的常規配置參數,變化比較頻繁

    4.2.1.3 啟動測試

    啟動eurake服務中心、conf配置中心、user_provider如果啟動沒報錯,其實已經使用上配置中心內容了
    在這里插入圖片描述
    可以在服務中心查看也可以檢驗user_service的服務

    在這里插入圖片描述

    4.3.1 修改碼云配置文件

    修改在碼云上的user-provider-dev.yml文件,添加一個屬性test.message,如下操作:
    在這里插入圖片描述

    4.3.2 讀取配置文件數據

    在user-provider工程中創建一個com.zengjx.controller.LoadConfigController讀取配置文件信息,代碼如下:

    @RestController
    @RequestMapping(value = "config")
    public class LoadConfigController {
    
        @Value("${test.message}")
        private String msg;
    
        /***
         * 讀取配置文件中的數據
         * @return
         */
        @RequestMapping(value = "load")
        public String load(){
            return msg;
        }
    }
    
    

    啟動運行user-provider,訪問http://localhost:18081/config/load
    在這里插入圖片描述
    修改碼云上的配置后,發現項目中的數據仍然沒有變化,只有項目重啟后才會變化。
    4.4 小結
    ? 配置中心的作用:將各個微服務的配置文件集中到一起進行統一管理。
    ? 能搭建配置中心
    需要在application.yml配置文件中指定需要遠程更新的倉庫地址。
    ? 修改微服務,從配置中心獲取修改的配置
    properties:

     創建bootstrap.yml,并在bootstrap.yml中配置
      # 注釋版本
      spring:
        cloud:
          config:
            name: user-provider # 與遠程倉庫中的配置文件的application保持一致,{application}-{profile}.yml
            profile: dev # 遠程倉庫中的配置文件的profile保持一致
            label: master # 遠程倉庫中的版本保持一致
            discovery:
              enabled: true # 使用配置中心
              service-id: config-server # 配置中心服務id
      #向Eureka服務中心集群注冊服務
      eureka:
        client:
          service-url:
            defaultZone: http://127.0.0.1:7001/eureka
    
    

    5 消息總線 Spring Cloud Bus

    SpringCloud Bus,解決上述問題,實現配置自動更新。
    注意:SpringCloudBus基于RabbitMQ實現,默認使用本地的消息隊列服務,所以需要提前安裝并啟動RabbitMQ。安裝參考./04資料/安裝Windows RabbitMQ.pdf

    5.1 Bus簡介

    Bus是用輕量的消息代理將分布式的節點連接起來,可以用于廣播配置文件的更改或者服務的監控管理。
    Bus可以為微服務做監控,也可以實現應用程序之間互相通信。Bus可選的消息代理RabbitMQ和Kafka。
    廣播出去的配置文件服務會進行本地緩存。

    5.2 整合案例

    目標:消息總線整合入微服務系統,實現配置中心的配置自動更新。不需要重啟微服務。

    5.2.1 改造配置中心

    改造步驟:
    ? 在config-server項目中加入Bus相關依賴
    ? 修改application.yml,加入RabbitMQ的配置信息,和暴露觸發消息總線地址

    5.2.1.1 引入依賴

    修改config-server的pom.xml引入依賴:

    <!--消息總線依賴-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-bus</artifactId>
    </dependency>
    <!--RabbitMQ依賴-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
    </dependency>
    
    

    5.2.1.2 修改application.yml配置文件

    修改config-server的application.yml,如下配置的rabbit都是默認值,其實可以完全不配置,代碼如下:

    # 注釋版本
    server:
      port: 18085 # 端口號
    spring:
      application:
        name: config-server # 應用名
      cloud:
        config:
          server:
            git:
              # 配置gitee的倉庫地址
              uri: https://gitee.com/StevenBlake/conf.git
      # rabbitmq的配置信息;如下配置的rabbit都是默認值,其實可以完全不配置
      rabbitmq:
        host: localhost
        port: 5672
        username: guest
        password: guest
    # 暴露觸發消息總線的地址
    management:
      endpoints:
        web:
          exposure:
            # 暴露觸發消息總線的地址
            include: bus-refresh
    # Eureka服務中心配置
    eureka:
      client:
        service-url:
          # 注冊Eureka Server集群
          defaultZone: http://127.0.0.1:7001/eureka
    # com.itheima 包下的日志級別都為Debug
    logging:
      level:
        com: debug
    

    5.2.2 改造用戶服務

    改造步驟:

    1. 在用戶微服務user_provider項目中加入Bus相關依賴
    2. 修改user_provider項目的bootstrap.yml,加入RabbitMQ的配置信息
    3. UserController類上加入@RefreshScope刷新配置注解
    4. 測試

    5.2.2.1 引入依賴

    修改user-provider引入如下依賴:

    <!--消息總線依賴-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-bus</artifactId>
    </dependency>
    <!--RabbitMQ依賴-->
    <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>
    
    

    5.2.2.2 添加bootstrap.yml文件

    在user-provider的resources目錄下添加bootstrap.yml,添加rabbitmq配置,代碼如下:

    # 注釋版本
    spring:
      cloud:
        config:
          name: user-provider # 與遠程倉庫中的配置文件的application保持一致,{application}-{profile}.yml
          profile: dev # 遠程倉庫中的配置文件的profile保持一致
          label: master # 遠程倉庫中的版本保持一致
          discovery:
            enabled: true # 使用配置中心
            service-id: config-server # 配置中心服務id
      # rabbitmq的配置信息;如下配置的rabbit都是默認值,其實可以完全不配置
      rabbitmq:
        host: localhost
        port: 5672
        username: guest
        password: guest
    #向Eureka服務中心集群注冊服務
    eureka:
      client:
        service-url:
          defaultZone: http://127.0.0.1:7001/eureka
    
    5.2.2.3	添加刷新配置
    修改user-provider的com.itheima.controller.LoadConfigController,添加一個@RefreshScope注解刷新配置信息,代碼如下:
    @RestController
    @RequestMapping(value = "config")
    @RefreshScope  //用于啟用刷新配置文件的信息
    public class LoadConfigController {
    
        @Value("${test.message}")
        private String msg;
    
        /***
         * 讀取配置文件中的數據
         * @return
         */
        @RequestMapping(value = "load")
        public String load(){
            return msg;
        }
    }
    
    

    5.2.3 測試

    目標:當我們修改Git倉庫的配置文件,用戶微服務是否能夠在不重啟的情況下自動更新配置文件信息。

    測試步驟:
    (1)啟動eureka-server
    (2)啟動config-server
    (3)啟動user-provider
    (4)訪問測試
    訪問http://localhost:18081/config/load ,效果如下:

    (5)修改碼云配置
    修改碼云的配置,修改后并提交,修改如下:

    (6)刷新配置

    使用Postman以POST方式請求http://localhost:18085/actuator/bus-refresh
    http://localhost:18086/actuator/bus-refresh
    在這里插入圖片描述

    也可以用idea 自帶的:
    在這里插入圖片描述
    在這里插入圖片描述
    請求地址中actuator是固定的,bus-refresh對應的是配置中心的config-server中的application.yml文件的配置項include的內容
    (7)刷新測試
    訪問http://localhost:18081/config/load ,效果如下:

    (7)刷新測試
    訪問http://localhost:18081/config/load
    消息總線實現消息分發過程:
    ? 請求地址訪問配置中心的消息總線
    ? 消息總線接收到請求
    ? 消息總線向消息隊列發送消息
    ? user-service微服務會監聽消息隊列
    ? user-service微服務接到消息隊列中消息后
    ? user-service微服務會重新從配置中心獲取最新配置信息

    什么時候使用了MQ?
    https://blog.csdn.net/u010255818/article/details/77855873/

    版權聲明:本文為oDianZi1234567原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/oDianZi1234567/article/details/102917937

    智能推薦

    springCloud搭建詳細教程

    springCloud搭建詳細教程 別的都不說了,直接動手: SpringCloud分布式開發五大組件詳解 服務發現——Netflix Eureka 客服端負載均衡——Netflix Ribbon 斷路器——Netflix Hystrix 服務網關——Netflix Zuul 分布式配置—&...

    springcloud筆記

    SpringCloud 微服務概述 [馬丁福勒微服務論文] : https://martinfowler.com/articles/microservices.html 什么是微服務 目前的微服務并沒有一個統一的標準,一般是以業務來劃分 將傳統的一站式應用,拆分成一個個的服務,徹底去耦合,一個微服務就是單功能業務,只做一件事。 與微服務相對的叫巨石 微服務與微服務架構 微服務是一種架構模式或者一種...

    SpringCloud 筆記

    文章目錄 一、SpringCloud介紹 1.1 微服務架構 1.2 SpringCloud介紹 二、服務的注冊與發現-Eureka【`重點`】 2.1 引言 2.2 Eureka的快速入門 2.2.1 創建EurekaServer 2.2.2 創建EurekaClient 2.2.3 測試Eureka 2.3 Eureka的安全性 2.4 Eureka的高可用 2.5 Eureka的細節 三、服...

    SpringCloud筆記

    SpringCloud 框架 一、分布式概念 1、分布式的優點 處理高并發問題: ? 面對越來越大的業務量,一臺機器的性能已經無法滿足。我們需要多臺機器才能滿足高并發的需求。因此我 們需要垂直或水平拆分業務系統,讓它變成一個分布式的架構。 加強系統可用性: ? 為了我們的系統不會因為一臺機器出故障二導致整個系統不可用。所以需要利用分布式來消除單點故障,提 高系統可用性。 把模塊拆分,使用接口通信,...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    猜你喜歡

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    精品国产乱码久久久久久蜜桃不卡