天天看點

Spring Cloud Alibaba:Gateway網關之Weight路由斷言工廠

之前已經介紹了​

​Gateway​

​​的十種路由斷言工廠,因為部落客之前看的官方文檔是舊版本(相較于部落客使用的架構版本​

​2.2.6.RELEASE​

​),該文檔隻介紹了十種路由斷言工廠。

  • ​​Spring Cloud Alibaba:Gateway網關 & 路由斷言工廠​​

部落客重新看了​

​2.2.9.RELEASE​

​​版本的官方文檔,新增了​

​Weight​

​​路由斷言工廠,更新還是很快的,想閱讀官方文檔可以如下圖所示擷取相關版本的​

​Gateway​

​文檔。

Spring Cloud Alibaba:Gateway網關之Weight路由斷言工廠

接下來部落客給大家示範一下它的使用方式,基于配置檔案和基于​

​Java DSL​

​​這兩種方式,然後使用​

​Postman​

​對網關進行批量請求,看效果是否符合預期。

搭建工程

一個父​

​module​

​​和兩個子​

​module​

​​(​

​server module​

​​提供服務,​

​gateway module​

​實作網關)。

父​

​module​

​​的​

​pom.xml​

​:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.kaven</groupId>
    <artifactId>alibaba</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>

    <description>Spring Cloud Alibaba</description>
    <modules>
        <module>gateway</module>
        <module>server</module>
    </modules>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <spring-cloud-version>Hoxton.SR9</spring-cloud-version>
        <spring-cloud-alibaba-version>2.2.6.RELEASE</spring-cloud-alibaba-version>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
    </parent>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud-version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba-version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>      

server module

​pom.xml​

​:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>com.kaven</groupId>
        <artifactId>alibaba</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>server</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>      

​application.yml​

​:

server:
  port: 8085      

接口定義:

package com.kaven.alibaba.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.atomic.AtomicInteger;

@RestController
public class MessageController {

    private static final AtomicInteger MESSAGE_COUNT = new AtomicInteger(0);
    private static final AtomicInteger NEW_MESSAGE_COUNT = new AtomicInteger(0);


    @GetMapping("/message")
    public Integer getMessage() {
        int count = MESSAGE_COUNT.incrementAndGet();
        System.out.println("message: " + count);
        return count;
    }

    @GetMapping("/new/message")
    public Integer getMessageNew() {
        int count = NEW_MESSAGE_COUNT.incrementAndGet();
        System.out.println("new message: " + count);
        return count;
    }
}      

啟動類:

package com.kaven.alibaba;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
}      

gateway module

​pom.xml​

​:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>com.kaven</groupId>
        <artifactId>alibaba</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>gateway</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

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

啟動類:

package com.kaven.alibaba;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
}      

基于配置檔案

​gateway module​

​​的​

​application.yml​

​:

server:
  port: 8086

spring:
  cloud:
    gateway:
      routes:
        - id: server
          uri: http://localhost:8085
          predicates:
            - Path=/message
            - Weight=group1, 75
        - id: new_server
          uri: http://localhost:8085
          predicates:
            - Path=/message
            - Weight=group1, 25
          filters:
            - PrefixPath=/new      

​Weight​

​​路由斷言工廠接受兩個參數:​

​group​

​​和​

​weight​

​​(​

​int​

​​類型),權重是按組計算的(​

​group​

​​參數需要相同)。如果請求網關的​

​/message​

​​路徑,會有​

​75%​

​​的機率被路由到​

​http://localhost:8085/message​

​​,​

​25%​

​​的機率被路由到​

​http://localhost:8085/new/message​

​​(​

​PrefixPath​

​​是一種路由過濾器,它會将指定的路徑以字首的形式加在請求路徑上,是以請求​

​/message​

​​路徑,會被路由到​

​/new/message​

​路徑)。

  • ​​Spring Cloud Alibaba:Gateway之路由過濾器工廠(一)​​

可見,這種配置可用于有新版本的服務,但不确定新版本服務是否存在問題,就可以将小部分流量導入新版本服務中,進行線上測試,用較小的代價試錯,即使出現了嚴重的錯誤,系統總體的損失也是可承受的,大家可以去了解一下金絲雀釋出。

啟動兩個應用,使用​

​Postman​

​對網關發送批量請求,可以根據如下圖所示進行操作。

Spring Cloud Alibaba:Gateway網關之Weight路由斷言工廠

運作​

​Collection​

​。

Spring Cloud Alibaba:Gateway網關之Weight路由斷言工廠

輸入運作​

​Collection​

​的配置(請求次數與請求間歇)。

Spring Cloud Alibaba:Gateway網關之Weight路由斷言工廠

服務端的輸出如下圖所示:

Spring Cloud Alibaba:Gateway網關之Weight路由斷言工廠

服務端的兩個接口分别被請求了​

​757​

​​次和​

​243​

​次,還是符合預期的。

基于Java DSL

修改​

​gateway module​

​​的​

​application.yml​

​(删除網關的路由配置):

server:
  port: 8086      

在​

​gateway module​

​​中增加兩個​

​bean​

​​,即以​

​Java DSL​

​的形式定義兩個路由的處理流程。

@Bean
    public RouteLocator routes1(RouteLocatorBuilder builder) {
        String uri = "http://127.0.0.1:8085";
        return builder.routes()
                .route("server", r -> r.path("/message")
                        .and().weight("group1", 75)
                        .uri(uri))
                .build();
    }

    @Bean
    public RouteLocator routes2(RouteLocatorBuilder builder) {
        String uri = "http://127.0.0.1:8085";
        return builder.routes()
                .route("new_server", r -> r.path("/message")
                        .and().weight("group1", 25)
                        .filters(f -> f.prefixPath("/new"))
                        .uri(uri))
                .build();
    }      

上面代碼的配置和之前的配置檔案是一樣的,重新啟動兩個應用,再用​

​Postman​

​給網關發送批量請求。

Spring Cloud Alibaba:Gateway網關之Weight路由斷言工廠