gateway网关
什么是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-serviceuri: lb://orderservicepredicates:- 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: carturi: lb://cart-servicepredicates:- Path=/carts/**- id: useruri: lb://user-servicepredicates:- Path=/users/**,/addresses/**- id: tradeuri: lb://trade-servicepredicates:- Path=/orders/**- id: payuri: lb://pay-servicepredicates:- 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 {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 在这里添加你的逻辑,比如修改请求头、参数等// 例如:添加一个请求头exchange.getRequest().mutate().header("X-Custom-Header", "CustomValue").build();// 继续过滤链return chain.filter(exchange);}@Overridepublic 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 实例。*/@Beanpublic 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 实例。*/@Beanpublic 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为123456default-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> 异步处理完成的信号*/@Overridepublic 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 过滤器的顺序值*/@Overridepublic int getOrder() {// 设置最高优先级return 0;} }