一、什么是网关:
在微服务架构里,每一个微服务都是一个个体,各个服务可以被独立的设计、开发、测试、部署和管理。这时,各个独立部署单元可以用不同的开发测试团队维护,可以使用不同的编程语言和技术平台进行设计,这就要求必须使用一种语言和平 台无关的服务协议作为各个单元间的通讯方式,此时出现了网关。
网关主要用于对应用层即具体业务的控制,还有一种我们之前常用的nginx是流量层网关,虽然都具有负载均衡等功能,但是使用的场景不同,nginx用于网页架构,网关用于对具体业务的,通常来讲业务层的网关Gataway调用后与nginx网页层。
主要功能:
- 对用户请求做身份认证、权限校验
- 将用户请求路由到微服务,并实现负载均衡
- 对用户请求做限流
二 、SpringCloud配置网关:
1、添加依赖:
因为网关也是一个服务,所以依然要添加到nacos里,所以我们需要先创建一个模块,然后对其进行配置。
<!--网关依赖-->
<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>
2、注册ncaos,并进行配置:
predicates的参数有多种,可以进行时间、路由规则、参数等,下文以路由规则为例。
server:
port: 10010 # 网关端口
spring:
application:
name: gateway # 服务名称
cloud:
nacos:
server-addr: localhost:8848 # nacos地址
gateway: # 配置网关要拦截的服务
routes: # 网关路由配置1
- id: user-service # 路由id,自定义,只要唯一即可
# uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
- Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求
routes: # 网关路由配置2
- id: order-service
# uri: http://127.0.0.1:8082
uri: lb://orderservice
predicates:
- Path=/order/**
三、路由过滤器:
对发来的请求进行过滤,然后将返回的结果同时也进行过滤
一)过滤器:
1、filters路由过滤器:
针对某一个特定的路由:
spring:
cloud:
gateway:
routes: # 网关路由配置
- id: user-service
uri: lb://userservice
predicates:
- Path=/user/**
filters: # 过滤器
- AddRequestHeader=Truth, Itcast is freaking awesome! # 添加请求头
2、default-filters默认过滤器:
针对上面的所有路由
spring:
application:
name: gateway # 服务名称
cloud:
nacos:
server-addr: localhost:8848 # nacos地址
gateway:
routes: # 网关路由配置
- id: user-service
uri: lb://userservice
predicates:
- Path=/user/**
- id: order-service
uri: lb://orderservice
predicates:
- Path=/order/**
default-filters: # 默认过滤器,会对所有的路由请求都生效
- AddRequestHeader=Truth, Itcast is freaking awesome! # 添加请求头
二)全局过滤器:
上面的是使用系统自带的过滤器,但是现在我们有自己的业务需求,所以需要编写自己的过滤器,所以需要全局过滤器。
主要是书写一个类,然后实现接口即可
public interface GlobalFilter {
/**
* 处理当前请求,有必要的话通过{@link GatewayFilterChain}将请求交给下一个过滤器处理
*
* @param exchange 请求上下文,里面可以获取Request、Response等信息
* @param chain 用来把请求委托给下一个过滤器
* @return {@code Mono<Void>} 返回标示当前过滤器业务结束
*/
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
实现:
下以一个简单的登录为例,如果用户的请求中携带一个参数名为authorization的变量,且值为admin,则放行,否则进行拦截
@Order(-1) //值越小,过滤等级越高,当有多个拦截器时,值小的先执行
@Component //将过滤器注入到容器中
public class AuthorizeFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1.获取请求参数
MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
// 2.获取authorization参数
String auth = params.getFirst(“authorization”);
// 3.校验
if (“admin”.equals(auth)) {
// 放行
return chain.filter(exchange);
}
// 4.拦截
// 4.1.禁止访问 401状态码
exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
// 4.2.结束处理
return exchange.getResponse().setComplete();
}
}
三)过滤器的执行顺序:
1、在路由和默认过滤器中,先声明的order值小,后声明的值大,先执行先声明的。先后顺序即order值。
上图中路由过滤器和默认过滤器按123执行
2、当三者过滤器的order值相同时,按照 defaultFilter > 路由过滤器 > GlobalFilter 的顺序执行。
四、跨域问题:
网关处理跨域采用的同样是CORS方案,并且只需要简单配置即可实现:
spring:
cloud:
gateway:
# 。。。
globalcors: # 全局的跨域处理
add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
corsConfigurations:
'[/**]':
allowedOrigins: # 允许哪些网站的跨域请求
- "http://localhost:8090"
- "http://www.leyou.com"
allowedMethods: # 允许的跨域ajax的请求方式
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求中携带的头信息
allowCredentials: true # 是否允许携带cookie
maxAge: 360000 # 这次跨域检测的有效期