| 学习路线指引(点击解锁) | 知识定位 | 人群定位 |
|---|---|---|
| 李 Python实战微信订餐小程序 李 | 进阶级 | 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。 |
| Python量化交易实战 | 入门级 | 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统 |
在微服务架构中,通常一个系统会被拆分为多个微服务,面对这么多微服务客户端应该如何去调用呢?如果没有其他更优方法,我们只能记录每个微服务对应的地址,分别去调用,但是这样会有很多的问题和潜在因素。
- 客户端多次请求不同的微服务,会增加客户端代码和配置的复杂性,维护成本比价高。
- 认证复杂,每个微服务可能存在不同的认证方式,客户端去调用,要去适配不同的认证,
- 存在跨域的请求,调用链有一定的相对复杂性(防火墙 / 浏览器不友好的协议)。
- 难以重构,随着项目的迭代,可能需要重新划分微服务
为了解决上面的问题,微服务引入了 网关 的概念,网关为微服务架构的系统提供简单、有效且统一的API路由管理,作为系统的统一入口,提供内部服务的路由中转,给客户端提供统一的服务,可以实现一些和业务没有耦合的公用逻辑,主要功能包含认证、鉴权、路由转发、安全策略、防刷、流量控制、监控日志等。
网关在微服务中的位置:
网关对比- Zuul 1.0 : Netflix开源的网关,使用Java开发,基于Servlet架构构建,便于二次开发。因为基于Servlet内部延迟严重,并发场景不友好,一个线程只能处理一次连接请求。
- Zuul 2.0 : 采用Netty实现异步非阻塞编程模型,一个CPU一个线程,能够处理所有的请求和响应,请求响应的生命周期通过事件和回调进行处理,减少线程数量,开销较小
- GateWay : 是Spring Cloud的一个全新的API网关项目,替换Zuul开发的网关服务,基于Spring5.0 + SpringBoot2.0 + WebFlux(基于⾼性能的Reactor模式响应式通信框架Netty,异步⾮阻塞模型)等技术开发,性能高于Zuul
- Nginx+lua : 性能要比上面的强很多,使用Nginx的反向代码和负载均衡实现对API服务器的负载均衡以及高可用,lua作为一款脚本语言,可以编写一些简单的逻辑,但是无法嵌入到微服务架构中
- Kong : 基于OpenResty(Nginx + Lua模块)编写的高可用、易扩展的,性能高效且稳定,支持多个可用插件(限流、鉴权)等,开箱即可用,只支持HTTP协议,且二次开发扩展难,缺乏更易用的管理和配置方式
官方文档:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-starter
Spring Cloud Gateway 是Spring Cloud的一个全新的API网关项目,目的是为了替换掉Zuul1,它基于Spring5.0 + SpringBoot2.0 + WebFlux(基于⾼性能的Reactor模式响应式通信框架Netty,异步⾮阻塞模型)等技术开发,性能⾼于Zuul,官⽅测试,Spring Cloud GateWay是Zuul的1.6倍 ,旨在为微服务架构提供⼀种简单有效的统⼀的API路由管理⽅式。
- 可以与Spring Cloud Discovery Client(如Eureka)、Ribbon、Hystrix等组件配合使用,实现路由转发、负载均衡、熔断、鉴权、路径重写、⽇志监控等
- Gateway还内置了限流过滤器,实现了限流的功能。
- 设计优雅,容易拓展
路由(Route)是GateWay中最基本的组件之一,表示一个具体的路由信息载体,主要由下面几个部分组成:
- id:路由唯一标识,区别于其他的route
- url: 路由指向的目的地URL,客户端请求最终被转发到的微服务
- order: 用于多个Route之间的排序,数值越小越靠前,匹配优先级越高
- predicate:断言的作用是进行条件判断,只有断言为true,才执行路由
- filter: 过滤器用于修改请求和响应信息
核心概念:
- Gateway Client 向 Spring Cloud Gateway 发送请求
- 请求首先会被 HttpWebHandlerAdapter 进行提取组装成网关上下文
- 然后网关的上下文会传递到 DispatcherHandler ,它负责将请求分发给 RoutePredicateHandlerMapping
- RoutePredicateHandlerMapping 负责路由查找,并根据路由断言判断路由是否可用
- 如果过断言成功,由 FilteringWebHandler 创建过滤器链并调用
- 通过特定于请求的 Fliter 链运行请求,Filter 被虚线分隔的原因是Filter可以在发送代理请求之前(pre)和之后(post)运行逻辑
- 执行所有pre过滤器逻辑。然后进行代理请求。发出代理请求后,将运行“post”过滤器逻辑。
- 处理完毕之后将 Response 返回到 Gateway 客户端
Filter过滤器:
- Filter在pre类型的过滤器可以做参数效验、权限效验、流量监控、日志输出、协议转换等。
- Filter在post类型的过滤器可以做响应内容、响应头的修改、日志输出、流量监控等
当用户发出请求达到 GateWay 之后,会通过一些匹配条件,定位到真正的服务节点,并且在这个转发过程前后,进行一些细粒度的控制,其中 Predicate(断言) 是我们的匹配条件,Filter 是一个拦截器,有了这两点,再加上URL,就可以实现一个具体的路由,核心思想:路由转发+执行过滤器链
这个过程就好比考试,我们考试首先要找到对应的考场,我们需要知道考场的地址和名称(id和url),然后我们进入考场之前会有考官查看我们的准考证是否匹配(断言),如果匹配才会进入考场,我们进入考场之后,(路由之前)会进行身份的登记和考试的科目,填写考试信息,当我们考试完成之后(路由之后)会进行签字交卷,走出考场,这个就类似我们的过滤器
Route(路由) :构建网关的基础模块,由ID、目标URL、过滤器等组成
Predicate(断言) :开发人员可以匹配HTTP请求中的内容(请求头和请求参数),如果请求断言匹配贼进行路由
Filter(过滤) :GateWayFilter的实例,使用过滤器,可以在请求被路由之前或者之后对请求进行修改
框架搭建通过上述讲解已经了解了基础概念,我们来动手搭建一个GateWay项目,来看看它到底是如何运行的
新建项目:cloud-alibaba-gateway-9006
版本对应:
GateWay属于SprinigCloud且有web依赖,在我们导入对应依赖时,要注意版本关系,我们这里使用的版本是 2.2.x的版本,所以配合使用的Hoxton.SR5版本
在这里我们要注意的是引入GateWay一定要删除spring-boot-starter-web依赖,否则会有冲突无法启动
父类pom引用:
Hoxton.SR5
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud-gateway-varsion}
pom
import
子类POM引用:
com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery org.springframework.cloud spring-cloud-starter-gateway 2.2.5.RELEASE org.projectlombok lombok
yml配置
server:
port: 9006
spring:
application:
name: cloud-gateway-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
discovery:
locator:
enabled: false #开启注册中心路由功能
routes: # 路由
- id: nacos-provider #路由ID,没有固定要求,但是要保证唯一,建议配合服务名
uri: http://localhost:9001/nacos-provider # 匹配提供服务的路由地址 lb://表示开启负载均衡
predicates: # 断言
- Path=/mxn
@Bean
public RouteLocator gateWayConfigInfo(RouteLocatorBuilder routeLocatorBuilder){
// 构建多个路由routes
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
// 具体路由地址
routes.route("path_mxn",r -> r.path("/mxn
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//获取第一个参数
String id = exchange.getRequest().getQueryParams().getFirst("id");
//打印当前时间
log.info("MyFilter 当前请求时间为:"+new Date());
//判断用户是否存在
if(StringUtils.isEmpty(id)){
log.info("用户名不存在,非法请求!");
//如果username为空,返回状态码为407,需要代理身份验证
exchange.getResponse().setStatusCode(HttpStatus.PROXY_AUTHENTICATION_REQUIRED);
// 后置过滤器
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
当我们访问http://localhost:9006/mxn/nacos-provider/mxn/hello请求,没有携带ID参数,请求失败
当我们访问http://localhost:9006/mxn/nacos-provider/mxn/hello?id=1请求,请求成功
总结到这里我们的GateWay就讲解完了,对于GateWay的核心点主要有三个RoutePredicateFilter,我们搞懂了这三点,基本上对于GateWay的知识就掌握的差不多了,GateWay核心的流程就是:路由转发+执行过滤器链,如果对文中有疑问的小伙伴,欢迎留言讨论。
创作不易,如果文中对你有帮助,记得点赞关注,您的支持是我创作的最大动力。
我是牧小农,怕什么真理无穷,进一步有进一步的欢喜~
点赞再看,养成习惯,微信搜索【牧小农】关注我获取更多资讯,风里雨里,小农等你,很高兴能够成为你的朋友。
项目源码地址:公众号回复 sentinel,即可免费获取源码



