整合Spring Cloud Gateway编码实践
接下来就通过实际的编码,把微服务网关整合到项目中,顺便体验一下 Spring Cloud Gateway
的功能。
编码整合Spring Cloud Gateway
笔者将结合实际的编码来讲解如何构建一个网关服务。本节代码是在 spring-cloud-alibaba-multi-service-demo
模板项目的基础上修改的,具体步骤如下。
-
修改项目名称。
修改项目名称为
spring-cloud-alibaba-gateway-demo
,并把各个模块中pom.xml
文件的artifactId
修改为spring-cloud-alibaba-gateway-demo
。 -
新建网关模块并引入
Spring Cloud Gateway
依赖。新建一个模块,并命名为
gateway-demo
,Java
代码的包名为ltd.newbee.cloud
。在该模块的pom.xml
配置文件中增加parent
标签,与上层Maven
建立好关系。打开
gateway-demo
项目中的pom.xml
文件,在dependencies
标签下引入Spring CloudGateway
的依赖文件,新增代码如下:<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
-
增加网关配置。
打开
gateway-demo
项目中的application.properties
文件,主要配置项目端口及路由,配置项为spring.cloud.gateway.routes.*
,最终的配置文件内容如下:server.port=8127 spring.cloud.gateway.routes[0].id=goods-demo-route spring.cloud.gateway.routes[0].uri=http://localhost:8120 spring.cloud.gateway.routes[0].order=1 spring.cloud.gateway.routes[0].predicates[0]=Path=/goods/** spring.cloud.gateway.routes[1].id=shopcart-demo-route spring.cloud.gateway.routes[1].uri=http://localhost:8122 spring.cloud.gateway.routes[1].order=1 spring.cloud.gateway.routes[1].predicates[0]=Path=/shop-cart/**
这里主要配置
gateway-demo
到goods-service-demo
和shopcart-service-demo
的路由信息。如果访问网关项目的路径是以/goods
开头的,就路由到goods-service-demo
,该项目的URL
为 http://localhost:8120 ;如果访问网关项目的路径是以/shop-cart
开头的,就路由到shopcart-service-demo
,该项目的URL
为 http://localhost:8122 。另外,在
goods-service-demo
和shopcart-service-demo
中分别新增两个接口用于测试。在
NewBeeCloudGoodsAPI
类中新增如下代码:@GetMapping("/goods/page/{pageNum}") public String goodsList(@PathVariable("pageNum") int pageNum) { // 返回信息给调用端 return "请求 goodsList, 当前服务的端口号为" + applicationServerPort; }
在
NewBeeCloudShopCartAPI
类中新增如下代码:@GetMapping("/shop-cart/page/{pageNum}") public String cartItemList(@PathVariable("pageNum") int pageNum) throws InterruptedException { // 返回信息给调用端 return "请求 cartItemList, 当前服务的端口号为" + applicationServerPort; }
依次启动 gateway-demo
、goods-service-demo
和 shopcart-service-demo
这三个项目。启动成功后,打开浏览器验证网关的功能,在地址栏中依次输入如下地址进行测试:
http://localhost:8127/goods?goodsId=2025
http://localhost:8127/goods/page/2
http://localhost:8127/shop-cart?cartId=2035
http://localhost:8127/shop-cart/page/3
四次访问的最终结果如图 9-7 所示。

Spring Cloud Gateway
网关整合成功!
另外,有一个知识点需要注意:不要在网关模块中加入 spring-boot-starter-web
依赖,否则网关项目是无法正常启动的,报错内容如下:
****************************
APPLICATION FAILED TO START
****************************
Description:
Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway.
Spring
官方文档中也做了重点提示,内容如下:
Spring Cloud Gateway requires the Netty runtime provided by Spring Boot and
Spring Webflux. It does not work in a traditional Servlet Container or when
built as a WAR.
在使用 Spring Cloud Gateway
组件时,不能使用传统的 Servlet
容器,也不能打包成 WAR
包。
将网关服务整合到服务中心
前文中只是简单地整合网关和功能验证,并没有整合服务中心,即网关模块并没有被真正纳入微服务架构中。在配置文件中定义的路由地址是 “写死的”,这种做法在真实项目中肯定是不推荐的。接下来要做的就是把 Spring Cloud Gateway
注册到服务中心,通过服务中心(本书中的技术选型为 Nacos
)把请求路由到对应的服务实例中。
新建一个模块,命名为 gateway-demo2
,Java
代码的包名为 ltd.newbee.cloud
。在该模块的 pom.xml
配置文件中增加 parent
标签,与上层 Maven
建立好关系。打开 gateway-demo2
项目中的 pom.xml
文件,在 dependencies
标签下引入 Spring Cloud Gateway
和服务发现的依赖文件,最终代码如下:
<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ltd.newbee.cloud</groupId>
<artifactId>gateway-demo2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gateway-demo2</name>
<description>Spring Cloud Alibaba Gateway Demo</description>
<parent>
<groupId>ltd.newbee.cloud</groupId>
<artifactId>spring-cloud-alibaba-gateway-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
</project>
下面修改 gateway-demo2
项目中的 application.properties
配置文件,增加服务发现的配置项和路由配置项,代码如下:
server.port=8129
# 应用名称
spring.application.name=newbee-cloud-gateway-service
# 注册中心 Nacos 的访问地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
# 登录名(默认为 nacos,可自行修改)
spring.cloud.nacos.username=nacos
# 密码(默认为 nacos,可自行修改)
spring.cloud.nacos.password=nacos
spring.cloud.gateway.discovery.locator.enabled=true
spring.cloud.gateway.discovery.locator.lower-case-service-id=true
spring.cloud.gateway.routes[0].id=goods-service-route
spring.cloud.gateway.routes[0].uri=lb://newbee-cloud-goods-service
spring.cloud.gateway.routes[0].order=1
spring.cloud.gateway.routes[0].predicates[0]=Path=/goods/**
spring.cloud.gateway.routes[1].id=shopcart-service-route
spring.cloud.gateway.routes[1].uri=lb://newbee-cloud-shopcart-service
spring.cloud.gateway.routes[1].order=1
spring.cloud.gateway.routes[1].predicates[0]=Path=/shop-cart/**
路由配置与前文中介绍的路由配置区别不大,只是将 “写死” 的地址修改为对应服务的地址,这样就能通过服务发现机制路由到对应的服务实例中了。另外,地址前缀由 http
改为了 lb
,表示启用负载均衡功能。微服务中负载均衡这个知识点的编码和源码,笔者都已经讲解过。
在本书中,Spring Boot
项目的配置文件都是 .properties
格式的。如果平时开发时习惯使用 .yml
格式的配置文件,可自行修改。
编码完成后,最终 spring-cloud-alibaba-gateway-demo
项目的目录结构如图 9-8 所示。

编码完成后进行功能验证,需要启动 Nacos Server
,之后依次启动 gateway-demo2
、goods-service-demo
和 shopcart-service-demo
这三个项目。如果未能成功启动,则开发人员需要查看控制台中的日志是否报错,并及时确认问题和修复。启动成功后进入 Nacos
控制台,单击 “服务管理” 中的服务列表,可以看到列表中已经存在这三个服务的服务信息,如图 9-9 所示。
打开浏览器验证网关的功能,在地址栏中依次输入如下地址进行测试:
http://localhost:8129/goods?goodsId=2025
http://localhost:8129/goods/page/2
http://localhost:8129/shop-cart?cartId=2035
http://localhost:8129/shop-cart/page/3

整合Spring Cloud Gateway报错503的问题解决方法
此时页面中显示的结果如下:
Whitelabel Error Page
This application has no configured error view, so you are seeing this as a
fallback.
Mon Jun 5 16:28:12 CST 2023
[0223c41b-3]There was an unexpected error(type=Service
Unavailable, status=503).
并未获取正确的结果,而是一个 503
的报错提示。
报错主要是因为 Spring Cloud Gateway
的相关依赖中没有负载均衡器,因此无法正确将请求路由到对应的服务中。修改方式比较简单,在 Gateway
项目的依赖文件中加上负载均衡器的依赖就可以了,新增如下代码:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
添加代码后记得刷新一下 Maven
依赖,之后重新启动这个项目,在浏览器中就能够获取正确的数据了。
为什么要单独讲一下这个问题呢?主要是因为浏览器中报了这个错误,但是在网关项目的日志文件中并没有这个错误的异常信息栈,这就导致开发人员在看到这个问题后,无法判断出现这个问题的具体原因,进而不知道如何处理它。
现在,服务网关也整合到项目中了。不过,仅仅整合和简单的配置是远远不够的,接下来笔者将介绍 Spring Cloud Gateway
组件中的重要知识——Predicate
(断言)和 Filter
(过滤器)。