什么是gateway网关?
网关相当于是微服务统一的大门,负责路由、跳转、身份校验。
常见的网关有哪些?
在spring cloud中的网关包括Geteway和zull,两者之间的区别在于一个是响应式一个是阻塞式编程,查阅了资料,经过测试响应式的吞吐速度要比阻塞式更加快,而且zuul维护较少,之后肯定是Geteway逐渐代替zuul。
当前端发送一个请求到网关的时候,网关会将请求路由到注册中心,并根据断言工厂返回指定的服务
server: port: 10010 # 网关端口 spring: application: name: gateway # 服务名称 cloud: nacos: server-addr: localhost:80 # nacos地址 gateway: routes: - id: user-service # 路由id,不能重复 uri: lb://userservice # 目标服务名称|| lb://+服务名 predicates: # 断言 - Path=/user/** # 以user开头的请求,都会被路由到userservice服务 - id: order-service uri: lb://orderservice predicates: - Path=/order/**
这是一段网关配置,先给大家看看,下面再说实战。
定义网关
网关本身也是一个微服务,所以需要单独创建一个项目模块启动并注册到注册中心。
创建项目->导入依赖->配置网关->????
1.创建一个项目,包含启动类,核心配置文件
2.导入依赖
<!--网关--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--nacos discovery--> <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-loadbalancer</artifactId> </dependency>
网关配置
server: port: 8080 # 端口号 spring: application: name: gateway # 服务名称 cloud: nacos: server-addr: localhost:8848 # nacos注册中心地址 gateway: routes: - id: item # 路由规则id,自定义,唯一 uri: lb://item-service # 路由的目标服务,lb代表负载均衡,会从注册中心拉取服务列表 predicates: # 路由断言,判断当前请求是否符合当前规则,符合则路由到目标服务 - Path=/items/**,/search/** # 这里是以请求路径作为判断规则 - id: cart uri: lb://cart-service predicates: - Path=/carts/** - id: user uri: lb://user-service predicates: - Path=/users/**,/addresses/** - id: trade uri: lb://trade-service predicates: - Path=/orders/** - id: pay uri: lb://pay-service predicates: - Path=/pay-orders/** default-filters: #全局过滤器 - name: PrintAny # 自定义过滤器
以上就是网关的基础配置了
过滤器
网关的过滤器分为局部过滤器和全局过滤器:
局部过滤器(GatewayFilter):专门针对一个微服务,只有在某个单独的过滤器访问时才触发
全局过滤器(GlobalFilter):对所有的微服务,每个微服务访问网关都会经过全局过滤器
局部过滤器:
局部过滤器的实现有两种,一种是通过配置文件来实现,还有一种是通过代码实现。
配置文件:
配置文件实现在就是在某个微服务配置的网关内部写filters
gateway: routes: - id: item # 路由规则id,自定义,唯一 uri: lb://item-service # 路由的目标服务,lb代表负载均衡,会从注册中心拉取服务列表 predicates: # 路由断言,判断当前请求是否符合当前规则,符合则路由到目标服务 - Path=/items/**,/search/** # 这里是以请求路径作为判断规则 filters: - addRequestHeader=X-Request-Id,123456 # 添加请求头,key为X-Request-Id,value为123456
常见的过滤器工厂:
- AddRequestParameter GatewayFilter Factory:用于添加请求参数。
- AddResponseHeader GatewayFilter Factory:用于添加响应头。
- SetStatus GatewayFilter Factory:用于设置HTTP响应状态码。
spring cloud为我们提供了非常多的过滤器工厂,具体的可以看官网: cloud局部过滤器官网
代码实现:
局部过滤器的代码实现十分复杂,不推荐,一般情况直接用配置文件就能完成需求
步骤 1: 创建一个实现了
GlobalFilter
接口的类import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; public class CustomFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 在这里添加你的逻辑,比如修改请求头、参数等 // 例如:添加一个请求头 exchange.getRequest().mutate().header("X-Custom-Header", "CustomValue").build(); // 继续过滤链 return chain.filter(exchange); } @Override public int getOrder() { // 设置过滤器的顺序,数值越小,优先级越高 return -1; } }
步骤 2: 将过滤器注册为Bean
在你的Spring Boot应用中,你需要将这个过滤器注册为一个Bean,这样Spring Cloud Gateway才能识别并使用它。
package com.hmall.gateway.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * 网关配置类,用于定义网关相关的 Bean 和配置。 */ @Configuration public class GatewayConfig { /** * 定义一个自定义过滤器的 Bean。 * * @return 返回一个初始化好的 CustomFilter 实例。 */ @Bean public CustomFilter customFilter() { return new CustomFilter(); } }
步骤 3: 将局部过滤器应用到特定的路由
虽然你已经创建了一个全局过滤器,但你可能想要将这个过滤器应用到特定的路由上。你可以在路由配置中指定这个过滤器。
package com.hmall.gateway.config; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * 网关路由配置类,用于定义网关的路由规则。 */ @Configuration public class RouteConfig { /** * 定义一个自定义的 RouteLocator Bean,用于配置网关的路由规则。 * * @param builder 路由构建器,用于创建和配置路由规则。 * @return 返回配置好的 RouteLocator 实例。 */ @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() // 定义一个名为 "custom_filter_route" 的路由规则 .route("custom_filter_route", r -> r // 匹配路径为 "/specific-path/**" 的请求 .path("/specific-path/**") // 添加自定义过滤器 CustomFilter 到该路由中 .filters(f -> f.filter(new CustomFilter())) // 将匹配到的请求转发到指定的目标 URI (http://example.com) .uri("http://example.com")) .build(); } }
在这个例子中,
CustomFilter
将只应用于路径匹配/specific-path/**
的请求。注意事项
filter
方法中的逻辑是你添加自定义处理的地方,比如修改请求头、参数、响应头等。getOrder
方法用于设置过滤器的执行顺序。Spring Cloud Gateway中的过滤器是有序的,可以根据需要调整这个顺序。- 在路由配置中,你可以通过
.filter(new CustomFilter())
来指定使用哪个过滤器实例。如果你想要应用多个过滤器,可以链式调用.filter()
方法。以上就是创建和使用局部过滤器的基本步骤和代码示例。你可以根据实际需求调整过滤器的逻辑和配置。
全局过滤器:
全局过滤器顾名思义就是全局生效,不管哪个微服务访问都能触发
配置实现
spring: application: name: gateway # 服务名称 cloud: nacos: server-addr: localhost:8848 # nacos注册中心地址 gateway: routes: - id: item # 路由规则id,自定义,唯一 uri: lb://item-service # 路由的目标服务,lb代表负载均衡,会从注册中心拉取服务列表 predicates: # 路由断言,判断当前请求是否符合当前规则,符合则路由到目标服务 - Path=/items/**,/search/** # 这里是以请求路径作为判断规则 filters: - addRequestHeader=X-Request-Id,123456 # 添加请求头,key为X-Request-Id,value为123456 default-filters: #全局过滤器 - name: PrintAny # 自定义过滤器
代码实现
全局过滤器可以有多个,会按照Ordered中的顺序来执行,也被称为过滤器链
package com.hmall.gateway.filters; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.HttpHeaders; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; /** * 自定义全局过滤器,用于处理所有请求 * 实现了GlobalFilter和Ordered接口,以定义过滤器的执行顺序 */ public class MyGlobalFilter implements GlobalFilter, Ordered { /** * 过滤器的具体逻辑 * * @param exchange 服务器Web交换对象,包含请求和响应的所有信息 * @param chain 网关过滤器链,用于将控制权转交给下一个过滤器 * @return Mono<Void> 异步处理完成的信号 */ @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 获取当前请求 ServerHttpRequest request = exchange.getRequest(); // 获取请求头 HttpHeaders headers = request.getHeaders(); // 打印请求头信息,用于调试和日志记录 System.out.println("请求头:" + headers); // 将请求传递给过滤器链中的下一个过滤器 return chain.filter(exchange); } /** * 获取过滤器的执行顺序 * 数值越小,优先级越高 * * @return int 过滤器的顺序值 */ @Override public int getOrder() { // 设置最高优先级 return 0; } }