前言
这一篇文章算是补充把,之前的Spring Cloud Gateway 是以Eureka为注册中心进行整合的,见《服务网关Gateway》,现在讲一下Spring Cloud Gateway 和Nacos的整合,该文章只介绍了Gateway和Nacos整合部分,请结合《服务网关Gateway》一起看你的收获会更大
1.Spring Cloud Gateway 认识
Zuul是Netflix的开源项目,Spring Cloud将其收纳成为自己的一个子组件。zuul用的是多线程阻塞模型,它本质上就是一个同步 Servlet,这样的模型比较简单,他都问题是多线程之间上下文切换是有开销的,线程越多开销就越大。线程池数量固定意味着能力接受的请求数固定,当后台请求变慢,面对大量的请求,线程池中的线程容易被耗尽,后续的请求会被拒绝。
在Zuul 2.0中它采用了 Netty 实现异步非阻塞编程模型,异步非阻塞模式对线程的消耗比较少,对线程上线文切换的消耗也比较小,并且可以接受更多的请求。它的问题就是线程模型比较复杂,要求深究底层原理需要花一些功夫。
Spring Cloud Gateway是Spring Cloud自己的产物,基于Spring 5 和Spring Boot 2.0 开发,Spring Cloud Gateway的出现是为了代替zuul,在Spring Cloud 高版本中没有对zuul 2.0进行集成,SpringCloud Gateway使用了高性能的Reactor模式通信框架Netty。
Spring Cloud Gateway 的目标,不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。
所以说其实Gateway和zuul 2.0差别不是特别大,都是采用Netty高性能通信框架,性能都挺不错。
1.2.Spring Cloud Gataway的特点
在Spring Cloud官方定义了SpringCloud Gateway 的如下特点:
- 基于 Spring 5,Project Reactor , Spring Boot 2.0
- 默认集成 Hystrix 断路器
- 默认集成 Spring Cloud DiscoveryClient
- Predicates 和 Filters 作用于特定路由,易于编写的 Predicates 和 Filters
- 支持动态路由、限流、路径重写
1.3.Spring Cloud Gataway的核心概念
Spring Cloud Gataway有几个核心组成:
- Filter(过滤器):
Spring Cloud Gateway的Filter和Zuul的过滤器类似,可以在请求发出前后进行一些业务上的处理 ,这里分为两种类型的Filter,分别是Gateway Filter网关filter和Global Filter全局Filter, 他们的区别在后续会讲到。
- Route(路由):
网关配置的基本组成模块,和Zuul的路由配置模块类似。一个Route模块由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配,目标URI会被访问。说白了就是把url请求路由到对应的资源(服务),或者说是一个请求过来Gateway应该怎么把这个请求转发给下游的微服务,转发给谁。
- Predicate(断言):
这是一个 Java 8 的 Predicate,可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。断言的输入类型是一个 ServerWebExchange。简单理解就是处理HTTP请求的匹配规则,在什么样的请情况下才能命中资源继续访问。
1.3.Spring Cloud Gateway的工作方式:
Spring Cloud Gateway 的工作原理跟 Zuul 的差不多,最大的区别就是 Gateway 的 Filter 只有 pre 和 post 两种,下面是官方的执行流程图:
客户端向Spring Cloud Gateway发出请求。如果网关处理程序映射确定请求与路由匹配,则将其发送到网关Web处理程序。该处理程序通过特定于请求的过滤器链来运行请求。筛选器由虚线分隔的原因是,筛选器可以在发送代理请求之前和之后运行逻辑。所有“前置”过滤器逻辑均被执行。然后发出代理请求。发出代理请求后,将运行“后”过滤器逻辑。
2. Spring Cloud Gataway入门
2.1.创建工程导入依赖
工程名:springcloud-gateway-server-1110 ,导入gataway基础依赖
<!--1.管理SpringBoot的依赖--><parent><groupId> org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.13.RELEASE</version></parent><!-- springcloud和alibaba依赖声明 --><dependencyManagement><dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${alibaba.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><!--网关--><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></dependency></dependencies>
【注意】这里不需要导入spring-boot-start-web包,在gateway依赖中已经有了
2.2.主配置类
通过 @EnableDiscoveryClient 注解启用服务发现功能
//服务注册与发现publicclassGatewayServerApplication1110 { publicstaticvoidmain(String[] args) { SpringApplication.run(GatewayServerApplication1110 .class); } }
2.3.yml配置
这里主要配置:服务信息 ,注册中心地址 ,路由配置 ,跨域几块内容:
server port1000spring application name service-gateway cloud nacos discovery server-addr 127.0.0.1 8848 #Nacos注册中心地址 gateway discovery locator enabled false #开放服务名访问方式 lower-case-service-id true #服务名小写 routesid service-user #指定服务名 uri lb //service-user #去注册中心找这个服务名 predicates#断言,匹配访问的路径#服务访问路径 Path=/user/** filters#请求转发的时候会去掉 /user访问路径 StripPrefix=1 id service-course #指定服务名 uri lb //service-course #去注册中心找这个服务名 predicates#断言,匹配访问的路径#服务访问路径 Path=/course/** filters#请求转发的时候会去掉 /user访问路径 StripPrefix=1 globalcors#跨域配置 cors-configurations '[/**]' allowedOrigins"http://127.0.0.1:8081"#允许跨域"http://127.0.0.1:8082" allow-credentialstrue allowed-headers"*" allowedMethods GET POST DELETE PUT PATCH OPTIONS HEAD CONNECT TRACE
这里除了要注册到Eureak以外,还需要配置Gataway的路由
spring.cloud.nacos.discovery.server-addr
:是Nacos注册中心地址,见:《服务注册与发现Nacos》spring.cloud.gateway.discovery.locator.enabled=false
: 不开放服务名访问方式spring.cloud.gateway.discovery.locator.lower-case-service-id: true
忽略服务名大小写,大写小写都可以匹配spring.cloud.gateway.routes.id
: 指定了路由的服务名,可以自己定义spring.cloud.gateway.routes.uri=lb://user-server
: 去注册中心找服务,采用负载均衡的方式请求。其实就是找要调用的服务。spring.cloud.gateway.routes.predicates
: 断言,这里使用的Path=/user/**,即匹配访问的路径如果匹配/user/就可以将请求路由(分发)到user-server这个服务上。spring.cloud.gateway.routes.filters
:这里使用StripPrefix=1主要是处理前缀 /user ,访问目标服务的时候会去掉前缀访问。这个需要根据url情况来定义。
2.5.访问测试
启动注册中心,启动用户服务,启动网关访问:http://localhost:1110/user/user/1
,请求将会打到用户服务上,并返回用户数据。