前言
本文主要介绍一个demo,用 nacos 做为注册中心,展示Spring gateway 网关的基本使用。也讲了在这一过程中踩过的坑。
一、启动 nacos
参考 Spring Cloud 中 OpenFeign的使用 中介绍 nacos 启动的部分。
二、新建项目 cloud-gateway
用 spring initializr 选择 Spring Cloud Routing - Reactive Gateway 和 Cloud LoadBalancer,这个项目不是MVC项目,没有Controller等类。然后我们手动在pom.xml中引入nacos ,配置好路由规则运行起来就可以作为网关使用了。
选择上述两个选项(Reactive Gateway 和 Cloud LoadBalancer),生成的pom.xml文件中,会引入 spring-cloud-starter-gateway 和 spring-cloud-starter-loadbalancer,
注意:
loadbalancer 一定不能缺失,踩过的坑就是之前没有引入 loadbalancer。
导致网关调用api时,如果网关uri设置为ip地址,可以访问到;
而换成设置为指向配置中心的,比如 lb:passenger-api,就会报错说:
NotFoundException: 503 SERVICE_UNAVAILABLE “Unable to find instance for passenger-api”
后来看日志,问文心一言,才想到可能是负载均衡器没有设置所导致,引入负载均衡器之后,网关就能调用到api了
另:如果我们用 spring initializr 选择 Spring Cloud Routing - Gateway 和 Cloud LoadBalancer,
引入的 gateway 将是 spring-cloud-starter-gateway-mvc。
spring-cloud-starter-gateway 和 spring-cloud-starter-gateway-mvc 是不同的,具体可以自行搜索。
pom.xml 中引入的依赖:
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-loadbalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!--SpringCloud依赖,一定要放到dependencyManagement中,起到管理版本的作用即可-->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2023.0.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--SpringCloudAlibaba依赖-->
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-alibaba-dependencies -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2023.0.1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
配置路由规则,新建一个GatewayConfig类
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("abc-route",r -> r.path("/api/**")
.filters(f -> f.stripPrefix(1))
.uri("lb://passenger-api"))
.build();
}
}
这个路由规则就是将我们对网关的请求,转发到实际执行的api接口
abc-route 是这个路由规则的id,可以任意取。
path(“/api/**”) 是这个路由的匹配路径,也就是只要是访问网关地址 localhost:9001/api/… 的请求,就会根据这条规则进行路由
filters(f -> f.stripPrefix(1)) 使用了过滤器,从匹配的请求路径中去掉第一个路径段(即去掉/api)
.uri(“lb://passenger-api”): 这指定了路由的目标URI。lb://前缀表示这是一个负载均衡的URI,passenger-api是服务的名称。Spring Cloud Gateway将使用Spring Cloud的负载均衡机制(如Spring Cloud LoadBalancer)来解析这个服务名称,并将请求转发到该服务的某个实例上。
举个例子来说明一下:
我们对网关发起请求 http://localhost:9000/api/gateway/hello
会匹配这条路由规则,因为符合/api/**的模式,
根据这条规则,会去掉/aip 这个路径段,
然后访问 passenger-api 服务的 /gateway/hello 接口,我们在nacos中注册 passenger-api 的 uri为 192.168.31.136:9002,
因此,这个请求最终会被路由到 http://192.168.31.136:9002/gateway/hello
三、新建项目passenger-api
这个项目就是一个支持 nacos discovery 的普通web项目,有一个Controller对外支持get请求访问 /gateway/hello
说明
还有一个坑就是pom.xml中引入的各项依赖要小心选择,保证兼容。
比如 spring-cloud-starter-gateway 和 spring-cloud-starter-loadbalancer 要兼容。之前就因为这2者不兼容而造成网关无法路由到api。