1. 概念
网关的作用:
- 认证、鉴权
- 服务路由、负载均衡
- 请求限流
网关的实现:
- gateway
基于Spring5中提供的WebFlux,属于响应式编程的实现,具备更好的性能 - zuul
基于Servlet的实现,属于阻塞式编程
2. 实现网关
1. 实现流程
新建module:
引入依赖:
<!--网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服务发现依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
启动类:
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
配置文件:
# 配置nacos服务地址
server:
port: 8099 # 网关端口
spring:
application:
name: gateway # 服务名称
cloud:
nacos:
server-addr: localhost:8848 # nacos地址
gateway:
routes: # 网关路由配置
- id: gateway # 路由id,自定义,只要唯一即可
# uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
uri: lb://provider # 路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
- Path=/pro/** # 这个是按照路径匹配,只要以/pro/开头就符合要求
启动报错:
Parameter 0 of method loadBalancerWebClientBuilderBeanPostProcessor in org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration required a bean of type 'org.springframework.cloud.client.loadbalancer.reactive.DeferringLoadBalancerExchangeFilterFunction' that could not be found.
解决报错:引入 loadbalancer 依赖
<!--loadbalancer——防止报错-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
访问测试:
2. 小结
网关访问流程:
- id:自定义,网关唯一标识
- uri:使用负载均衡+服务名作为路由地址(lb://serviceName)
- predicates:路由断言,满足断言匹配规则才能进行访问
3. 断言工厂
在配置文件中的 gateway.routes.predicates 中定义好匹配规则,然后这些规则就会被 断言工厂(predicate factory——org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory) 读取并处理,转换为路由判断的条件。
常见断言工厂:
名称 | 说明 | 示例 |
---|---|---|
After | 是某个时间点后的请求 | - After=2037-01-20T17:42:47.789-07:00[America/Denver] |
Before | 是某个时间点之前的请求 | - Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai] |
Between | 是某两个时间点之前的请求 | - Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver] |
Cookie | 请求必须包含某些cookie | - Cookie=chocolate, ch.p |
Header | 请求必须包含某些header | - Header=X-Request-Id, \d+ |
Host | 请求必须是访问某个host(域名) | - Host=.somehost.org,.anotherhost.org |
Method | 请求方式必须是指定方式 | - Method=GET,POST |
Path | 请求路径必须符合指定规则 | - Path=/red/{segment},/blue/** |
Query | 请求参数必须包含指定参数 | - Query=name, Jack或者- Query=name |
RemoteAddr | 请求者的ip必须是指定范围 | - RemoteAddr=192.168.1.1/24 |
Weight | 权重处理 |
注意: 可同时匹配多个断言规则。
4. 过滤器工厂
1. GatewayFilter
过滤器(GatewayFilter)可以对进入网关的请求和微服务返回的响应做处理。
常见过滤器:
名称 | 说明 |
---|---|
AddRequestHeader | 给当前请求添加一个请求头 |
RemoveRequestHeader | 移除请求中的一个请求头 |
AddResponseHeader | 给响应结果中添加一个响应头 |
RemoveResponseHeader | 从响应结果中移除有一个响应头 |
RequestRateLimiter | 限制请求的流量 |
过滤器官方写法: https://docs.spring.io/spring-cloud-gateway/docs/3.1.4/reference/html/#gatewayfilter-factories
指定服务,过滤器仅对 provider 服务生效:
gateway:
routes: # 网关路由配置
- id: gatewayid # 路由id,自定义,只要唯一即可
# uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
uri: lb://provider # 路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
- Path=/pro/** # 这个是按照路径匹配,只要以/pro/开头就符合要求
# 将标头添加到所有匹配请求的下游请求标头中。X-Request-red:blue
filters:
- AddRequestHeader=X-Request-red, blue
默认过滤器,对所有服务都生效:
gateway:
routes: # 网关路由配置
- id: gatewayid # 路由id,自定义,只要唯一即可
# uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
uri: lb://provider # 路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
- Path=/pro/** # 这个是按照路径匹配,只要以/pro/开头就符合要求
default-filters:
- AddRequestHeader=X-Request-red, blue
2. GlobalFilter
全局过滤器(GlobalFilter): 处理一切进入网关的请求和微服务响应,不同于 GatewayFilter ,全局过滤器需要自己写代码实现过滤逻辑。
自定义的全局过滤器需要实现以下接口
public interface GlobalFilter {
/**
* 处理Web请求、委托给下一个下一个过滤器处理(可选)
* @param exchange 请求上下文,里面可以获取Request、Response等信息
* @param chain 用来把请求委托给下一个过滤器
* @return {@code Mono<Void>} 返回标示当前过滤器业务结束
*/
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
可通过实现上述接口,重写 filter 方法实现以下功能:
- 登录状态判断
- 权限校验
- 请求限流
实现身份认证:
@Order(-100)
@Component
public class AuthorizeFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1.获取请求参数
ServerHttpRequest request = exchange.getRequest();
MultiValueMap<String, String> params = request.getQueryParams();
// 2.获取参数中的 auth 参数
String auth = params.getFirst("auth");
// 3.判断参数值是否等于 root
if ("root".equals(auth)) {
// 4.是,放行
return chain.filter(exchange);
}
// 5.否,拦截
// 5.1.设置状态码
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
// 5.2.拦截请求
return exchange.getResponse().setComplete();
}
}
- @Order 用来处理相同接口实现类的执行优先级问题
- 数值越小,越优先执行
测试:
3. 过滤器的执行顺序
默认执行顺序如下:
- 每个过滤器都被指定了一个整型的 order 值,order 越小,优先级越高,越早执行
- 路由过滤器(单个微服务的)和 默认过滤器 的 order 值 由 spring 指定,全局过滤器的 order 需要自行指定
5. 解决跨域问题
跨域问题:
- 跨域:域名不一致,包括三种类型:①域名不同;②域名相同,端口不同;③ 二级域名不同
- 跨域问题:浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题
解决跨域问题:
-
方式一: CORS
跨域问题及CORS解决跨域问题方法import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; @Configuration public class GlobalCorsConfig { @Bean public CorsFilter corsFilter() { //1.添加CORS配置信息 CorsConfiguration config = new CorsConfiguration(); //1) 允许的域,不要写*,否则cookie就无法使用了 config.addAllowedOrigin("http://manage.leyou.com"); //2) 是否发送Cookie信息 config.setAllowCredentials(true); //3) 允许的请求方式 config.addAllowedMethod("OPTIONS"); config.addAllowedMethod("HEAD"); config.addAllowedMethod("GET"); config.addAllowedMethod("PUT"); config.addAllowedMethod("POST"); config.addAllowedMethod("DELETE"); config.addAllowedMethod("PATCH"); // 4)允许的头信息 config.addAllowedHeader("*"); //2.添加映射路径,我们拦截一切请求 UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); configSource.registerCorsConfiguration("/**", config); //3.返回新的CorsFilter. return new CorsFilter(configSource); } }
-
方式二:通过 gateway
spring: cloud: gateway: # 。。。 globalcors: # 全局的跨域处理 add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题 corsConfigurations: '[/**]': allowedOrigins: # 允许哪些网站的跨域请求 - "http://localhost:8090" allowedMethods: # 允许的跨域ajax的请求方式 - "GET" - "POST" - "DELETE" - "PUT" - "OPTIONS" allowedHeaders: "*" # 允许在请求中携带的头信息 allowCredentials: true # 是否允许携带cookie maxAge: 360000 # 这次跨域检测的有效期
转载:https://blog.csdn.net/m0_54355172/article/details/128451435