本章节的讲解代码下载地址如下:
链接: https://pan.baidu.com/s/1kEHVjog45PztXxJNjSkpTA
提取码: 14fu
接下来就通过实际的编码,把微服务网关整合到项目中,顺便来体验一下 Spring Cloud Gateway 的功能。
编码整合 Spring Cloud Gateway
接下来笔者将结合实际的编码,来讲解如何构建一个网关服务。本章节代码是在 spring-cloud-alibaba-multi-service-demo 模板项目的基础上修改的,具体步骤如下所示。
第一步,修改文件名称。
首先,修改项目名称为 spring-cloud-alibaba-gateway-demo,然后把各个 Module 中 pom.xml 文件的 artifactId 修改为 spring-cloud-alibaba-gateway-demo。
第二步,新建网关 Module 并引入 Spring Cloud Gateway 依赖。
新建一个 Module,命名为 gateway-demo,Java 代码的包名为 ltd.newbee.cloud。在该 Module 的 pom.xml 配置文件中增加 parent 标签,与上层 Maven 建立好关系。
然后打开 gateway-demo 项目中的 pom.xml 文件,在 dependencies 标签下引入 Spring Cloud Gateway 的依赖文件,新增代码如下:
<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 这 3 个项目。启动成功后,打开浏览器验证网关的功能,在地址栏中依次输入如下地址进行测试。
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
四次访问的最终结果如下图所示。
网关整合成功!
另外,有一个知识点需要注意:不要在网关 Module 中加入 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)把请求路由到对应的服务实例中。
新建网关模块并整合至 Nacos
新建一个 Module,命名为 gateway-demo2,Java 代码的包名为 ltd.newbee.cloud。在该 Module 的 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
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.cloud.nacos.username=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/**
本课程中,Spring Boot 项目的配置文件都是. properties 格式的。如果平时开发时习惯使用. yml 格式的配置文件,可自行修改。
路由配置与前文中介绍的区别不大,只是由 “写死” 的地址修改为对应服务的地址,这样就能通过服务发现机制路由到对应的服务实例中了。另外,就是地址前缀由 http 改为了 lb,表示将会启用负载均衡功能,微服务中负载均衡这个知识点的编码和源码,笔者都已经讲解过。
编码完成后,最终 spring-cloud-alibaba-gateway-demo 项目的目录结构如下图所示。
功能验证
接下来,需要启动 Nacos Server,然后依次启动 gateway-demo2、goods-service-demo 和 shopcart-service-demo 这 3 个项目。如果未能成功启动,开发者需要查看控制台中的日志是否报错,并及时确认问题和修复。启动成功后进入 Nacos 控制台,点击 “服务管理” 中的服务列表,可以看到列表中已经存在这三个服务的服务信息,如下图所示。
接着,打开浏览器验证网关的功能,在地址栏中依次输入如下地址进行测试。
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
然而,此时的结果如下图所示。
并未获取到正确的结果,而是一个 503 的报错提示。
主要是因为 Spring Cloud Gateway 的相关依赖中并没有负载均衡器,因此无法正确将请求路由到对应的服务中。修改方式也比较简单,在 Gateway 项目的依赖文件中加上负载均衡器的依赖就可以,新增如下代码即可。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
添加后记得刷新一下 Maven 依赖,然后再重新启动这个项目,在浏览器中就能够获取到正确的数据了。
为什么要单独讲一下这个问题呢?主要是因为浏览器中报了这个错误,但是在网关项目的日志文件中并没有这个错误的异常信息栈,这就导致开发者们在看到这个问题后,无法判断出导致这个问题的具体原因,进而也无法知道如何去处理它。另外一点就是当前使用的技术栈,版本都比较高,有些问题在网络上还无法找到答案,因此笔者在这里复现了这个问题并介绍了处理方式。
现在,服务网关也整合到项目中来了。不过,仅仅整合和简单的配置是远远不够的,接下来,笔者将继续介绍 Spring Cloud Gateway 组件中的重要知识点——Predicate(断言)和 Filter(过滤器)。当然,读者如果有任何问题或者想要和笔者讨论的内容,都可以在评论区留下看法,笔者会根据读者的反馈和问题继续整理和完善本章节内容。
原文地址 juejin.cn