一、前言
最近在 github 上看了 soul 网关的设计,突然就来了兴趣准备自己从零开始写一个高性能的网关。经过两周时间的开发,我的网关 ship-gate 核心功能基本都已完成,最大的缺陷就是前端功底太差没有管理后台 。
二、设计
2.1 技术选型
网关是所有请求的入口,所以要求有很高的吞吐量,为了实现这点可以使用请求异步化来解决。目前一般有以下两种方案:
- Tomcat/Jetty+NIO+Servlet3
Servlet3 已经支持异步,这种方案使用比较多,京东,有赞和 Zuul,都用的是这种方案。
- Netty+NIO
Netty 为高并发而生,目前唯品会的网关使用这个策略,在唯品会的技术文章中在相同的情况下 Netty 是每秒 30w+的吞吐量,Tomcat 是 13w+,可以看出是有一定的差距的,但是 Netty 需要自己处理 HTTP 协议,这一块比较麻烦。
后面发现 Soul 网关是基于 Spring WebFlux(底层 Netty)的,不用太关心 HTTP 协议的处理,于是决定也用 Spring WebFlux。
网关的第二个特点是具备可扩展性,比如 Netflix Zuul 有 preFilters,postFilters 等在不同的阶段方便处理不同的业务,基于责任链模式将请求进行链式处理即可实现。
在微服务架构下,服务都会进行多实例部署来保证高可用,请求到达网关时,网关需要根据 URL 找到所有可用的实例,这时就需要服务注册和发现功能,即注册中心。
现在流行的注册中心有 Apache 的 Zookeeper 和阿里的 Nacos 两种(consul 有点小众),因为之前写 RPC 框架时已经用过了 Zookeeper,所以这次就选择了 Nacos。
2.2 需求清单
首先要明确目标,即开发一个具备哪些特性的网关,总结下后如下:
- 自定义路由规则
可基于 version 的路由规则设置,路由对象包括 DEFAUL,HEADER 和 QUERY 三种,匹配方式包括=、regex、like 三种。
- 跨语言
HTTP 协议天生跨语言
- 高性能
Netty 本身就是一款高性能的通信框架,同时 server 将一些路由规则等数据缓存到 JVM 内存避免请求 admin 服务。
- 高可用
支持集群模式防止单节点故障,无状态。
- 灰度发布
灰度发布(又名金丝雀发布)是指在黑与白之间,能够平滑过渡的一种发布方式。在其上可以进行 A/B testing,即让一部分用户继续用产品特性 A,一部分用户开始用产品特性 B,如果用户对 B 没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到 B 上面来。通过特性一可以实现。
- 接口鉴权
基于责任链模式,用户开发自己的鉴权插件即可。
- 负载均衡
支持多种负载均衡算法,如随机,轮询,加权轮询等。利用 SPI 机制可以根据配置进行动态加载。