SpringCloudAlibaba实战入门之路由网关Gateway初体验(十)
Spring Cloud 原先整合 Zuul 作为网关组件,Zuul 由 Netflix 公司提供的,现在已经不维护了。后面 Netflix 公司又出来了一个 Zuul2.0 网关,但由于一直没有发布稳定版本,所以 Spring Cloud 等不及了就自己推出一个网关,已经不打算整合 zuul2.0 了。
一、什么是网关
1、顾明思议,网关就是网络的关口。数据在网络间传输,从一个网络传输到另一网络时就需要经过网关来做数据的路由和转发以及数据安全的校验。
2、更通俗的来讲,网关就像是以前园区传达室的大爷。
-
外面的人要想进入园区,必须经过大爷的认可,如果你是不怀好意的人,肯定被直接拦截。
-
外面的人要传话或送信,要找大爷。大爷帮你带给目标人。
3、所谓的API网关,就是指系统的统一入口,它封装了应用程序的内部结构,为客户端提供统一服务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控、路由转发等等。
可以看到,引入 API 网关后,客户端只需要连接 API 网关,由 API 网关根据实际情况进行路由转发,将请求转发到具体的微服务,同时,API 网关会提供认证、授权、限流和监控等功能。
执行流程大体如下:
- Gateway Client 向 Gateway Server 发送请求
- 请求首先会被 HttpWebHandlerAdapter 进行提取组装成网关上下文
- 然后网关的上下文会传递到 DispatcherHandler,它负责将请求分发给 RoutePredicateHandlerMapping
- RoutePredicateHandlerMapping 负责路由查找,并根据路由断言判断路由是否可用
- 如果过断言成功,由 FilteringWebHandler 创建过滤器链并调用
- 请求会一次经过 PreFilter -> 微服务 -> PostFilter 的方法,最终返回响应
二、网关的核心特性
权限控制:网关作为微服务入口,需要校验用户是是否有请求资格,如果没有则进行拦截。
路由和负载均衡:一切请求都必须先经过gateway,但网关不处理业务,而是根据某种规则,把请求转发到某个微服务,这个过程叫做路由。当然路由的目标服务有多个时,还需要做负载均衡。
限流:当请求流量过高时,在网关中按照下流的微服务能够接受的速度来放行请求,避免服务压力过大。
三、Gateway 与 Zuul 的区别
1、Spring Cloud 中的 网关类型
- Gateway
- Zuul
2、两者之间的区别
- Zuul 是基于Servlet 的实现,属于
阻塞式编程,已经被抛弃!
- Spring Cloud Alibaba Gateway 服务网关是基于 Spring5.x 提供的WebFlux,属于
响应式编程
的实现,具备更好的性能。
四、代码入门实例
创建一个网关服务和两个服务提供者,我这里大概如下:
cloud-gateway-1008:是网关服务
cloud-provider-1101:是服务名叫cloud-provider的服务实例1
cloud-provider-1102:是服务名叫cloud-provider的服务实例2
1、复制一个之前的模块重新命名为cloud-gateway-1008,大概结构如下
2、POM文件中增加需要的依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><parent><artifactId>cloud-alibaba</artifactId><groupId>org.example</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloud-gateway-1008</artifactId><name>cloud-gateway-1008</name><url>http://maven.apache.org</url><properties><spring-cloud-openfeign.version>2.0.0.RELEASE</spring-cloud-openfeign.version><spring-cloud-netflix.version>2.0.0.RELEASE</spring-cloud-netflix.version></properties><dependencies><dependency><groupId>org.example</groupId><artifactId>cloud-common</artifactId><version>1.0-SNAPSHOT</version></dependency><!--nacos发现依赖--><dependency><groupId>com.alibaba.cloud </groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--网关--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!--客户端负载均衡loadbalancer--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency></dependencies></project>
3、application.yml中添加相关的路由规则配置
server:port: 1008spring:application:name: cloud-gateway-1008cloud:nacos:discovery:server-addr: 127.0.0.1:8848username: nacospassword: nacosgateway:discovery:locator:enabled: true # gateway 可以从 nacos 发现微服务routes:- id: cloud-provider-1 # 路由id,自定义,只要唯一即可# uri: http://127.0.0.1:1101 # 路由的目标地址 http就是固定地址uri: lb://cloud-provider # 路由的目标地址 lb就是负载均衡,后面跟服务名称predicates: # 路由断言,也就是判断请求是否符合路由规则的条件- Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求- id: cloud-provider-2 # 路由id,自定义,只要唯一即可# uri: http://127.0.0.1:1102 # 路由的目标地址 http就是固定地址uri: lb://cloud-providerpredicates:- Path=/order/**#- Before=2024-12-26T14:20:00.789-07:00[Asia/Shanghai]
id: 路由规则的唯一标识。
uri: 路由的目标地址或者负载均衡服务名称。
predicates: 路由断言,也就是只有当这里的条件满足时候,请求才会被网关转发给目标服务。
predicates:-Path: 只有你的请求地址匹配该路径时候,你的请求才会被网关转发给目标服务。
4、cloud-provider-1101模块
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><parent><artifactId>cloud-alibaba</artifactId><groupId>org.example</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloud-provider-1101</artifactId><name>cloud-provider-1101</name><url>http://maven.apache.org</url><properties><spring-cloud-openfeign.version>2.0.0.RELEASE</spring-cloud-openfeign.version><spring-cloud-netflix.version>2.0.0.RELEASE</spring-cloud-netflix.version></properties><dependencies><dependency><groupId>org.example</groupId><artifactId>cloud-common</artifactId><version>1.0-SNAPSHOT</version></dependency><!-- nacos注册中心 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- nacos配置中心 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId><version>${spring-cloud-openfeign.version}</version></dependency></dependencies></project>
application.yml
server:port: 1101servlet:context-path:spring:application:name: cloud-providercloud:nacos:discovery:server-addr: 127.0.0.1:8848 #注册中心地址
# namespace: public #如果使用的是Nacos的命名空间,需要配置此项
# group: DEFAULT_GROUP #配置分组,默认是DEFAULT_GROUPconfig:import-check:enabled: falseserver-addr: 127.0.0.1:8848 #配置中心file-extension: yaml #配置文件的后缀名,默认是properties
PlayerController.java
package xu.com.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/player")
public class PlayerController {@GetMapping("/{id}")public String getUser(@PathVariable("id") Integer id) {return "Name:" + id;}}
UserController.java
package xu.com.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/user")
public class UserController {@GetMapping("/{id}")public String getUser(@PathVariable("id") Integer id) {return "Name:" + id;}}
5、cloud-provider-1102模块
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><parent><artifactId>cloud-alibaba</artifactId><groupId>org.example</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloud-provider-1102</artifactId><name>cloud-provider-1102</name><url>http://maven.apache.org</url><dependencies><dependency><groupId>org.example</groupId><artifactId>cloud-common</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- nacos注册中心 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- nacos配置中心 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency></dependencies></project>
application.yml
server:port: 1102servlet:context-path:spring:application:name: cloud-providercloud:nacos:discovery:server-addr: 127.0.0.1:8848 #注册中心地址
# namespace: public #如果使用的是Nacos的命名空间,需要配置此项
# group: DEFAULT_GROUP #配置分组,默认是DEFAULT_GROUPconfig:import-check:enabled: falseserver-addr: 127.0.0.1:8848 #配置中心file-extension: yaml #配置文件的后缀名,默认是properties
GoodsController.java
package xu.com.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/goods")
public class GoodsController {@GetMapping("/{id}")public String getOrder(@PathVariable("id") Integer id) {return "Order: " + id;}
}
OrderController.java
6、启动nacos注册中心
7、然后启动下面三个模块cloud-gateway-1008、cloud-provider-1101、cloud-provider-1102
8、启动成功后,我们可以看到nacos中已经出现了我们启动并注册成功的3个服务,因为cloud-provider服务有两个同名,所以下面显示实例数是2
9、我们在浏览器中输入:http://localhost:1008/user/1
注意:我们这里端口是1008,这是网关的端口,网关获得请求后,将符合路由规则的路由请求转发给目标服务,将不符合路由规则的请求直接拦截
我们在浏览器中输入:http://localhost:1008/player/1,因为不符合网关路由规则,所以请求失败。
注意:我们这里端口是1008,这是网关的端口,网关获得请求后,将符合路由规则的路由请求转发给目标服务,将不符合路由规则的请求直接拦截
我们在浏览器中输入:http://localhost:1008/order/2
我们再次在浏览器中输入:http://localhost:1008/goods/2
今天我们初步了解了gateway的基本概念和初步体验,我们下节课将继续深入学习gateway,感谢大家的订阅和学习。