學習SpringCloud之服務網關Gateway

簡介

  • SpringCloudGatewaySpringCloudZuul一樣是微服務網關,不過Gateway是SpringCloud官方推出的,而Zuul是Netflix推出的。
    看其他人的一些文章說是Gateway是用於取代Zuul的第二代網關,這個我在官方找不到資料說明。

  • 主要術語

    • Route: 路由。
    • Predicate: 斷言,即匹配規則。
    • Filter: 過濾器,用於修改請求。

Route: Route the basic building block of the gateway. It is defined by an ID, a destination URI, a collection of predicates and a collection of filters. A route is matched if aggregate predicate is true.

Predicate: This is a Java 8 Function Predicate. The input type is a Spring Framework ServerWebExchange. This allows developers to match on anything from the HTTP request, such as headers or parameters.

Filter: These are instances Spring Framework GatewayFilter constructed in with a specific factory. Here, requests and responses can be modified before or after sending the downstream request.

  • 功能實現流程
    image

以下示例均基於SpringCloud的Greenwich.SR1版本,且需要依賴到之前介紹SpringCloud相關的文章

基礎依賴

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <artifactId>*</artifactId>
                <groupId>*</groupId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

這裏有一點要說明一下,因爲父模塊中有spring-boot-starter-web的依賴,而SpringCloudGateway還不支持spring-boot-starter-web,所以需要先把依賴排除。
否則啓動會出現以下錯誤:

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of method modifyRequestBodyGatewayFilterFactory in org.springframework.cloud.gateway.config.GatewayAutoConfiguration required a bean of type 'org.springframework.http.codec.ServerCodecConfigurer' that could not be found.


Action:

Consider defining a bean of type 'org.springframework.http.codec.ServerCodecConfigurer' in your configuration.

GatewayServer

啓動Gateway很簡單,只需要一個啓動簡單的SpringBoot應用就可以。

@SpringBootApplication
class GatewayServerStarter

fun main(args: Array<String>) {
    runApplication<GatewayServerStarter>(*args)
}

配置Gateway可以使用application.yml來配置,也可以從代碼層面去配置。

如果是用配置文件的方式去配置的話,即用一下的方式去配置路由。

server:
  port: 6609

spring:
  application:
    name: gateway-server

  cloud:
    gateway:
      routes:
        - id: # 路由的標識
        - uri: # 轉發的地址
        - predicates: # 指定斷句
        - filters: # 指定過濾器

用過是代碼的方式,則以新建一個RouteLocator的Bean來實現。

@Configuration
class GatewayConfiguration {

    @Bean
    fun routes(builder: RouteLocatorBuilder): RouteLocator {
        return builder.routes()
            .route {
                it.predicate { p -> p.request.queryParams["name"]?.get(0) == "czb1n" }
                    .filters { f -> f.addRequestHeader("Name", "czb1n") }
                    .uri("http://httpbin.org:80")
            }
            .route {
                it.path("/get")
                    .uri("http://httpbin.org:80")
            }
            .build()
    }

}

啓動之後,訪問http://localhost:6609/get就會根據第二條轉發規則,轉發至http://httpbin.org:80,頁面會顯示以下結果。

{
  "args": {}, 
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", 
    "Accept-Encoding": "gzip, deflate, br", 
    "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8", 
    "Cache-Control": "max-age=0", 
    "Cookie": "Hm_lvt_a14b0dbc71bff63c2370f65118b12426=1552964642,1553068348,1553132391,1554186102; Hm_lpvt_a14b0dbc71bff63c2370f65118b12426=1554278774", 
    "Forwarded": "proto=http;host=\"localhost:6609\";for=\"0:0:0:0:0:0:0:1:53856\"", 
    "Host": "httpbin.org", 
    "Upgrade-Insecure-Requests": "1", 
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36", 
    "X-Forwarded-Host": "localhost:6609"
  }, 
  "origin": "0:0:0:0:0:0:0:1, ::1", 
  "url": "https://localhost:6609/get"
}

訪問http://localhost:6609/get?name=czb1n會匹配第一條規則,也會轉發至http://httpbin.org:80,但是不會匹配到第二條規則。
原因是因爲規則是從上往下匹配的,只會匹配到符合的第一條規則。
頁面會顯示結果。

{
  "args": {
    "name": "czb1n"
  }, 
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", 
    "Accept-Encoding": "gzip, deflate, br", 
    "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8", 
    "Cookie": "Hm_lvt_a14b0dbc71bff63c2370f65118b12426=1552964642,1553068348,1553132391,1554186102; Hm_lpvt_a14b0dbc71bff63c2370f65118b12426=1554278774", 
    "Forwarded": "proto=http;host=\"localhost:6609\";for=\"0:0:0:0:0:0:0:1:53856\"", 
    "Host": "httpbin.org", 
    "Name": "czb1n", 
    "Purpose": "prefetch", 
    "Upgrade-Insecure-Requests": "1", 
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36", 
    "X-Forwarded-Host": "localhost:6609"
  }, 
  "origin": "0:0:0:0:0:0:0:1, ::1", 
  "url": "https://localhost:6609/get?name=czb1n"
}

Filter會在轉發請求的headers上添加上"Name": "czb1n"

其他

示例代碼地址: https://github.com/czb1n/learn-spring-cloud-with-kotlin

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章