springCloudGateway-踩坑记录
一、需求描述
旧项目做好之后,已经维护了一两个月,基本上已经趋于稳定,按照项目的整体进度基本上不会在做什么改动。新项目已经确定
下来,只是有一个大概的需求,unity3d的客户端已经开始做,在这个月23号之前会要求先出一个游戏的版本。目前相对来说不是太忙,
自己就考虑着开始搭建新项目的框架,首先考虑的就是先搭建网关服务。之前的项目由于工期非常短,并且非常急就没有把网关服务
给加进去,现在有时间了自己就想着第一个任务就是先添加网关服务,之后在根据需要在添加其他的服务。
二、需求分析
自己的一个了解,网关服务可以做很多事情,比如实现所有访问请求的日志采集;身份认证,是否已经登录,是否有权限登录某个
系统;如果系统的访问量比较大的话,还可以做负载均衡;还可以做路由转发,根据不同的路由转发到对应的服务。好处这么多当然需要
使用一个网关服务来作为项目的统一入口,做各种事情。
三、技术选型
由于现在技术更新得特别快,比如springboot的版本一直在不断地进行更新,支持时间也在不断地压缩。
参考了很多资料,最终自己采纳选择2.3.x的springboot版本,springcloud和springcloudalibaba的版本如下,
<!-- 依赖的jar包所对应的版本 -->
<properties>
<spring-cloud.version>Hoxton.SR9</spring-cloud.version>
<spring-cloud-alibaba.version>2.2.6.RELEASE</spring-cloud-alibaba.version>
<!--<spring-cloud-starter-alibaba-nacos-config.version>1.4.2</spring-cloud-starter-alibaba-nacos-config.version>-->
<!-- 编译插件 mvn compile -->
<maven-compiler-plugin.source>1.8</maven-compiler-plugin.source>
<maven-compiler-plugin.target>1.8</maven-compiler-plugin.target>
<maven-compiler-plugin.encoding>UTF-8</maven-compiler-plugin.encoding>
<!-- 是否跳过单元测试 解决中文乱码 -->
<maven-surefire-plugin.skipTests>true</maven-surefire-plugin.skipTests>
<maven-surefire-plugin.argLine>-Dfile.encoding=UTF-8</maven-surefire-plugin.argLine>
<mybatis-generator-maven-plugin.version>1.3.2</mybatis-generator-maven-plugin.version>
</properties>
<!-- 单个子项目特有的jar包 -->
<dependencyManagement>
<dependencies>
<!-- springcloud版本 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- springcloud alibaba 版本 -->
<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>
版本选定好之后就开始搭建项目。由于自己之前一直在使用springcloudalibaba的nacos组件,因此新搭建的项目中继续使用这个组件。
主要用来做配置管理和服务发现。本篇博文需要有nacos使用基础的人才能理解。
首先搭建gateway网关项目,java代码很简单,就一个启动类,导入的maven配置如下:<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- lombok 仅限编译的时候使用 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</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>
nacos中的配置如下:
![](https://img2020.cnblogs.com/blog/2127275/202201/2127275-20220107223400892-189318653.png)
spring.application.name=motionSpaceGateway
spring.profiles.active=dev
#配置管理
spring.cloud.nacos.config.server-addr=127.0.0.1:24700
#spring.cloud.nacos.config.server-addr=192.168.1.2.5
#命名空间
spring.cloud.nacos.config.namespace=8760e76628114fceb7fc723b2da51c5c
#分组配置
spring.cloud.nacos.config.group=motionSpace
# 开启动态刷新
spring.cloud.nacos.config.refresh.enabled=true
#读取的配置文件后缀名
spring.cloud.nacos.config.file-extension=properties
#服务发现地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:24700
#spring.cloud.nacos.discovery.server-addr=192.168.1.2.5
由于刚开始搭建项目,只要请求能够转发即可,之后的一些功能会一步一步的进行添加。
做完这些工作后,启动项目,如下图
注意事项:springcloudgateway这个项目,不需要配置项目的根路径,如上图所示。它和其他springboot项目的启动方式还不太一样,其他
项目可以配置项目的根路径,在项目启动时也会添加进去。可是springcloudgateway 即使在配置中添加了项目根路径,启动时也不会加载。
上图显示的是Netty started on port,只需要配置一个端口即可。
之后是搭建一个后端主项目,导入的maven配置如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- lombok 仅限编译的时候使用 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</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>
配置更加简单,一个端口和一个访问路径即可:
bootstrap.properties的配置如下:
spring.application.name=motionSpacebackend
spring.profiles.active=dev
#配置管理
spring.cloud.nacos.config.server-addr=127.0.0.1:24700
#spring.cloud.nacos.config.server-addr=192.168.1.2.5
#命名空间
spring.cloud.nacos.config.namespace=8760e76628114fceb7fc723b2da51c5c
#分组配置
spring.cloud.nacos.config.group=motionSpace
# 开启动态刷新
spring.cloud.nacos.config.refresh.enabled=true
#读取的配置文件后缀名
spring.cloud.nacos.config.file-extension=properties
#服务发现地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:24700
#spring.cloud.nacos.discovery.server-addr=192.168.1.2.5
然后添加一个测试类
@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {
/**
* @description:
* @author: dengyilang
* @date: 2022/1/7 17:40
* @return: void
*/
@RequestMapping(value = "/rout", method = RequestMethod.GET)
public String scanBind(){
log.info("backend路由测试---");
return "路由测试";
}
}
项目启动成功。
首先测试后端项目能否正常访问,访问的地址为 http://localhost:17303/backend/test/rout
测试结果正常。
然后测试使用网关服务进行转发是否正常,请求地址为 http://localhost:51309/gateway/backend/test/rout
测试结果正确。
请求的大致过程为 首先请求地址 http://localhost:51309/gateway/backend/test/rout 会到达 gateway项目的后台,
根据路由匹配规则,匹配到如下图中的路由,并且会截取掉第一个前缀/gateway/变为 http://localhost:51309/backend/test/rout
然后gateway项目将请求进行转发到下图的地址中,gateway项目在底层进行处理时,会将motionSpacebackend这个项目名称解析为
对应的地址和端口,在本地就解析为127.0.0.1:17303
转发后的请求就变为http://127.0.0.1:17303/backend/test/rout 最终正确地返回想要的结果。
到此一个简单的网关服务就搭建完成,之后在使用过程中遇到任何问题都会更新在本篇博客中。
参考博客
https://www.cnblogs.com/hellohero55/p/12723451.html
2022-01-10-出现问题一:自己按照之前的教程将gateway项目搭建起来后,顺利的通过gateway项目转发请求访问到另外一个项目的首页,
可是当自己重新引入一个自定义的公共模块后,发现就访问不了了,这就让我很纳闷,是怎么回事呢?明明之前还好好的,
而且还报了一个错如下,
Action:
Consider defining a bean of type 'org.springframework.http.codec.ServerCodecConfigurer' in your configuration.
查看网友的类似问题,经过排查发现,自己确实在新引入的公共模块中引入了spring-boot-starter-web 这个依赖导致的,参考博文如下
https://www.cnblogs.com/youcong/p/13939473.html
解决办法,暂时不导入公共模块即可。
springcloudgateway的配置如下:
#SSL证书配置 网站是使用 https访问
由于项目中使用了WebSocket这门技术,如果使用gateway网关进行转发wss协议的请求,会一直报一个错如下
java.lang.ClassCastException: org.apache.catalina.connector.ResponseFacade cannot be cast to reactor.netty.http.server.HttpServerResponse
at org.springframework.web.reactive.socket.server.upgrade.ReactorNettyRequestUpgradeStrategy.getNativeResponse(ReactorNettyRequestUpgradeStrategy.java:124)
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ HTTP GET "/gateway/applets/websocket" [ExceptionHandlingWebHandler]
这个错暂时还未解决,可是不影响系统的使用。在使用google搜索这个异常后,发现都只有3页的答案,一个一个的尝试后暂时还未解决这个问题。
让系统能够正常运行的办法是有使用websocket这门技术的项目直接使用nginx进行转发,不走gateway网关项目,其他项目的请求都走网关项目,
而且是使用https访问,以确保项目的安全性。
现在这种配置方式已经在生产环境上正式使用起来,已经稳定运行一两个月,暂时没发现其他问题。
之后在使用过程中遇到任何问题,都会贴出来进行分享。