网关功能:
- 身份认证和权限校验
- 服务路由,负载均衡
- 请求限流
在SpringCloud中网关的实现有两种:
Zuul是基于Servlet的实现,属于阻塞式编程。而SpringCloudGateway则是基于Spring5中提供的WebFlux,属于响应式编程的实现,具备更好的性能。
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-gatewayartifactId>
dependency>
server:
port: 10010 #网关端口
spring:
application:
name: gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848 #nacos地址
gateway:
routes: # 网关路由配置
- id: user-server #路由id,自定义,唯一就行
# uri,可以写固定地址:http:127.0.0.1:8080
uri: lb://userserver # 路由的目标地址,lb的意思是loadbandle负载均衡
predicates: # 路由断言,判断请求是否符合规则
- Path=/user/** # 按照路径匹配,只要以/user/开头的请求都符合要求
- id: order-server
uri: lb://orderserver
predicates:
- Path=/order/**
网关路由可以配置的内容包括:
- 路由id:路由唯一标示
- uri:路由目的地,支持lb和http两种
- predicates: 路由断言,判断请求是否符合要求,符合则转发到路由目的地
- filters:路由过滤器,处理请求或响应
请求先进入网关,由网关根据路由规则判断是否匹配,匹配到了根据服务名去注册中心拉取服务,经过负载均衡规则判断发送到哪个具体的实例上
路由断言工厂Route Predicate Factory
读取路由规则,然后解析成判断条件,对请求做出判断
过滤器有三十多种,具体可以看路由过滤器
针对某个服务的请求头,添加一个请求头信息:
gateway:
routes: # 网关路由配置
- id: user-server #路由id,自定义,唯一就行
# uri,可以写固定地址:http:127.0.0.1:8080
uri: lb://userserver # 路由的目标地址,lb的意思是loadbalancer负载均衡
predicates: # 路由断言,判断请求是否符合规则
- Path=/user/** # 按照路径匹配,只要以/user/开头的请求都符合要求
filters:
- AddRequestHeader=Hello,welcome to userserver!
- id: order-server
uri: lb://orderserver
predicates:
- Path=/order/**
- Before=2031-01-20T17:42:47.789-07:00[America/Denver]
如果是要给所有的服务都添加一个请求头信息:针对所有请求都生效
gateway:
routes: # 网关路由配置
- id: user-server #路由id,自定义,唯一就行
# uri,可以写固定地址:http:127.0.0.1:8080
uri: lb://userserver # 路由的目标地址,lb的意思是loadbalancer负载均衡
predicates: # 路由断言,判断请求是否符合规则
- Path=/user/** # 按照路径匹配,只要以/user/开头的请求都符合要求
- id: order-server
uri: lb://orderserver
predicates:
- Path=/order/**
- Before=2031-01-20T17:42:47.789-07:00[America/Denver]
default-filters:
- AddRequestHeader=Hello,welcome to userserver!
全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样区别在于GatewayFilter通过配置定义,处理逻辑是固定的。而GlobalFilter的逻辑需要自己写代码实现。
作用:
对所有路由都生效的过滤器,可以自定义处理逻辑
实现步骤:
- 实现
GlobalFilter
接口- 添加
@Order()
注解或者实现Ordered
接口- 编写逻辑
请求带authorization=admin才能正确访问
@Component
@Order(-1)
public class AuthorizeFilter implements GlobalFilter {
/**
* 全局过滤器,有处理逻辑的能力,路由过滤器没有处理逻辑的能力
* @param exchange 过滤器上下文,可以获取request跟responed
* @param chain 过滤器链
* @return
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1.获取请求参数
ServerHttpRequest request = exchange.getRequest();
MultiValueMap<String, String> queryParams = request.getQueryParams();
// 2.获取参数中的authorize
String authorization = queryParams.getFirst("authorization");
// 3.判断参数值是否等于admin
if ("admin".equals(authorization)) {
// 4.是,放行
return chain.filter(exchange);
}
// 5.不是,拦截
// 5.1设置状态码
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
// 5.2拦截返回
return exchange.getResponse().setComplete();
}
}
路由过滤器跟默认过滤器底层都是GatewayFilter,而全局过滤器底层是GlobalFilter,通过GatewayFilterAdater适配器最终将GlobalFilter转化成GatewayFilter
跨域问题:浏览器精致请求的发起者与服务端发送跨域ajax请求,请求被浏览器拦截的问题
解决方案:CORS
globalcors: # 全局的跨域处理
add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
corsConfigurations:
'[/**]':
allowedOrigins: # 允许哪些网站的跨域请求
- "http://127.0.0.1:8845"
- "http://127.0.0.1:8846"
- "http://www.leyou.com"
allowedMethods: # 允许的跨域ajax的请求方式
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求中携带的头信息
allowCredentials: true # 是否允许携带cookie
maxAge: 360000 # 这次跨域检测的有效期
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求中携带的头信息
allowCredentials: true # 是否允许携带cookie
maxAge: 360000 # 这次跨域检测的有效期