TOC
网关和BFF是如何演化出来的
-
接入
- 网关即Gateway,是整个微服务的集中入口,是实现前后分离的关键
- 网关的可编程性对微服务的升级及部署灵活性非常重要
- 所以需要设计一款轻量级的可编程网关,以应对不断变化的业务需求
-
网关和BFF(Backend For Frontend)的演化进程
-
MyShop SOA V1,2011年左右
- 外网:浏览器 -> Nginx:反向代理+负载均衡 -> 服务端web应用 -> 微服务:认证、用户、购物车、商品、支付
-
MyShop SOA V2,2012年,移动端发展
- 移动端 -> Nginx -> 微服务
- 浏览器 -> Nginx -> 服务端web应用 -> 微服务
-
MyShop SOA V2.5,移动端添加无线BFF层
- 移动端 -> Nginx -> 无线BFF -> 微服务
- 浏览器 -> Nginx -> 服务端web应用 -> 微服务
-
MyShop SOA V3,移动端添加无线网关层
- 移动端 -> Nginx -> 无线网关 -> 无线BFF -> 微服务
- 浏览器 -> Nginx -> 服务端web应用 -> 微服务
-
MyShop SOA V4,统一网关层
- 用户体验层 -> 网关层 -> BFF层 -> 微服务层
- 用户体验层:第三方应用、H5前后分离应用、无线应用、浏览器
- 网关层:开放平台网关、H5网关、无线网关、Web应用网关
- BFF层:开放平台BFF层、H5 BFF层、无线BFF层、服务器端Web应用
- 微服务层
-
网关(Gateway)和反向代理(Reverse Proxy)是什么关系
-
Web1.0/2.0时代,应用以web网站形式呈现
- 前置反向代理,作用是返乡路由和负载均衡,也承担安全认证、日志监控、限流熔断、缓存等功能
- 产品有Nginx、HAProxy
- 网站升级频率不高,反向代理采用静态配置方式,由运维团队单独配置
-
Web3.0/微服务时代
- 应用形态出现了提供大量api的服务,api的升级更新频率很高,对路由、安全的动态配置能力要求很高
- 出现的矛盾
- 传统反向代理的静态配置不灵活,缺乏动态配置能力
- 传统运维配置方式效率低效,研发无法做到自助配置
- API Gateway作为补充因运而生
- API Gateway和反向代理功能大同小异,不过是主要面向api和微服务,提供更灵活的、可供研发自助配置的动态配置能力
- 产品有Netflix Zuul
- 网关和反向代理共存,运维成本高
-
云原生时代
- 对服务灵活升级有更高的要求,需要灰度、金丝雀、蓝绿部署等,对网关不仅要求可动态配置,而且要求可动态编程
- 网关和动态代理融合的趋势:面向云原生的统一代理,或称统一网关
- 产品有envoy、Traefik,是云原生组织CNCF(Cloud Native Computing Foundation)推荐的产品
网关需要分集群部署吗
-
反向代理 + 网关部署架构
- 架构:共存
- API流量 -> 网关(可按不同api场景分集群部署) -> 微服务
- 网页流量 -> 反向代理 -> 单页应用 + Web应用
- 分析
- 部署架构相对复杂,需维护两套体系
- 如果网关和反向代理不在同一个域,还要解决跨域问题
- 适合业务和团队规模大,应用场景多的场合
- 架构:共存
-
统一网关部署架构
- 架构:统一
- 流量 -> 统一网关 -> 微服务 + 单页应用 + Web应用
- 分析
- 所有应用可统一部署,没有跨域问题,只要应用和微服务都在同一个根域下
- API和Web/SPA场景有一些差异化需求,如:对网关统一错误处理,web错误需展示错误页面,api错误提供错误消息;认证方式差异;对于差异,统一网关不易区分,需要在网关层添加区分逻辑
- 架构:统一
-
统一网关 + 分集群部署架构
- 网关层
- 开放平台网关 + H5网关 + 无线网关 + Web应用网关
- 网关层
Faraday网关(自研)内核设计
-
设计
- 核心
- ReverseProxyFilter,是一个Servlet Filter
- 组件
- 路由解析器
接收到http请求时,取出其中的host域名信息,通过查询路由映射表找到对应的目标服务,包括服务名、地址和其他配置,然后将请求交由下个环节进行处理
- 路由映射表
网关关键。常见路由方式有:基于域名的路由、基于请求path的路由、基于Http头请求参数的路由等。此处采用基于域名的路由,路由映射表存储的是Http的Host头和service之间的映射关系。表可静态配置,如使用本地文件配置,也可动态配置,如从服务注册表里动态获取并定期更新。动态配置需要对接Eureka、Zookeeper或Consul这种服务发现的产品
- HttpClient映射表
存储service服务和实际访问该服务的HttpClient的映射关系,这个映射关系是基于路由表信息构建,根据路由表更新而更新;采用提前加载(eager loading)的机制。在网关初始化和后续路由表异步更新时,提前初始化每个服务所使用的httpClient,这样实际访问服务时,就可以重用已经创建好的httpClient,不需要再按需创建,从而提升服务访问的性能
- 请求转发器
负责转发请求的组件,当获得请求和目标服务的信息,通过查询httpClient映射表找到对应的httpClient,就可以通过httpClient将请求转发到目标服务,并接收服务产生的响应,并最终将响应返回给调用方。如果网关启用了LB的能力,请求转发还要根据一定规则计算出实际要访问的服务实例的地址,再进行转发。若使用K8s,则无需开启LB,因K8s已经支持服务发现和负载均衡的能力
- 请求截获器
可以在请求上添加必要的http header,认证鉴权,日志监控等等,扩展网关能力
- 响应截获器
可以在响应上添加必要的http header,认证鉴权,日志监控等等,扩展网关能力
- 核心
-
静态路由配置
- 举例:本地开发环境的静态路由配置
- 路由名称 + 主机头 + 对应目标服务的地址
- 目标服务可以是域名、ip列表
- 路由配置还可包括超时配置等信息
- 举例:本地开发环境的静态路由配置
Faraday网关代码解析
- MappingsProvider
- 路由映射表实现的超类
- 主要方法:resolveMapping(),updateMappings()
- 子类:ConfigurationMappingsProvider通过读取配置文件方式、ProgrammaticMappingProvider通过可编程方式
- HttpClientProvider
- HttpClient映射表的实现
- 主要方法:updateHttpClients(),getHttpClient()
- ReverseProxyFilter
- 主流程,继承自OncePerRequestFilter
- 主方法:doFilterInternal(request, response, filterChain)
- RequestForwarder
- 请求转发器
- 主方法:forwardHTTPRequest()
生产级网关需要考虑哪些环节(生产扩展点)
-
限流熔断:集成resilience4j或hystrix
-
动态路由和负载均衡:集成eureka
-
基于Path的路由,如api.xxx.com/pathx
-
截获器链
-
日志采集和Metrics埋点
-
响应流优化
主流开源网关
支持公司 | 实现语言 | 亮点 | 不足 | |
---|---|---|---|---|
Nginx (2004) | Nginx Inc | C/Lua | 高性能,成熟稳定 | 门槛高,扁运维,可编程弱 |
Kong (2014) | Kong Inc | OpenResty/Lua | 高性能,可编程API | 门槛较高 |
Zuul1 (2012) | Netflix/Pivotal | Java | 成熟,简单门槛低 | 性能一般,可编程一般 |
Spring Cloud Gateway (2016) | Pivotal | Java | 异步,配置灵活 | 早期产品 |
Envoy (2016) | Lyft | C++ | 高性能,可编程API/ServiceMesh集成 | 门槛较高 |
Traefik (2015) | Containous | Golang | 云原生,可编程API/对接各种服务发现 | 生产案例不多 |
「真诚赞赏,手留余香」
真诚赞赏,手留余香
使用微信扫描二维码完成支付
