【微服务】八. 统一网关gateway

8.1 网关作用介绍

网关功能:

  • 身份认证和权限校验
  • 服务路由、负载均衡
  • 请求限流

网关的技术实现

在SpringCloud中网关的实现包括两种:

  • gateway
  • zuul
    Zuul是基于Servlet的实现,属于阻塞式编程。而SpringCloudGateway则是基于Spring5中提供的WebFlux,属于响应式编程的实现,具备更好的性能。

总结

网关的作用

  • 对用户请求做身份认证、权限验证
  • 将用户请求路由到微服务,并实现负载均衡
  • 对用户请求做限流

8.2 搭建网关服务

搭建网关服务的步骤:

  1. 创建新的module,引入SpringCloudGateway的依赖和nacos的发现服务依赖
xml 复制代码
<!--网关依赖-->
<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>
  1. 编写路由配置及nacos地址
yaml 复制代码
server:
	port: 10010 # 网关端口
spring:
	application:
		name: gateway  # 服务名称
	cloud:
    	nacos:
    		server-addr: localhost:8848  # nacos地址
    	gateway:
        	routes:  # 网关路由配置
        	 	- id: user-service # 路由id,自定义,只要唯一即可
        			# uri: http://127.0.0.1:8081  #路由的目标地址,http就是固定地址
        			uri: lb://userservice  # 路由的目标地址 lb就是负载均衡,后面跟服务名称
        			predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
        				- Path=/user/**  # 这个是按照路径匹配,只要以/user/开头就符合要求
        		-id: order-service
        			uri: lb://orderservice
        			predicates:
        				- Path=/order/**

"-"代表集合,会有很多个

配置完之后,访问localhost:10010/order/...就可以访问到订单服务 换成user就可以访问到用户服务

路由过程:

总结

网关搭建步骤:

  1. 创建项目,引入nacos服务发现和gateway依赖
  2. 配置application.yaml,包括服务基本信息、nacos地址、路由

路由配置包括:

  1. 路由id:路由的唯一标示
  2. 路由目标(uri):路由的目标地址,http代表固定地址,lb代表根据服务名负载均衡
  3. 路由断言(predicates):判断请求是否符合要求,符合则转发到路由目的地
  4. 路由过滤器(filter):对请求或响应做处理

8.3 路由断言工厂 Route Predicate Factory

  • 我们在配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变为路由判断的条件
  • 例如Path=/user/**是按照路径匹配,这个规则是由org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类来处理的
  • 像这样的断言工厂在springCloudGateway还有十几个

Spring提供了11种基本的Predicate工厂:

可以在官方文档查看使用方式

总结

PredicateFactory的作用是什么?

读取用户定义的断言条件,对请求做出判断

Path=/user/**是什么含义?

路径是以/user开头的就认为是符合的

8.4 路由的过滤器配置

路由过滤器 GatewayFilter

GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应做处理:

过滤器工厂GatewayFilterFactory

Spring提供了31种不同的路由过滤器工厂。例如:

案例:给所有进入userservice的请求添加一个请求头

给所有进入userservice的请求添加一个请求头:Truth=itcast is freaking awesome!

实现方式:在gateway中修改application.yml文件,给userservice的路由添加过滤器:

yaml 复制代码
spring:
	cloud:
		gateway:
			routes: # 网关路由配置
				- id: user-service
					uri: lb://userservice
					predicates:
						- Path=/user/**
					filters: #过滤器
                    	-AddRequstHeader=Truth, Itcast is freaking awesome! #添加请求头

,逗号前代表key,逗号后代表value

如何查看添加请求头是否生效:在userservice的接口上添加参数,调用接口查看日志

默认过滤器:

如果要对所有的路由都生效,则可以将过滤器工厂写到default下。格式如下:

总结

过滤器的作用是什么?

  • 对路由的请求或响应做加工处理,比如添加请求头
  • 配置在路由下的过滤器只对当前路由的请求生效

defaultFilters的作用是什么?

对所有路由都生效的过滤器

8.5 ### 全局过滤器 GlobalFilter

全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与GatewayFilter一样。

区别在于GatewayFilter通过配置定义,处理逻辑是固定的。而GlobalFilter的逻辑需要自己写代码实现。

定义方式是实现GlobalFilter接口

java 复制代码
public interface GlobalFiter {
    /**
    * 处理当前请求,有必要的话通过{@link GatewayFilterChain}将请求交给下一个过滤器处理
    
    exchange 请求上下文,里面可以获取Request、Response等信息
    chain  用来把请求委托给下一个过滤器
    
    {@code Momo<Void>} 返回标示当前过滤器业务结束
    **/
    Momo<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}

案例:定义全局过滤器,拦截并判断用户身份

需求:定义全局过滤器,拦截请求,判断请求的参数是否满足下面条件:

  • 参数中是否有authorization
  • authorization参数值是否为admin

如果同时满足则放行,否则拦截

实现:

java 复制代码
@Order(-1)   // 实现顺序方法二
@Component
public class AuthorizeFilter implements GlobalFilter, Ordered{
    @Override
     Momo<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain){
         // 1. 获取请求参数
         ServerHttpRequest request = exchange.getRequest();
         MultiValueMap<String, String> params = request.getQueryParams();
         // 2. 获取参数中的 authorization参数
         Spring auth = params.getFirst("authorization");
         // 3. 判断参数值是否等于admin
         if("admin".equals(auth)){
             // 4. 是,放行
             return chain.filter(exchange);
         }
         // 5. 否,拦截
         // 5.1 设置状态码
         exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
         // 5.2 拦截请求
         return exchange.getResponse().setComplete();
     }
    
    // 添加顺序方法一:Ordered  实现ordered
    public int getOrder(){
        return -1;  // -1优先级高   优先级从小到大,数字越小越优先
    }

}

总结:

全局过滤器的作用是什么?

对所有路由都生效的过滤器,并且可以自定义处理逻辑

实现全局过滤器的步骤?

  • 实现GlobalFilter接口
  • 添加@Order注解或实现Orderd接口
  • 编写处理逻辑

8.6 过滤器链执行顺序

请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter

请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter,合并到一个过滤器链(集合中),排序后依次执行每个过滤器

  • 每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前。
  • GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定order值,由我们自己指定
  • 路由过滤器和defaultFilter的order由Spring指定,默认是按照声明顺序从1递增
  • 当过滤器的order值一样时,会按照defaultFilter>路由过滤器>GlobalFilter的顺序执行。

可以参考下面几个类的源码来查看:

java 复制代码
org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters()方法是先加载defaultFilters,然后再加载某个route的filters,然后合并。

org.springframework.cloud.gateway.handler.FilteringWebHandler#handle()方法会加载全局过滤器,与前面的过滤器合并后根据order排序,组织过滤器链
    

总结

路由过滤器、defaultFilter、全局过滤器的执行顺序?

order值越小,优先级越高

当order值一样时,顺序是defaultFilter最先,然后是局部的路由过滤器,最后是全局过滤器

8.7 网关的cors跨域配置

跨越问题处理

跨域:域名不一致就是跨域,主要包括:

跨域问题:浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题

解决方案:CORS

网关处理跨域采用的同样是CORS方案,并且只需要简单配置即可实现:

yaml 复制代码
spring:
	cloud:
		gateway:
			globalcors:  #全局的跨域处理
				add-to-simple-url-handler-mapping: true  # 解决options请求被拦截问题
				crosConfigurations:
					'[/**]':
						allowedOrigins: # 允许哪些网站的跨域请求
							- "http://localhost:8090"
							- "http://www.leyou.com"
						allowedMethods:  # 允许的跨域ajax的请求方式
                        	- "GET"
                        	- "POST"
                        	- "DELETE"
                       		- "PUT"
                       		- "OPTIONS"
                       	allowedHeaders: "*"  # 允许在请求中携带的头信息
                       	allowCredentials: true  # 是否允许携带cookie
                       	maxAge: 360000 # 这次跨域检测的有效期

有效期范围内浏览器将不再发送请求,而是直接通过

总结

CORS跨域要配置的参数包括哪几个?

  • 允许哪些域名跨域
  • 允许哪些请求头
  • 允许哪些请求方式
  • 是否允许使用cookie
  • 有效期是多久
相关推荐
米丘2 天前
微前端之 Web Components 完全指南
微服务·html
霸道流氓气质4 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
霸道流氓气质5 天前
Spring Boot 微服务性能优化完全指南
spring boot·微服务·性能优化
地瓜伯伯5 天前
从MESI缓存一致性协议讲透synchronized的底层
java·spring boot·spring·spring cloud·微服务·springcloud
Devin~Y5 天前
大厂 Java 面试实录:从音视频内容社区到 AI RAG 的全链路技术设计
java·spring boot·redis·spring cloud·微服务·kafka·音视频
递归尽头是星辰5 天前
AI 访问数据仓库:从直连到微服务化
数据仓库·人工智能·微服务·dataagent·ai数据治理
Hadoop_Liang5 天前
使用Kubernetes Gateway API实现域名访问应用
容器·kubernetes·gateway
就改了5 天前
Windows 环境 SkyWalking 完整实操教程
windows·微服务·skywalking
worilb5 天前
Spring Cloud 学习与实践(9):Gateway + JWT 统一鉴权
学习·spring cloud·gateway
至乐活着6 天前
Docker Compose多服务编排实战:从零搭建Node.js+MySQL+Redis全栈应用
docker·微服务·devops·容器编排·compose