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(统一网关)的相关知识,希望对你有所帮助。

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

相关推荐
暮乘白帝过重山12 分钟前
Singleton和Prototype的作用域与饿汉式/懒汉式的初始化方式
spring·原型模式·prototype·饿汉式·singleton·懒汉式
ejinxian42 分钟前
Spring AI Alibaba 快速开发生成式 Java AI 应用
java·人工智能·spring
杉之1 小时前
SpringBlade 数据库字段的自动填充
java·笔记·学习·spring·tomcat
圈圈编码1 小时前
Spring Task 定时任务
java·前端·spring
爱的叹息1 小时前
Java 连接 Redis 的驱动(Jedis、Lettuce、Redisson、Spring Data Redis)分类及对比
java·redis·spring
松韬2 小时前
Spring + Redisson:从 0 到 1 搭建高可用分布式缓存系统
java·redis·分布式·spring·缓存
天上掉下来个程小白2 小时前
Redis-14.在Java中操作Redis-Spring Data Redis使用方式-操作列表类型的数据
java·redis·spring·springboot·苍穹外卖
汤姆大聪明3 小时前
Redisson 操作 Redis Stream 消息队列详解及实战案例
redis·spring·缓存·maven
正经摸鱼5 小时前
classpath与classpath*实现逻辑
后端·spring
良枫5 小时前
Spring Security认证授权深度解析
spring boot·spring