SpringCloud之Gateway(统一网关)

文章目录


前言

网关功能(对整个微服务起保护作用):

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

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

  • gateway
  • zuul

两种的性能对比:

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


一、搭建网关服务

1、导入依赖

xml 复制代码
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
        <!--nacos服务发现依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
         </dependency>

2、在application.yml中写配置

xml 复制代码
server:
  port: 10010
spring:
  application:
    name: gateway
  cloud:
    nacos:
      server-addr: localhost:8848 #nacos地址
    gateway:
      routes:
        - id: user-service #路由标示,必须唯一
         # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址【路由地址配置的第一种模式】
          uri: lb://userservice #路由的目标地址【路由地址配置的第二种模式】【lb:loadBalance】
          predicates: #路由断言(布尔表达式),判断请求是否符合规则
            - Path=/user/** #路径断言,判断路径是否是以/user开头,如果是则符合
        - id: order-service
          uri: lb://orderservice
          predicates:
            - Path=/order/**

配置包括:

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

二、路由断言工厂Route Predicate Factory

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

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

官网断言工厂的地址:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories

三、路由过滤器 GatewayFilter

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

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

官网地址:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories

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

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

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

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

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

xml 复制代码
server:
  port: 10010
logging:
  level:
    cn.itcast: debug
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS
spring:
  application:
    name: gateway
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos地址
      discovery:
#        namespace: 48f42a9a-ed33-4b61-a2b1-dfa248a7e6a7 #dev环境
    gateway:
      routes: # 网关路由配置
        - id: user-service # 路由标示,必须唯一
          uri: lb://userservice # 路由的目标地址
          predicates: # 路由断言,判断请求是否符合规则
            - Path=/user/** # 路径断言,判断路径是否是以/user开头,如果是则符合
        - id: order-service
          uri: lb://orderservice
          predicates:
            - Path=/order/**
      default-filters:
        - AddRequestHeader=Truth,Itcast is freaking awesome!

总结

四、全局过滤器 GlobalFilter

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

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

定义方式是实现GlobalFilter接口。

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

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

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

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

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

步骤1:自定义过滤器

自定义类,实现GlobalFilter接口,添加@Order注解:

xml 复制代码
@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.禁止访问        
			exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);        
		// 4.2.结束处理        
			return exchange.getResponse().setComplete();    
	}
}

总结

五、过滤器执行顺序

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

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

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

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

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

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

总结

六、跨域问题处理

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

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

解决方案:CORS

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

xml 复制代码
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 # 这次跨域检测的有效期

总结


总结

以上就是SpringCloud之Gateway(统一网关)的相关知识,希望对你有所帮助。

积跬步以至千里,积怠惰以至深渊。时代在这跟着你一起努力哦!

相关推荐
来杯@Java5 小时前
图书管理系统(基于springboot+vue前后端分离的项目)计算机毕业设计java
java·spring boot·spring·vue·毕业设计·mybatis·课程设计
卷毛的技术笔记6 小时前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
半旧夜夏9 小时前
【保姆级】微服务组件环境搭建(Docker Compose版)
java·linux·spring cloud·微服务·云原生·容器
云烟成雨TD10 小时前
Spring AI 1.x 系列【33】RAG Advisor 组件与四大分层架构
java·人工智能·spring
J2虾虾11 小时前
Spring AI Alibaba - Tools
服务器·人工智能·spring
J2虾虾13 小时前
Spring AI Alibaba - 人工介入(Human-in-the-Loop)
java·人工智能·spring
J2虾虾13 小时前
Spring AI Alibaba - Skills 技能
人工智能·python·spring
J2虾虾16 小时前
Spring AI Alibaba - 智能体作为工具(Agent Tool)
java·人工智能·spring
Devin~Y16 小时前
从内容社区到AIGC客服:Spring Boot、Redis、Kafka、K8s、RAG的三轮大厂Java面试对话(附标准答案)
java·spring boot·redis·spring cloud·kafka·kubernetes·micrometer
J2虾虾16 小时前
Spring AI Alibaba - 记忆管理(Memory)
人工智能·windows·spring