Spring Cloud Gateway使用簡介


Spring Cloud Gateway是類似Nginx的網關路由代理,有替代原來Spring cloud zuul之意:

Spring 5 推出了自己的Spring Cloud Gateway,支持Java 8、Reactor API,可在Spring Boot 2 使用,看到了響應式組件Reactor,可以理解這個網關方案目標之一是能夠采用Reactive 來實現高效率的網關。

想要建立一個Spring Cloud Gateway 的話,在Spring Tool Suite 上可以選擇「Gateway」這個Starter,為了能注冊到服務發現服務器,也為了能開放gateway/routes 端點,以便觀察路由信息,就順便加入Eureka與Actuator 的Starter,比如在build.gradle 中可以包含:

  

implementation('org.springframework.boot:spring-boot-starter-actuator')  
implementation('org.springframework.cloud:spring-cloud-starter-gateway')
implementation('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')

 

Spring Cloud Gateway 可以在注冊服務器上注冊的服務ID,自動建立路由信息,為此,可以如下設定bootstrap.properties:

  

server.port=5555

spring.cloud.gateway.discovery.locator.enabled=true
spring.cloud.gateway.discovery.locator.lowerCaseServiceId=true

eureka.instance.preferIpAddress=true
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/

management.endpoints.web.exposure.include: gateway

 

spring.cloud.gateway.discovery.locator.enabled啟用了自動根據服務ID建立路由,路由的路徑對應會使用大寫ID,若想要使用小寫ID,可將spring.cloud.gateway.discovery.locator.lowerCaseServiceId設為true;在設置中也開放了gateway端點。必要時,可以使用RouteLocator實現自定義路由的方式。

 

接下來啟動相關服務,啟動Spring Cloud Gateway,默認會跑在Netty上,如果測試請求http://localhost:5555/actuator/gateway/routes的話,就可以看到以下:

 

 

[
    {
        "route_id": "CompositeDiscoveryClient_ACCTSVI",
        "route_definition": {
            "id": "CompositeDiscoveryClient_ACCTSVI",
            "predicates": [
                {
                    "name": "Path",
                    "args": {
                        "pattern": "/acctsvi/**"
                    }
                }
            ],
            "filters": [
                {
                    "name": "RewritePath",
                    "args": {
                        "regexp": "/acctsvi/(?<remaining>.*)",
                        "replacement": "/${remaining}"
                    }
                }
            ],
            "uri": "lb://ACCTSVI",
            "order": 0
        },
        "order": 0
    },
    ...
]

 

每個路由設定會有個route_id作為識別,在路由定義的predicates中,可以看到設置了Path,這是Spring Cloud Gateway內建的斷言器工廠Bean名稱,pattern這個設置表示對於http://localhost:5555/acctsvi/xxxx的請求會轉給uri設定的值:lb://ACCTSVI,也就是說路由轉給了服務ID為ACCTSVI的服務。

 

filters中設置了RewritePath,這是個過濾器工廠Bean名稱,依照regexp的規則,會捕捉請求中的/acctsvi/之后的部份,套用至服務的URI上,也就是http://localhost:5555/acctsvi/xxxx的請求,將會路由轉發至http://acctsvi-uri/xxxx。

 

predicates與filters是Spring Cloud Gateway的重要特性,predicates斷言哪些路徑符合路由定義,filters設置具體哪些路徑適用什么樣的具體過濾器,除了設置之外,必要時,都可以代碼自己定義。

 

Spring Cloud Gateway也內建了一些斷言器工廠過濾器工廠,這些工廠類別,是可以通過屬性檔來定義的,必要時,也可以自定義工廠類別

 

就以上的設置來說,請求http://localhost:5555/acctsvi/accountByName?username=caterpillar就可以得到以下回應:

 

 

{
    "name": "caterpillar",
    "email": "caterpillar@openhome.cc",
    "password": "$2a$10$CEkPOmd.Uid2FpIOHA6Cme1G.mvhWfelv2hPu7cxZ/vq2drnXaVo.",
    "_links": {
        "self": {
            "href": "http://Justin-2017:8084/accountByNameEmail?username=caterpillar"
        }
    }
}

如果想要自定義路由,可以寫個application.yml(若不想自動建立路由,可以將spring.cloud.gateway.discovery.locator.enabled與spring.cloud.gateway.discovery.locator.lowerCaseServiceId注解掉):

 

 

spring:
    application:
            name: gateway
    cloud:
        gateway:
            routes: 
                - predicates:
                    - Path=/acct/**                   filters:                       - StripPrefix=1                   uri: lb://acctsvi                 - predicates:                     - Path=/msg/**                   filters:                       - StripPrefix=1                   uri: lb://msgsvi                      - predicates:                     - Path=/email/**                   filters:                       - StripPrefix=1                   uri: lb://email          

 

上述配置filters中的StripPrefix也是內建的過濾器工廠Bean名稱,設定值為1表示將路由中的第一個層去除,其余保留用來轉發請求,請求http://localhost:5555/actuator/gateway/routes的話,就可以看到以下:

 

 

[
    {
        "route_id": "545d278b-192b-4370-8156-161815957f91",
        "route_definition": {
            "id": "545d278b-192b-4370-8156-161815957f91",
            "predicates": [
                {
                    "name": "Path",
                    "args": {
                        "_genkey_0": "/acct/**"
                    }
                }
            ],
            "filters": [
                {
                    "name": "StripPrefix",
                    "args": {
                        "_genkey_0": "1"
                    }
                }
            ],
            "uri": "lb://acctsvi",
            "order": 0
        },
        "order": 0
    },
    ...
]

 

也就是對http://localhost:5555/acct/accountByName?username=caterpillar的請求,會轉給http://acctsvi-url/accountByName?username=caterpillar。

 

如果想要設定api前置路徑,就是修改一下StripPrefix=1為StripPrefix=2:

 

 

spring:
    application:
            name: gateway
    cloud:
        gateway:
            default-filters:
                - StripPrefix=2
            routes: 
                - predicates:
                    - Path=/api/acct/**
                  uri: lb://acctsvi
                - predicates:
                    - Path=/api/msg/**
                  uri: lb://msgsvi     
                - predicates:
                    - Path=/api/email/**
                  uri: lb://email               

 

對於每個路由都要套用的過濾器,可以使用default-filters來設置,就以上設定來說,可以請求http://localhost:5555/api/acct/accountByName?username=caterpillar來取得使用者信息。

一開始自動根據服務ID建立路由時,可以看到RewritePath,它也是內建的過濾器工廠,可以運用規則表示式來進行路徑重寫,因此,也可以這么設置api前置:

 

 

spring:
    application:
            name: gateway
    cloud:
        gateway:
            default-filters:
                - RewritePath=/api/.*?/(?<remaining>.*), /$\{remaining}
            routes: 
                - predicates:
                    - Path=/api/acct/**
                  uri: lb://acctsvi
                - predicates:
                    - Path=/api/msg/**
                  uri: lb://msgsvi     
                - predicates:
                    - Path=/api/email/**
                  uri: lb://email            

 

就目前的設定來說,在客戶端的部份,〈使用Zuul〉中的gossip就可以了,畢竟交互的接口沒有改變,但是因為使用spring.application.gateway作為應用代理了,還是要記得改一下@FeignClient中的服務ID為gateway。

可以在首頁qq群加群獲取代碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM