客户端向 Spring Cloud Gateway 发出请求。如果Gateway Handler Mapping确定请求与路由匹配,则将其发送到Gateway Web Handler 处理程序。此处理程序通过特定于请求的Fliter链运行请求。在过滤器链上线执行pre部分逻辑,然后执行代理服务,然后支线post部分逻辑。 所以在执行一个过滤器时流程是这样的 pre→proxied service→post,如下图所示:
因为GateWay属于SpringCloud的,所以我们要导入对应依赖,一定要注意版本关系:
版本对应地址:Spring Cloud
我这里使用的是SpringBoot 2.3.12.RELEASE的版本所以配合的是SpringCloud的Hoxton.SR5版本
注意:引入GateWay一定要删除spring-boot-starter-web依赖,因为gateway 使用的是webflux 使用spring-boot-starter-web会导致无法启动
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.3.12.RELEASE
org.example
AlibabaNacos
1.0-SNAPSHOT
pom
8
8
1.8
2.2.7.RELEASE
2.2.7.RELEASE
Hoxton.SR5
org.projectlombok
lombok
1.18.22
org.springframework.cloud
spring-cloud-starter-openfeign
${spring-cloud-openfeign-version}
com.alibaba.cloud
spring-cloud-alibaba-dependencies
${spring-cloud-alibaba-version}
pom
import
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud-version}
pom
import
nacos-provider
gateway-app
4.0.0
org.example
AlibabaNacos
1.0-SNAPSHOT
com.example
gateway-app
0.0.1-SNAPSHOT
gateway-app
gateway-app
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
org.springframework.cloud
spring-cloud-starter-gateway
该模块支持多实例部署,以测试负载均衡
服务需要注册到注册中心nacos
服务名称:nacos-provider
端口:8081/8083
提供访问接口
@RestController
public class TestController {
@Value("${server.port}")
private String serverPort;
@GetMapping("/test/getServerPort")
public String getServerPort() {
return "Hello Nacos Discovery Port:" + serverPort;
}
}
配置如下:
spring.application.name=nacos-provider
spring.cloud.nacos.discovery.server-addr=192.168.43.11:8848
management.endpoints.web.exposure.include=*
server.port=8888
spring.application.name=gateway-app
# 注册发现服务nacos
spring.cloud.nacos.discovery.server-addr=192.168.43.11:8848
# 配置发现的服务自动配置路由转发
spring.cloud.gateway.discovery.locator.enabled=true
# 配置自定义路由转发id,不能重复
spring.cloud.gateway.routes[0].id=nacos-provider
# 配置路由转发地址,http://开头代表转发的服务地址。 如果是lb://服务名称,则是负载均衡转发
spring.cloud.gateway.routes[0].uri=http://localhost:8081
# 断言的第一种写法
#spring.cloud.gateway.routes[0].predicates[0].name=Path
#spring.cloud.gateway.routes[0].predicates[0].args.pattern=/test/**
# 断言的第二种写法
spring.cloud.gateway.routes[0].predicates[0]=Path=/test/**
从访问地址可以看出,服务提供者已正常
从图上可以看出通过8888端口,也就是网关也能正常访问服务,说明服务以通过网关转发成功了。
服务提供者和网关服务都通过注册中心注册服务,然后网关通过拉取注册中心服务实例,进行负载均衡调用,所以这里需要有注册中心支持。
需要修改网关服务配置文件
# 配置路由转发地址,http://开头代表转发的服务地址。 如果是lb://服务名称,则是负载均衡转发
spring.cloud.gateway.routes[0].uri=lb://nacos-provider
需要修改网关服务器启动类加服务注册发现支持
@SpringBootApplication
//启用服务注册发现客户端,这样才能通过nacos获取和注册服务
@EnableDiscoveryClient
public class GatewayAppApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayAppApplication.class, args);
}
}
然后启动服务提供者8081和8083服务,保证能正常访问
注意:服务提供者也需要服务注册发现支持
然后启动网关服务测试从网关访问,多访问几次看看返回端口是否有变化,如果有,则说明负载均衡以生效
除了上述我们使用了配置文件的方式配置路由,spring cloud gateway 还支持以代码的方式配置路由,这种方式可以实现动态的路由方式。 当然如果是静态的配置,推荐还是通过配置文件来配置, 这样就可以通过配置中心来实现热加载。
要用代码的方式来配置路由,我们需要创建一个Configuration类,并且返回一个RouteLocator类实例的Bean给SpringBean工厂。 如下:
@Configuration
public class GatewayRouteConfig {
/*
* 配置了一个id为path_msb1的路由规则
* 当访问地址http://localhost:8888/test/**
* 就会转发到lb://nacos-provider/ 的任何地址
*/
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
// 构建多个路由routes
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
// 具体路由地址
routes.route("code-route", predicateSpec -> predicateSpec.path("/**").uri("lb://nacos-provider")).build();
// 返回所有路由规则
return routes.build();
}
}