欢送拜访我的 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> 是如何实现的
你不孤独,欣宸原创一路相伴
- Java 系列
- Spring 系列
- Docker 系列
- kubernetes 系列
- 数据库 + 中间件系列
- DevOps 系列
欢送关注公众号:程序员欣宸
微信搜寻「程序员欣宸」,我是欣宸,期待与您一起畅游 Java 世界 …
https://github.com/zq2599/blog_demos