1. 程式人生 > 實用技巧 >springcloud-feign&gateway&config&bus

springcloud-feign&gateway&config&bus

一 feign

集成了ribbon負載均衡功能,集成了hystrix熔斷器功能。支援請求壓縮

1 使用feign替代resttemplate傳送rest請求

1)在consumer中匯入依賴openfeign 2)建立feign客戶端,面向介面程式設計,@feignclient註解,屬性賦值服務名;方法上寫方法請求對映。feign通過動態代理生成實現類 3) 控制層,注入Feign客戶端介面,面向介面程式設計呼叫方法實現遠端呼叫服務提供者的對應方法 4)啟動類使用 `@EnableFeignClients`註解開啟feign 接收路徑攜帶引數變數不能省略賦值,@PathVariable路徑變數、@RequestParam請求引數 int login(@RequestParam("s") String s); //這裡是引數變數用@RequestParam("s")註解,路徑變數則用@PathVariable("s") //可以傳遞普通引數,不能傳遞Java物件,Java物件只能轉換為json字串格式

2負載均衡

用resttemplate還要加上@loadbalanced註解 配置檔案
# 修改服務地址輪詢策略,預設是輪詢,配置之後變隨機
# MaxAutoRetriesNextServer: 0 # 最大重試下一個服務次數(叢集的情況才會用到,一起來規律是1=2,2 2=2,4 3=4,4 4=4,6 5=6,6)
user-provider:
  ribbon:
    #輪詢
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
    ConnectTimeout: 10000 # 連線超時時間,比如修改服務提供者的ip讓你連不上那你消費者肯定連線超時報錯
    ReadTimeout: 
2000 # 資料讀取超時時間,這個是連上服務提供者,然後伺服器提供者程式執行超過2秒報錯 MaxAutoRetries: 1 # 最大重試次數(第一個服務),比如連上了,但讀取超時再重去嘗試讀取1次,控制器被訪問↓ MaxAutoRetriesNextServer: 0 # 最大重試下一個服務次數(叢集的情況才會用到,一起來規律在上↑) OkToRetryOnAllOperations: false # 無論是請求超時或者socket read timeout等情況都進行重試

3熔斷器

也就是發生故障不走動態代理生成的實現類,走自定義的介面實現類來降級 1)配置檔案開啟feign熔斷器支援
feign:
  hystrix:
    enabled: 
true # 開啟Feign的熔斷功能
2)熔斷降級類 實現介面:自定義方法體。注意實現類需加上@component註解,才能把物件交給spring容器。 也可以採用內部類方式 3)在介面@feignclient註解內給屬性fallback賦值來指定降級類

4feign壓縮yml配置

對請求和響應進行GZIP壓縮,以減少通訊過程中的效能損耗。 通過配置開啟請求與響應的壓縮功能compression:
feign:
    compression:
        request:
            enabled: true # 開啟請求壓縮
        response:
            enabled: true # 開啟響應壓縮

也可對請求資料型別,及觸發壓縮上下限進行設定

5feign日誌級別配置類

普通日誌等級配置
# com.ywj 包下的日誌級別都為Debug
logging:
  level:
    com.ywj: debug
feign日誌等級配置。除了使用配置類,也可以在啟動類內通過@bean注入給spring容器管理。
@Configuration//配置類註解!
public class FeignConfig {
    /**
     * 日誌級別
     * @return
     */
    @Bean
    public Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL;
    }
}

二 spring cloud gateway閘道器

核心:過濾,路由 同樣作為一個微服務,需註冊到eureka;工程pom檔案匯入閘道器依賴及eureka客戶端依賴;啟動類新增開啟發現客戶端註解;配置檔案,埠,應用名,eureka地址

1路由配置

靜態路由--動態路由 區域性過濾器--全域性過濾器
spring:
  cloud:
    gateway:
      routes:
        # id唯一標識,可自定義
        - id: gate-service-route
          #路由服務地址
          #靜態路由策略
          # uri: http://localhost:18081
          #動態,lb協議表示從Eureka註冊中心獲取服務請求地址,應該用服務名叢集訪問,會使用負載均衡訪問對應服務,負載均衡LoaderBalance
          uri: lb://user-provider
          #路由攔截地址配置(斷言)
          predicates:
            - Path=/**   #注意首字母P要是大寫的,2個*
          # 配置區域性過濾器
          filters:
            # 請求地址新增路徑字首過濾器
            #- PrefixPath=/user
            # 去除路徑字首過濾器
            - StripPrefix=1
            - My
       # 配置全域性預設過濾器
      default-filters:
            # 往響應過濾器中加入資訊
        - AddResponseHeader=X-Response-Default-MyName,ywj

注意:斷言,過濾器等關鍵字key首字母大寫。- Path=/** #注意首字母P要是大寫的,2個*

2自定義過濾器

1)全域性過濾器

package com.zl.filter;
 
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component//這個不能少,建立物件才能呼叫下面的非靜態方法↓
public class LoginGlobalFilter implements GlobalFilter, Ordered {
    /**
     * 過濾攔截
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //獲取請求引數
        //千萬不要點錯用這個方法String token =    request.getQueryParams().get("token").get(0);//NullPointerException,否則出現空指標異常
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        System.out.println("通過全域性過濾器");
        //如果token為空,則表示沒有登入
        if(StringUtils.isEmpty(token)){
            //沒登入,狀態設定413
            exchange.getResponse().setStatusCode(HttpStatus.PAYLOAD_TOO_LARGE);
            //結束請求
            return exchange.getResponse().setComplete();
        }
 
        //放行
        return chain.filter(exchange);
    }
 
    /**
     * 定義過濾器執行順序
     * 返回值越小,越靠前執行,可以理解為預設從小到大執行
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}

2)區域性過濾器

自定義區域性攔截器,要注意自定義類的字首用在配置檔案,字尾必須是指定工廠字尾
package com.zl.filter;
 
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
 
@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config> {
    public MyGatewayFilterFactory() {
        super(MyGatewayFilterFactory.Config.class);
    }
 
    @Override
    public GatewayFilter apply(Config config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                System.out.println("通過區域性過濾器");
                MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams();
                String token = queryParams.getFirst("token");
                ServerHttpResponse response = exchange.getResponse();
                if (token == null) {
                    return response.setComplete();
                }
                return chain.filter(exchange);
            }
        };
    }
 
    public static class Config {
    }
}