乐趣区

关于云计算:Spring-Cloud-Gateway实战之二更多路由配置方式

欢送拜访我的 GitHub

https://github.com/zq2599/blog_demos

内容:所有原创文章分类汇总及配套源码,波及 Java、Docker、Kubernetes、DevOPS 等;

本篇概览

  • 本文是《Spring Cloud Gateway 实战》系列的第二篇,通过前文咱们理解到 Spring Cloud Gateway 的外围是路由配置,而后在本地 application.yml 中配置了一条路由,但这种批改本地配置文件的形式不足灵活性,未必能满足灵便多变的业务需要,因而,本篇的目标就是找出本地配置之外的其余配置形式来,满足各种理论需要;
  • 总的来说以下三种形式都是罕用的:
  • 指标地址反对用服务名(取代之前的 IP+ 端口);
  • 反对在 nacos 上配置;
  • 反对写代码的形式配置;
  • 另外还有一种更加灵便的配置形式:<font color=”blue”> 动静代理 </font>,因为波及到不少的代码所以会独自出一篇文章具体介绍

源码下载

  • 本篇实战中的残缺源码可在 GitHub 下载到,地址和链接信息如下表所示 (https://github.com/zq2599/blo…):
名称 链接 备注
我的项目主页 https://github.com/zq2599/blo… 该我的项目在 GitHub 上的主页
git 仓库地址 (https) https://github.com/zq2599/blo… 该我的项目源码的仓库地址,https 协定
git 仓库地址 (ssh) git@github.com:zq2599/blog_demos.git 该我的项目源码的仓库地址,ssh 协定
  • 这个 git 我的项目中有多个文件夹,本篇的源码在 <font color=”blue”>spring-cloud-tutorials</font> 文件夹下,如下图红框所示:

筹备工作

  • 正式开始前须要再做一点筹备工作,整个《Spring Cloud Gateway 实战》系列中,所有申请最初都会被路由到 <font color=”blue”>provider-hello</font> 这个 web 下来,该服务目前只有一个 web 接口 <font color=”blue”>/hello/str</font>,当初咱们再给它减少一个,前面的实战会用到
  • 新减少的 web 接口来自 LBTest.java,可见非常简单:
package com.bolingcavalry.provider.controller;

import com.bolingcavalry.common.Constants;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.text.SimpleDateFormat;
import java.util.Date;

@RestController
@RequestMapping("/lbtest")
public class LBTest {private String dateStr(){return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date());
    }

    /**
     * 返回字符串类型
     * @return
     */
    @GetMapping("/str")
    public String helloStr() {return Constants.LB_PREFIX + "," + dateStr();
    }
}
  • 上述代码中的 <font color=”blue”>Constants.LB_PREFIX</font> 来自子工程 <font color=”red”>common</font>:
package com.bolingcavalry.common;

public interface Constants {
    String HELLO_PREFIX = "Hello World";
    String LB_PREFIX = "Load balance";
}
  • 写完代码后,先确保 nacos 曾经启动
  • 在启动 <font color=”blue”>provider-hello</font> 工程,启动胜利后去看 nacos,确认曾经注册:

  • 筹备结束,能够开始实战了

指标地址反对用服务名(取代之前的 IP+ 端口)

  • 咱们从最简略的开始,先看前文的路由配置,如下图红框,指标地址是 IP+ 端口:

  • 玩过 Spring Cloud 的您天然看出了问题所在:没有注册发现,的确,这样将地址和端口写死在配置文件中是不适合的,咱们先来解决这个问题;
  • 新增名为 <font color=”blue”>gateway-by-loadbalance</font> 的子工程,其 pom.xml 中的依赖状况如下,可见重点是 <font color=”red”>spring-cloud-starter-loadbalancer</font>:
<dependencies>
        <dependency>
            <groupId>com.bolingcavalry</groupId>
            <artifactId>common</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 路由策略应用 lb 的形式是,这个依赖肯定要有 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
        <!--nacos: 注册核心 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>
  • 启动类的代码省去了 (和前文的一样)
  • 配置信息如下,重点是 uri 的值 <font color=”red”>lb://provider-hello</font>,用了前缀 <font color=”blue”>lb:</font>,前面的 <font color=”blue”>provider-hello</font> 就是在 nacos 注册的服务名:
server:
  #服务端口
  port: 8085
spring:
  application:
    name: gateway-by-loadbalance
  cloud:
    nacos:
      # 注册核心的配置
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      routes:
        - id: path_route_lb
          uri: lb://provider-hello
          predicates:
          - Path=/lbtest/**
  • 单元测试类:
package com.bolingcavalry.gateway;

import com.bolingcavalry.common.Constants;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.reactive.server.WebTestClient;
import static org.junit.jupiter.api.Assertions.assertTrue;

@SpringBootTest
@ExtendWith(SpringExtension.class)
@AutoConfigureWebTestClient
public class HelloTest {

    @Autowired
    private WebTestClient webClient;

    @Test
    void testLoadBalance() {webClient.get()
                .uri("/lbtest/str")
                .accept(MediaType.APPLICATION_JSON)
                .exchange()
                // 验证状态
                .expectStatus().isOk()
                // 验证后果,留神后果是字符串格局
                .expectBody(String.class).consumeWith(result  -> assertTrue(result.getResponseBody().contains(Constants.LB_PREFIX)));
    }
}
  • 运行单元测试,通过,可见上述配置能够通过前缀 <font color=”blue”>lb:</font> 精确找到服务:

反对在 nacos 上配置

  • 将所有配置信息写在 application.yml 中有个问题:不能近程配置,这在利用数量较多的场景就不不便了,好在 nacos 提供了近程配置的能力,利用启动后能够从 nacos 获得本人的配置信息,咱们来试试
  • 新增名为 <font color=”blue”>gateway-nacos-config</font> 的子工程,其 pom.xml 中的依赖状况如下,请留神外面的中文正文,每指明了每一个依赖的作用:
<dependencies>
        <dependency>
            <groupId>com.bolingcavalry</groupId>
            <artifactId>common</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 应用 bootstrap.yml 的时候,这个依赖肯定要有 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
        <!-- 路由策略应用 lb 的形式是,这个依赖肯定要有 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
        <!--nacos: 配置核心 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!--nacos: 注册核心 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>
  • 本地的配置文件 <font color=”blue”>bootstrap.yml</font>,非常简单,就是 nacos 的地址和近程配置信息:
spring:
  application:
    name: gateway-nacos-config
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yml
        group: DEFAULT_GROUP
  • 接下来再 nacos 减少一个配置文件,操作如下图红框:

  • 减少一个配置,要留神的中央如下(配置信息的文本稍后给出,便于复制):

  • 上图中残缺的配置信息如下:
server:
  port: 8083
spring:
  cloud:
    gateway:
      routes:
        - id: path_route_addr
          uri: http://127.0.0.1:8082
          predicates:
          - Path=/hello/**
        - id: path_route_lb
          uri: lb://provider-hello
          predicates:
          - Path=/lbtest/**
  • 测试类中的两个测试方法如下所示,和后面没有任何区别:
@Test
    void testHelloPredicates() {webClient.get()
                .uri("/hello/str")
                .accept(MediaType.APPLICATION_JSON)
                .exchange()
                // 验证状态
                .expectStatus().isOk()
                // 验证后果,留神后果是字符串格局
                .expectBody(String.class).consumeWith(result  -> assertTrue(result.getResponseBody().contains(Constants.HELLO_PREFIX)));
    }

    @Test
    void testLoadBalance() {webClient.get()
                .uri("/lbtest/str")
                .accept(MediaType.APPLICATION_JSON)
                .exchange()
                // 验证状态
                .expectStatus().isOk()
                // 验证后果,留神后果是字符串格局
                .expectBody(String.class).consumeWith(result  -> assertTrue(result.getResponseBody().contains(Constants.LB_PREFIX)));
    }
  • 运行单元测试类,测试通过,证实从 nacos 获取配置文件胜利:

写代码的形式配置

  • 后面的几个例子,路由信息都是写在配置文件中的,其实还有一种形式:写代码配置路由,能本人写代码来配置,这灵活性就更强了
  • 新增名为 <font color=”blue”>gateway-by-code</font> 的子工程,其 pom.xml 文件参照后面工程的即可
  • 接下来的本例的重点,在配置类中减少一个 RouteLocator 类型的 bean,通过以下代码即可减少一个路由:
package com.bolingcavalry.gateway.cofig;

import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RouteConfig {

    @Bean
    public RouteLocator customizeRoute(RouteLocatorBuilder builder) {
        return builder
                .routes()
                .route(
                            // 第一个参数是路由的惟一身份
                        "path_route_lb",
                            // 第二个参数是个 lambda 实现,// 设置了配套条件是依照申请门路匹配,以及转发地址,// 留神 lb:// 示意这是个服务名,要从
                            r -> r.path("/lbtest/**").uri("lb://provider-hello")
                )
                .build();}
}
  • 上述代码只配置了一个路由,还有一个在配置文件中,这样就能验证代码和配置文件能不能同时失效了:
server:
  #服务端口
  port: 8084
spring:
  application:
    name: gateway-by-code
  cloud:
    nacos:
      discovery:
        # nacos 服务地址
        server-addr: 127.0.0.1:8848
    gateway:
      routes:
        - id: path_route_addr
          uri: http://127.0.0.1:8082
          predicates:
          - Path=/hello/**
  • 测试类和之前工程的截然不同,就不占用篇幅了,仍旧是两个测试方法 <font color=”blue”>testHelloPredicates</font> 和 <font color=”blue”>testLoadBalance</font>
  • 执行单元测试能够顺利通过,证实代码配置路由没有问题:

  • 至此,负载平衡、nacos 配置、代码配置的实例咱们都尝试过了,它们合起来会给理论生存环境的配置带来很大的不便,心愿可能给您一些参考

缺点和解决之道

  • 上述配置形式虽多,但有一个独特的问题:每当配置变动后,Gateway 利用须要重启能力失效,这在申请不间断的生产环境是难以承受的
  • 为了让最新的路由配置能在 Gateway 利用不重启的前提下失效,接下来的文章咱们一起去摸索 <font color=”blue”> 动静路由 </font> 是如何实现的

你不孤独,欣宸原创一路相伴

  1. Java 系列
  2. Spring 系列
  3. Docker 系列
  4. kubernetes 系列
  5. 数据库 + 中间件系列
  6. DevOps 系列

欢送关注公众号:程序员欣宸

微信搜寻「程序员欣宸」,我是欣宸,期待与您一起畅游 Java 世界 …
https://github.com/zq2599/blog_demos

退出移动版