SpringCloud Gateway網關

SpringCloud Gateway網關
在提供一種簡單而有效的方式來路由到API塑悼,提供例如:安全性摘悴,監(jiān)控指標等功能稚铣。

官方說明文檔

//官方
https://spring.io/projects/spring-cloud-gateway#overview
//官方說明文檔
https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/index.html#gateway-starter
image.png
image.png

Spring Cloud Gateway的工作方式:

官網截圖.png

三個重要部分

Route路由

網關的基本構建單元是整。它由ID,URI拭嫁,匹配規(guī)則集合和過濾集合定義可免。

Predicate 判定器

判斷請求走哪條路由規(guī)則。匹配來自HTTP請求的如何內容做粤,例如標頭或者參數浇借。

Filter 過濾器

用于在發(fā)送下游請求之前或之后修改請求和響應

內置路由選擇器

Route Predicate Factories

路由選擇器 描述
After 匹配在指定日期之后發(fā)生的請求
Before 匹配在指定日期時間之前發(fā)生的請求
Between 匹配在指定日期時間之間發(fā)生的請求
Cookie 匹配具有指定Cookie值的請求
Header 匹配header中具有指定名稱且值與正則表達式匹配的請求
Host 匹配指定的host
Method 匹配指定的method
Path 匹配指定的請求路徑
Query 匹配指定的查詢參數
RemoteAddr 匹配指定的客戶端ip
image.png

內置過濾器

GatewayFilter Factories

過濾器類型 描述
AddRequestHeader 網關下游請求發(fā)起前,增加請求的header
AddRequestParameter 網關下游請求發(fā)起前怕品,增加請求的參數
AddResponseHeader 網關下游響應之后妇垢,增加響應的header
Hystrix 為該路由增加熔斷器
FallbackHeaders 熔斷后,為響應增加一個降級的header
PrefixPath 設置發(fā)起網關下游請求的路徑前綴(隱藏真實路徑)
PreserveHostheader 網關發(fā)起下游請求時,是否在header中附帶原請求中的host
RequestRateLimiter 網關限流器(可選擇結合redis實現(xiàn))
RedirectTo 將該路由的請求重定向到指定地址
RemoveNoProxyHeaders 網關發(fā)起下游請求時修己,刪除指定header(默認刪除一系列header名)
RemoveRequestHeader 網關下游請求發(fā)起前恢总,刪除指定的請求header
RemoveResponseHeader 網關下游響應之后,刪除指定的響應的header
RewritePath 請求路徑重寫
RewriteResponseHeader 重寫指定的響應header
SaveSession 網關保存session會話
SecureHeaders 為響應內容增加一系列和安全相關的header信息
SetPath 路徑修改(重寫類型)
SetResponseheader 替換(不是新增)指定的響應header
SetStatus 設置該路由的響應狀態(tài)碼
StripPrefix 網關在發(fā)起請求之前睬愤,根據/分隔刪除部分url路徑(eg:2,則/name/bar/foo變?yōu)?foo)
Retry 為指定路由開啟錯誤重試機制
RequestSize 請求內容大小限制纹安,超出大小則返回413Payload Too Large
Modify Request Body 網關修改客戶端的請求內容尤辱,僅支持代碼設置(實質性功能)
Modify Response Body 網關修改下游的響應內容,僅支持代碼設置(實質性功能)
LoadBalancerClient 自定義路由的負載均衡(配置ribbon服務后厢岂,路由的uri修改為lb:service)(eureka無關)
Websocket 支持websocket代理(配置方式uri:ws://localhost:3001
Gateway Metrics Filter 開啟路由metrics功能(spring.cloud.gateway.metrics.enabled=true默認false關閉)
default filters 要添加過濾器并將其應用于所有路由
image.png

全局過濾器

GlobalFilter

//官網示例
@Bean
public GlobalFilter customFilter() {
    return new CustomGlobalFilter();
}
public class CustomGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("custom global filter");
        return chain.filter(exchange);
    }
    @Override
    public int getOrder() {
        return -1;
    }
}

局部過濾器

GatewayFilter

@Configuration
public class GatewayFilterConfig {

//    /**
//     * 把過濾器注入容器
//     * @return
//     */
    @Bean
    TestGatewayFilterFactory testGatewayFilterFactory(){
        return new TestGatewayFilterFactory();
    }
}

/**
 * 局部過濾器
 * 
 */
public class TestGatewayFilterFactory extends AbstractGatewayFilterFactory<TestGatewayFilterFactory.Config> {

    /**
     * 定義可以再yaml中聲明的屬性變量
     */
    private static final String TYPE = "type";//參數
    private static final String TYPE_2 = "type_2";//參數2

    public TestGatewayFilterFactory(){
        //這里需要將自定義的config傳過去光督,否則會報告ClassCastException
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        System.err.println("GatewayFilter config 自定義過濾器工廠,config="+config.toString());
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                System.err.println("GatewayFilter config 自定義過濾器工廠 filter==");
                return chain.filter(exchange);
            }
        };
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(TYPE, TYPE_2);
    }

    //自定義的config類,用來設置傳入的參數
    public static class Config{
        //Put the configuration properties for your filter here
        /**
         * 過濾類型
         */
        private String type;

        /**
         * 操作
         */
        private String type_2;

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getType_2() {
            return type_2;
        }

        public void setType_2(String type_2) {
            this.type_2 = type_2;
        }

        @Override
        public String toString() {
            return "Config{" +
                    "type='" + type + '\'' +
                    ", type_2='" + type_2 + '\'' +
                    '}';
        }
    }

}

在application.yml配置文件,配置自定義filters

spring:
  application:
    name: spring-cloud-gateway
  cloud:
    gateway:
      # 路由 id
      routes:
        - id: study
          # 注冊服務的名: lb://
          uri: lb://server-demo
          predicates:  #斷言
            - Path=/index/**
#           - Query=paramA
           # - Before=2020-04-20T06:06:06+08:00[Asia/Shanghai]
          filters:
            - name: Test
              args:
                type: root
                type_2: 1112233333
image.png

集成示例

1 . pom導入依賴

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
    </properties>

    <dependencies>
      <!--gateway 包含了web-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--netflix-eureka-client注冊中心客戶端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

    </dependencies>

配置

@Configuration
public class GatewayFilterConfig {

//    /**
//     * 把過濾器注入容器
//     * @return
//     */

    @Bean
    TestGatewayFilterFactory testGatewayFilterFactory(){
        return new TestGatewayFilterFactory();
    }

    /**
     * 全局過濾鏈
     * @return
     */
    @Bean
    public GlobalFilter customFilter() {
        return new CustomGlobalFilter();
    }

    /**
     * 全局攔截
     * 全局過濾器GlobalFilter
     */
    public class CustomGlobalFilter implements GlobalFilter, Ordered {

        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            System.err.println("GlobalFilter CustomGlobalFilter ");
            return chain.filter(exchange);
        }

        /**
         * 攔截順序
         * @return
         */
        @Override
        public int getOrder() {
            return -1;
        }
    }
}

TestGatewayFilterFactory 局部過濾器

/**
 * 局部過濾器
 *
 */
public class TestGatewayFilterFactory extends AbstractGatewayFilterFactory<TestGatewayFilterFactory.Config> {

    /**
     * 定義可以再yaml中聲明的屬性變量
     */
    private static final String TYPE = "type";//參數
    private static final String TYPE_2 = "type_2";//參數2

    public TestGatewayFilterFactory(){
        //這里需要將自定義的config傳過去塔粒,否則會報告ClassCastException
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        System.err.println("GatewayFilter config 自定義過濾器工廠,config="+config.toString());
//        return new GatewayFilter() {
//            @Override
//            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//                System.err.println("GatewayFilter config 自定義過濾器工廠 filter==");
//                return chain.filter(exchange);
//            }
//        };
        return new InnerFilter(config);
    }

    
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(TYPE, TYPE_2);
    }

    /**
     * 設置 執(zhí)行順序
     */
    public class InnerFilter implements GatewayFilter, Ordered {

        private Config config;

        public InnerFilter(Config config){
            this.config = config;
        }

        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            //按order结借,優(yōu)先被執(zhí)行,CustomGlobalFilter執(zhí)行卒茬,apply(),then方法
            System.err.println("GatewayFilter config 自定義過濾器工廠 InnerFilter 船老,config="+this.config.toString());

            //進入下一個處理流程
//            return chain.filter(exchange);

            // 在then方法里的,相當于aop中的后置通知
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                System.out.println("  post 自定義過濾器工廠 AAAA " + this.getClass().getSimpleName());
            }));
        }

        @Override
        public int getOrder() {
            //數字越小圃酵,優(yōu)先級越高
            return -100;
        }
    }

    //自定義的config類柳畔,用來設置傳入的參數
    public static class Config{
        //Put the configuration properties for your filter here
        /**
         * 過濾類型
         */
        private String type;

        /**
         * 操作
         */
        private String type_2;

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getType_2() {
            return type_2;
        }

        public void setType_2(String type_2) {
            this.type_2 = type_2;
        }

        @Override
        public String toString() {
            return "Config{" +
                    "type='" + type + '\'' +
                    ", type_2='" + type_2 + '\'' +
                    '}';
        }
    }

}

application配置

server:
  port: 8090

spring:
  application:
    name: spring-cloud-gateway
  cloud:
    gateway:
      # 路由 id
      routes:
        - id: study
          # 注冊服務的名: lb://
          uri: lb://server-demo
          predicates:  #斷言
            - Path=/index/**
#           - Query=paramA
           # - Before=2020-04-20T06:06:06+08:00[Asia/Shanghai]
          filters:
            - name: Test
              args:
                type: root
                type_2: 1112233333



          # 自定義 filters
      discovery:
        locator:
          enabled: true
      enabled: true
      httpclient:
        ssl:
          handshake-timeout: 10000
          close-notify-flush-timeout: 3000
          close-notify-read-timeout: 0
          use-insecure-trust-manager: true

# eureka
eureka:
  client:
    enabled: true
    service-url: # http://localhost:8761/eureka/
      defaultZone: http://localhost:8761/eureka/
    register-with-eureka: true
    fetch-registry: true

#
logging:
  level:
    #  root: debug
   org.springframework.cloud: debug

執(zhí)行順序


image.png
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市郭赐,隨后出現(xiàn)的幾起案子薪韩,更是在濱河造成了極大的恐慌,老刑警劉巖捌锭,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俘陷,死亡現(xiàn)場離奇詭異,居然都是意外死亡观谦,警方通過查閱死者的電腦和手機拉盾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坎匿,“玉大人盾剩,你說我怎么就攤上這事√媸撸” “怎么了告私?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長承桥。 經常有香客問我驻粟,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任蜀撑,我火速辦了婚禮挤巡,結果婚禮上,老公的妹妹穿的比我還像新娘酷麦。我一直安慰自己矿卑,他們只是感情好,可當我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布沃饶。 她就那樣靜靜地躺著母廷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪糊肤。 梳的紋絲不亂的頭發(fā)上琴昆,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天,我揣著相機與錄音馆揉,去河邊找鬼业舍。 笑死,一個胖子當著我的面吹牛升酣,可吹牛的內容都是我干的舷暮。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼拗踢,長吁一口氣:“原來是場噩夢啊……” “哼脚牍!你這毒婦竟也來了?” 一聲冷哼從身側響起巢墅,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤诸狭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后君纫,有當地人在樹林里發(fā)現(xiàn)了一具尸體驯遇,經...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年蓄髓,在試婚紗的時候發(fā)現(xiàn)自己被綠了叉庐。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡会喝,死狀恐怖陡叠,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情肢执,我是刑警寧澤枉阵,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站预茄,受9級特大地震影響兴溜,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧呼巷,春花似錦、人聲如沸想诅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽侧蘸。三九已至,卻和暖如春鹉梨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背穿稳。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工存皂, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人逢艘。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓旦袋,卻偏偏與公主長得像,于是被迫代替她去往敵國和親它改。 傳聞我的和親對象是個殘疾皇子疤孕,可洞房花燭夜當晚...
    茶點故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內容