前言
在新公司做工已经两个月了,时间真的是快的吓人。我的主要工作是重构项目,所以也没什么适应期,不需要看老项目。随着这个新项目开发推进和合理性讨论,DDD的落地还是需要借助SpringCloud来做服务领域划分,因为我前东家用的是SpringCloud-Alibaba,所以我自己对其生态比较熟悉,所以经过讨论就打算先慢慢接入。
首先就是把注册中心(Nacos)和网关接入(Gateway),然后服务的rpc调用框架(OpenFeign)。其实springboot相关的生态已经做的很开箱即用了,但是在引入的过程中还是遇到一些小小的问题,尤其是引入Gateway过程中花了无谓的一下午时间,现在看来只要导入依赖和设置路由配置就好了。所以特意记录一下,给大家避避坑。
我写一个简单的QuicStart,并且把项目放到Github上
项目结构
- quickstart-gateway(外层父项目)
- demo-gateway(gateway项目)
- demo-service(服务项目,通过Gateway访问这个项目接口)
项目结构就是如上,这里只演示通过Gateway去调用一个service应用。这个跑通了,抄到项目里面就八九不离十。里面pom文件的编写我就不多说啦
pom坐标
设置SpringBoot的版本(这个在父模块)
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
设置dependencyManagement(在父模块,规定cloud和springboot相对应的版本号)
<properties>
<spring-cloud.version>Hoxton.SR10</spring-cloud.version>
</properties>
<dependencyManagement>
<!-- 指定cloud的版本 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Gateway我选择的版本(这个只在demo-gateway模块,代码里面我使用的dependencyManagement来管理子模块的版本号)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>2.2.7.RELEASE</version>
</dependency>
Nacos我选择的版本(demo-gateway和demo-service都要引入。代码里面我使用的dependencyManagement来管理子模块的版本号)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>0.9.0.RELEASE</version>
</dependency>
配置文件
demo-gateway模块的配置文件
server:
port: 8081
spring:
application:
name: demo-gateway
cloud:
# nacos的配置(这个nacos.host,请换成自己的nacos地址)
nacos:
discovery:
server-addr: nacos.host:8848
# gateway的配置
gateway:
# 开启从注册中心动态创建路由的功能,利用微服务名进行路由
discovery:
locator:
enabled: false
routes:
# 路由组名
- id: service
# lb负载均衡访问, 后面是模块的application.name
uri: lb://demo-service
# 匹配规则, 最好api-模块名的规范匹配
predicates:
- Path=/api-service/**
# 截取访问路径的前缀
# routes:
# filters:
# -StripPrefix=1
demo-service的配置文件
server:
port: 8082
spring:
# 在各注册中心中显示服务的名字
application:
name: demo-service
cloud:
# nacos的设置(这个nacos.host,请换成自己的nacos地址)
nacos:
discovery:
server-addr: nacos.host:8848
测试
把上面的配好以后,其实gateway现在就可以启动了,gateway可以在代码里面进行配置(例如复杂的过滤器等),也可以在配置文件中简单的进行一些谓词和过滤器的配置
然后我们在demo-service模块中写一个hello接口
@RestController
@RequestMapping("/api-service")
public class DemoController {
@GetMapping("/hello")
public String judgeOk() {
return "ok";
}
}
可能会遇到的问题速查
至此已经引入成功,这些组件都已经封装的很好了,理论上可以做到开箱即用,这里列举一些我遇到的问题。
- java.lang.NoSuchMethodError: reactor.netty.http.client.HttpClient.chunkedTransfer(Z)Lreactor/netty/http/client/HttpClient;
我的推测:版本问题(springboot版本高了),可以换2.1.6.RELEASE
试试
- java.lang.IllegalStateException: Error processing condition on org.springframework.cloud.gateway.config.GatewayAutoConfiguration$NettyConfiguration.gatewayHttpClient
我的推测:版本问题(gateway版本高了),可以换2.1.1.RELEASE
试试
- Parameter 0 of method modifyRequestBodyGatewayFilterFactory in org.springframework.cloud.gateway.config.GatewayAutoConfiguration required a bean of type ‘org.springframework.http.codec.ServerCodecConfigurer’ that could not be found.
上面这个版本问题强烈建议使用dependencyManagement
来管理。在这官网找到自己springboot版本对应的cloud版本,如下图
比如我用的是2.3.4的boot版本,我看到Hoxton里面如下告诉我,我的2.3.x是需要用以下的组件版本。
然后你在pom里面设置dependencyManagement
,它会帮你管理成如下的版本,你只需要导入就行了不用管版本号。
- 服务启动成功,但是访问报错404
我的推测:web依赖和webflux依赖冲突
<!-- web依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${springboot.version}</version>
</dependency>
<!-- webflux依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>${springboot.version}</version>
</dependency>
这个问题我实测好几遍,就是web和webflux冲突了,gateway使用的是webflux,如果你在gateway项目里面又重复引入web依赖或者gateway的父级(最有可能)就会出现这样的问题。那么解决办法就是把spring-boot-starter-web的依赖移除,但是如果是父级的话,可以考虑把这个父级依赖分别挪到对应的项目中,毕竟web模块不起服务的模块是不需要的,但是如果已经做了粒度划分实在想要排除,可以使用曲线救国实现。把下面代码添加到gateway的pom文件。
子模块重新导入web模块,并且指定test才生效,总这样就可以让编译器把这个依赖给过滤掉。如果想要排除只能这样,我试过exclusions排除web,发现没有效果,原因是exclusions只能在某个依赖里面使用,它排除的是这个依赖里面的依赖,不能排除自己项目的父级依赖
<!-- 特殊处理,不引入父类lib -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>test</scope>
</dependency>
- 服务启动成功,但是访问报错503
排除服务刚刚启动它没来得及就被你访问了导致503后
- 可能在nacos中没找到对应访问应用,检查一下nacos状态和配置文件里面的name
- 看看getway的依赖是否排除了webflux,这个不能排除
- 服务启动成功,但是访问报错404
- 检查配置文件
gateway:
# 开启从注册中心动态创建路由的功能,利用微服务名进行路由
discovery:
locator:
enabled: false
- 如果还是不行,检查一下predicates的配置,值得注意的是添加下面的配置,会截取前面N个/路径。意思就是假如predicates: -Path=/api-service/**。然后N配置1,访问/api-service/hello。到对应service应用只有hello。
routes:
filters:
-StripPrefix=N(这个N是数字)
(转载本站文章请注明作者和出处 没有气的汽水)
┌┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┐ ├ 文章已经完啦, 想要第一时间收到文章更新可以关注↓ ┤ └┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┘
Post Directory
下面是评论区,欢迎大家留言探讨或者指出错误哈