Gateway使用入門

一、什么是Gateway

如果沒有網(wǎng)關(guān),我們在開發(fā)和治理微服務(wù)架構(gòu)的系統(tǒng)時(shí),為了完成一個(gè)業(yè)務(wù)邏輯的功能,不得不自己調(diào)用多個(gè)服務(wù)的主機(jī)和端口,會(huì)顯得繁雜,容易出錯(cuò)。因此微服務(wù)網(wǎng)關(guān)項(xiàng)目應(yīng)運(yùn)而生。

網(wǎng)關(guān)為微服務(wù)架構(gòu)的系統(tǒng)提供簡單、有效且統(tǒng)一的API路由管理,主要功能包含協(xié)議適配、協(xié)議轉(zhuǎn)發(fā)、安全策略、防刷、流量控制、監(jiān)控日志等。

二、入門案例

start.sprinig.io上一鍵下載包含了Gateway組件的項(xiàng)目即可。

一鍵生成gateway項(xiàng)目

然后在啟動(dòng)類上配置路由信息:

@SpringBootApplication
public class GatewayDemoApplication {

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

    // 配置路由信息
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
        return builder.routes()
                .route("blog_route",r -> r.path("/zhangxun")
                        .uri("https://blog.csdn.net"))
                .route("search_route", r -> r.path("/jansen")
                        .uri("https://www.zhihu.com/"))
                .build();
    }
}

以上配置路由信息主要定義了如下三個(gè)要素:

  • 路由ID,此處就是blog_route,可以自定義;
  • 路由斷言,此處就是/zhangxun,凡是符合這個(gè)路由斷言的訪問路徑都會(huì)被通過;
  • 路由目標(biāo),此時(shí)就是https://blog.csdn.net

當(dāng)我們訪問Gateway項(xiàng)目時(shí),如果訪問路徑上包含"/zhangxun",網(wǎng)關(guān)就會(huì)將請求轉(zhuǎn)發(fā)到"https://blog.csdn.net"上,我們啟動(dòng)如上的項(xiàng)目,然后訪問“http://localhost:8080/zhangxun”就會(huì)看到,最終訪問到的是CSDN的網(wǎng)址。

在實(shí)際開發(fā)中,一般都會(huì)采用配置文件的方式,而不是如上代碼配置的方式。因?yàn)榕渲梦募?nèi)容可以托管到統(tǒng)一配置中心,給與服務(wù)治理更大的靈活性。如下是等價(jià)的配置文件形式:

spring:
  application:
    name: gateway-demo-service
  cloud:
    gateway:
      routes:
        - id: blog_route
          # uri: lb://注冊中心的服務(wù)名稱
          uri: https://blog.csdn.net
          predicates:
            - Path=/zhangxun
        - id: search_route
          # uri: lb://注冊中心的服務(wù)名稱
          uri: https://www.zhihu.com/
          predicates:
            - Path=/jansen

三、路由斷言

Gateway包含了很多的路由斷言工廠,當(dāng)請求達(dá)到Gateway的時(shí)候,配置好的的路由斷言工廠就會(huì)根據(jù)配置的路由規(guī)則,對請求進(jìn)行斷言匹配,只有匹配成功才會(huì)進(jìn)入到下一步的處理中,否則斷言失敗就會(huì)直接返回錯(cuò)誤信息。

如下是Gateway支持的一些斷言工廠,分別在不同的場景下可以配置使用:

gateway路由斷言工廠

3.1 Datetime

假設(shè)我們設(shè)定一個(gè)標(biāo)準(zhǔn)時(shí)間,這個(gè)標(biāo)準(zhǔn)時(shí)間是某熱銷產(chǎn)品的開賣時(shí)間,只有當(dāng)達(dá)到這個(gè)開賣時(shí)間時(shí),用戶購買請求才可以被轉(zhuǎn)發(fā)到購買的服務(wù)上。此時(shí)我們就需要用到Datetime分類中的AfterRoutePredicateFactory。

    @Bean
    public RouteLocator customerRouteLocator(RouteLocatorBuilder builder){
        // 設(shè)置一小時(shí)前的時(shí)間為標(biāo)準(zhǔn)時(shí)間
        ZonedDateTime standardTime = LocalDateTime.now().minusHours(1).atZone(ZoneId.systemDefault());
        return builder.routes()
                .route("after_route", r -> r.after(standardTime)
                        .uri("https://www.zhihu.com/"))
                .build();
    }

假設(shè)我們的熱銷產(chǎn)品有一個(gè)截止買賣時(shí)間,超過這個(gè)時(shí)間就不能再購買,那么可以使用Datetime分類的BeforeRoutePredicateFactory。

    @Bean
    public RouteLocator customerRouteLocator(RouteLocatorBuilder builder){
        // 設(shè)置一小時(shí)后的時(shí)間為標(biāo)準(zhǔn)時(shí)間
        ZonedDateTime standardTime = LocalDateTime.now().plusHours(1).atZone(ZoneId.systemDefault());
        return builder.routes()
                .route("after_route", r -> r.before(standardTime)
                        .uri("https://www.zhihu.com/"))
                .build();
    }

同樣的,我們還可以設(shè)置一個(gè)時(shí)間段,在這個(gè)時(shí)間段內(nèi)的請求才是合法的,使用Datetime分類的BetweenRoutePredicateFactory。

    @Bean
    public RouteLocator customerRouteLocator(RouteLocatorBuilder builder){
        // 設(shè)置一小時(shí)前的時(shí)間為開始時(shí)間
        ZonedDateTime startTime = LocalDateTime.now().minusHours(1).atZone(ZoneId.systemDefault());
        // 設(shè)置一小時(shí)后的時(shí)間為截止時(shí)間
        ZonedDateTime endTime = LocalDateTime.now().plusHours(1).atZone(ZoneId.systemDefault());
        return builder.routes()
                .route("after_route", r -> r.between(startTime, endTime)
                        .uri("https://www.zhihu.com/"))
                .build();
    }

3.2 Cookie

我們還可以設(shè)定對請求的cookie內(nèi)容進(jìn)行斷言:

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("cookie_route", r -> r.cookie("name", "zhangsan")
                        .uri("https://www.zhihu.com/"))
                .build();
    }

在測試的時(shí)候,我們使用postman進(jìn)行,首先輸入期望的cookie內(nèi)容進(jìn)行測試:

CookiePredicate

然后輸入非期望的cookie內(nèi)容進(jìn)行測試:

CookiePredicate2

3.3 Weight

基于路由權(quán)重的斷言,指定路由分組和權(quán)重值即可使用:

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("weight_route_1", r -> r.weight("w1", 5)
                        .uri("https://www.zhihu.com/"))
                .route("weight_route_2", r -> r.weight("w1", 95)
                        .uri("https://blog.csdn.net"))
                .build();
    }

這里配置了兩個(gè)路由,它們屬于同一個(gè)路由分組w1,但是知乎網(wǎng)站的轉(zhuǎn)發(fā)權(quán)重為5%,csdn網(wǎng)站的轉(zhuǎn)發(fā)權(quán)重為95%,那么我們的請求將有95%概率會(huì)被轉(zhuǎn)發(fā)到csdn去。

3.4 Header

Header中的某個(gè)屬性值必須符合預(yù)期才會(huì)通過;

3.5 Host

請求來源域名必須是預(yù)期的才會(huì)通過;

3.6 Method

請求的方法必須是預(yù)期的才會(huì)通過;

3.7 Path

已經(jīng)在第二節(jié)入門案例中演示過,符合預(yù)期路徑才會(huì)通過;

3.8 Query

對請求路徑中的參數(shù)內(nèi)容進(jìn)行斷言;

3.9 RemoteAddr

基本同Host,只不過此時(shí)應(yīng)該寫IP地址或者網(wǎng)段;

四、內(nèi)置Filter

過濾器的作用就是可以按照應(yīng)用場景修改請求和返回的內(nèi)容,總的來說,F(xiàn)ilter可以分為如下七類,但是不限于以下這些Filter:

gateway過濾器工廠

4.1 Header

對于匹配上的請求加上header內(nèi)容:

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("add_request_header_route", r -> r.path("/zhangxun")
                        .filters(f -> f.addRequestHeader("name", "zhangsan"))
                        .uri("https://www.zhihu.com/"))
                .build();
    }

4.2 Parameter

會(huì)在請求地址后面增加上請求參數(shù):

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("add_request_parameter_route", r -> r.path("/zhangxun")
                        .filters(f -> f.addRequestParameter("name", "zhangsan"))
                        .uri("https://www.zhihu.com/"))
                .build();
    }

4.3 Path

StripPrefixGatewayFitlerFactory是用于去除請求前綴,而PrefixPathGatewayFilterFactory是用于增加請求前綴。

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("path_route", r -> r.path("/zhangxun/jansen")
                        .filters(f -> f.stripPrefix(2))
                        .uri("https://www.zhihu.com/"))
                .build();
    }

如上前綴過濾器在我們訪問http://localhost:8080/zhangxun/jansen的時(shí)候,會(huì)把路徑前綴的前兩個(gè)去掉再進(jìn)行轉(zhuǎn)發(fā)https://www.zhihu.com/。

4.4 Status

4.5 Redirect

4.6 Hystrix

4.7 RateLimeter

部分實(shí)例暫未涉及,后續(xù)再補(bǔ)充。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容