SpringCloud Alibaba 微服务 — 微服务网关 Gateway

一、Spring Cloud Gateway 简介

Spring Cloud Gateway 是 Spring 官方基于 Spring 5.x、Spring Boot 2.x、Spring WebFlux 和 Reactor 等技术开发的响应式的、异步非阻塞式的 API 网关。支持 websockets,和Spring 框架紧密集成。底层使用netty模型,性能极高。旨在为微服务架构提供简单、有效且统一的 API 路由管理方式。Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Netflix Zuul 1.x。Spring Cloud Gateway 其不仅提供统一的路由方式,并且还基于 Filter 链的方式提供了网关基本的功能,例如:熔断、重试、安全、监控 / 指标、限流等

Spring Cloud Gateway 里明确的区分了 Router 和 Filter,并且一个很大的特点是内置了非常多的开箱即用功能,并且都可以通过 SpringBoot 配置或者手工编码链式调用来使用。
比如内置了 10 种 Router,使得我们可以直接配置一下就可以随心所欲的根据 Header、或者 Path、或者 Host、或者 Query 来做路由。比如区分了一般的 Filter 和全局 Filter,内置了 20 种 Filter 和 9 种全局 Filter,也都可以直接用。当然自定义 Filter 也非常方便。

API 网关

网关的角色是作为一个 API 架构,用来保护、增强和控制对于 API 服务的访问。
API 网关是一个处于应用程序或服务(提供 REST API 接口服务)之前的系统,用来管理授权、访问控制和流量限制等,这样 REST API 接口服务就被 API 网关保护起来,对所有的调用者透明。因此,隐藏在 API 网关后面的业务系统就可以专注于创建和管理服务,而不用去处理这些策略性的基础设施。
在这里插入图片描述

API 网关的职能

在这里插入图片描述

API 网关的分类与功能

在这里插入图片描述

Spring Cloud Gateway 的核心原理

Spring Cloud Gateway 的核心处理流程如下图所示:
① Gateway 的客户端会向 Spring Cloud Gateway 发起请求,请求首先会被 HttpWebHandlerAdapter 进行提取组装成网关的上下文;
② 然后网关的上下文会传递给 DispatcherHandler,这里的 DispatcherHandler 是所有请求的分发处理器,DispatcherHandler 主要负责分发请求到对应的处理器,比如将请求分发到对应 RoutePredicateHandlerMapping(路由断言处理映射器)。
③ 路由断言处理映射器主要用于路由的查找,以及找到路由后返回对应的 FilteringWebHandler。
④ FilteringWebHandler 主要负责组装 Filter 链表并调用 Filter 执行一系列的 Filter 处理,然后把请求转到后端对应的代理服务处理,处理完毕之后,将 Response 返回到 Gateway 客户端。在 Filter 链中,通过虚线分割 Filter 的原因是,过滤器可以在转发请求之前处理或者接收到被代理服务的返回结果之后处理。所有的 Pre 类型的 Filter 执行完毕之后,才会转发请求到被代理的服务处理。被代理的服务把所有请求处理完毕之后,才会执行 Post 类型的过滤器。
值得一提的是,在配置路由的时候,如果不指定端口的话,HTTP 默认设置端口为 80,HTTPS 默认设置端口为 443,Spring Cloud Gateway 的启动容器目前只支持 Netty。
在这里插入图片描述

Spring Cloud Gateway 由 Route(路由)、Predicate(断言)、Filter(过滤器) 三大核心组件组成:
在这里插入图片描述

简单的项目架构图

在这里插入图片描述

二、Spring Cloud Gateway 的使用

项目中新建模块 alibaba-gateway,然后配置 alibaba-server-consumer、alibaba-server-hellocloud 和 alibaba-server-helloworld 的路由。
在这里插入图片描述

1、添加依赖

	<dependencies>
      <!--gateway 依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
         <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>      
    </dependencies>

特别注意:
Spring Cloud Gateway 是基于 WebFlux 的,它与 Spring MVC 是不兼容的,如果引用了 spring-boot-starter-web,则需要把 spring-webmvc 排除掉
由于 Spring Cloud Gateway 的启动容器目前只支持 Netty,因此还需要将 spring-boot-starter-tomcat 排除掉。这里也可以引入 spring-boot-starter-webflux 来替代 Spring MVC 的功能,关于 Gateway 的使用,原则上只需要引入 spring-cloud-starter-gateway 即可

	 <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
        	<exclusions>
           		<exclusion>
              		<groupId>org.springframework</groupId>
             		<artifactId>spring-webmvc</artifactId>
           		</exclusion>
        		<exclusion>
         			<groupId>org.springframework.boot</groupId>
  					 <artifactId>spring-boot-starter-tomcat</artifactId>
				 </exclusion>
			</exclusions>
	</dependency>

2、配置文件

创建 application.yml 文件,配置项目。

server:
  port: 5000

spring:
  application:
    name: cloud-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        group: HD-GROUP

3、网关配置跨域

(1)配置文件方式

在 application.yml 中通过配置网关来控制 CORS 行为

spring:   
	cloud:
    	gateway:
      		globalcors:
        		cors-configurations:     # CORS 跨域配置
        	  		'[/**]':
           	 			allowedOrigins: "https://docs.spring.io"     # 允许跨域访问的域名
             			allowedMethods:							     # 允许跨域访问的方法
            				- GET 

(2)Java 配置类方式

新建 CorsConfigution.java 文件,内容如下:

org.springframework.context.annotation.Configuration; import
org.springframework.web.cors.CorsConfiguration; import
org.springframework.web.cors.reactive.CorsWebFilter; import
org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.util.pattern.PathPatternParser;


@Configuration public class CorsConfigution {

    @Bean
    public CorsWebFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
        source.registerCorsConfiguration("/**", buildConfig());
        return new CorsWebFilter( source);
    }

    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        //在生产环境上最好指定域名,以免产生跨域安全问题
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.setAllowCredentials(true);
        return corsConfiguration;
    }
   } 

4、网关配置路由

路由是构建网关的基本模块,它由 ID,目标URI,一系列的断言和过滤器组成。如果断言为 true (请求与断言相匹配)则匹配该路由。
路由分为静态路由和动态路由:静态路由的目标 URL 被写死,动态路由的目标 URL 由目标服务名获得。

断言进行匹配的种类:

断言 Predicate 进行匹配的几种方式:
1)通过请求路径匹配 :Path Route Predicate 接收一个匹配路径的参数来判断是否走路由。

spring:
 cloud:
   gateway:
     routes:
     	- id: host_route
       	  uri: http://localhost:8006
       	  predicates:
       		- Path=/hello/lhj/**

2)通过 Host 匹配 :Host Route Predicate 接收一组参数,一组匹配的域名列表,这个模板是一个 ant 分隔的模板,用.号作为分隔符。它通过参数中的主机地址作为匹配规则。

spring:
 cloud:
   gateway:
     routes:
     	- id: host_route
       	  uri: http://ityouknow.com
       	  predicates:
       		- Host=**.ityouknow.com

3)通过请求方式匹配 :可以通过是 POST、GET、PUT、DELETE 等不同的请求方式来进行路由。

spring:
 cloud:
   gateway:
     routes:
     	- id: method_route
       	  uri: http://ityouknow.com
       	  predicates:
       		- Method=GET

4)通过请求参数匹配 :Query Route Predicate 支持传入两个参数,一个是属性名一个为属性值,属性值可以是正则表达式。

spring:
 cloud:
   gateway:
     routes:
     	- id: query_route
       	  uri: http://ityouknow.com
       	  predicates:
       	    - Query=smile

5)通过请求 ip 地址进行匹配 :Predicate 也支持通过设置某个 ip 区间号段的请求才会路由,RemoteAddr Route Predicate 接受 cidr 符号 (IPv4 或 IPv6) 字符串的列表(最小大小为 1),例如 192.168.0.1/16 (其中 192.168.0.1 是 IP 地址,16 是子网掩码)。

spring:
 cloud:
   gateway:
     routes:
     	- id: remoteaddr_route
       	  uri: http://ityouknow.com
       	  predicates:
       		- RemoteAddr=192.168.1.1/24

6)通过 Cookie 匹配 :Cookie Route Predicate 可以接收两个参数,一个是 Cookie name , 一个是正则表达式,路由规则会通过获取对应的 Cookie name 值和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行。

spring:
 cloud:
   gateway:
     routes:
      	- id: cookie_route
          uri: http://ityouknow.com
          predicates:
        	- Cookie=ityouknow, kee.e

7)通过时间匹配 :Predicate 支持设置一个时间,在请求进行转发的时候,可以通过判断在这个时间之前或者之后进行转发。

spring:   
  cloud:
    gateway:
      routes:
       	- id: time_route
          uri: http://ityouknow.com
          predicates:
            - After=2018-01-20T06:06:06+08:00[Asia/Shanghai] 

在这里插入图片描述

(1) 静态路由

1)在 application.yml 配置文件中配置路由,根据断言来决定是否进行匹配路由

server:   
	port: 5000 
spring:   
	application:
    	name: cloud-gateway   
    cloud:
   	    # 配置nacos   	
    	nacos:
      		discovery:
        		server-addr: 127.0.0.1:8848
        		group: HD-GROUP
        		ip: localhost    
   	    # 配置gateway    
    	gateway:
      		discovery:
        		locator:
          			enabled: true  	# 开启注册中心路由功能
      		# 配置路由
     		 routes:
        		- id: hello_world			# id 必须唯一,且与配置类中定义的id相同(建议与服务名相匹配)
          		  uri: http://localhost:8006		# 匹配后提供的路由地址
          		  predicates:		# 断言,决定是否进行路由匹配
            		- Path=/helloworld/**		# 路径相匹配的进行路由
            
        		- id: hello_cloud			# 配置多个路由时用“-”隔开
          		  uri: http://localhost:8007
          		  predicates:		
            		- Path=/hellocloud/** 

2)GatewayConfig 配置类配置路由具体信息

@Configuration public class GatewayConfig {
    @Bean
    public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder) {
        
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        routes.route("hello_world", r -> r.path("/helloworld/**").uri("http://localhost:8006")).build();
        routes.route("hello_cloud", r -> r.path("/hellocloud/**").uri("http://localhost:8007")).build(); 		
        return routes.build();
    }
  } 

(2)动态路由

在静态路由中,我们的地址完全写死了,而且也只写了一台机器,为了解决这个问题,我们需要配置动态路由。动态路由用微服务名进行路由

1)在 application.yml 配置文件中配置路由,根据断言来决定是否进行匹配路由

server:   
	port: 5000 
spring:
   application:
    name: cloud-gateway
   cloud:
    # 配置nacos
   	nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        group: HD-GROUP
        ip: localhost     
    # 配置gateway    
    gateway:
      discovery:
        locator:
          enabled: true  	# 开启注册中心路由功能
      routes:
      	- id: hello_world  		# 没有固定的规则但是要求唯一,建议配合服务名
          uri: lb://alibaba-server-helloworld 		# 匹配后提供的路由地址
          predicates:
          	- Path=/helloworld/**  		# 断言,路径相匹配的进行路由
       
       - id: hello_cloud 
          uri: lb://alibaba-server-hellocloud 
          predicates:
          	- Path=/hellocloud/**   

2)GatewayConfig 配置类配置路由具体信息

@Configuration public class GatewayConfig {

    @Bean
    public RouteLocator routeLocator(RouteLocatorBuilder builder) {
    
    	 RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
         routes.route("hello_world", r -> r.path("/helloworld/**").uri("lb://alibaba-server-helloworld")).build();
         routes.route("hello_cloud", r -> r.path("/hellocloud/**").uri("lb://alibaba-server-hellocloud")).build();
		
         return routes.build();      
   } 

注意:这里的 ”uri: lb://“ 中的 lb 代表的意思是 loadbalance 也就是负载均衡的意思

通过配置路由后,访问 http://localhost:5000/helloworld/lhj 即可访问到 http://localhost:8006/helloworld/lhj 服务下的 /helloworld/lhj 下的方法;访问 http://localhost:5000/hellocloud/lhj 即可访问到 http://localhost:8007/hellocloud/lhj 服务下的 /hellocloud/lhj 下的方法。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值