如何开发业务网关?

2022-08-25 14:08:46 浏览数 (1)

微服务架构中网关层属于业务方能处理用户请求的第一层,网关设计是否合理直接影响到整个系统的稳定性、吞吐量和安全性。基于微服务架构的分层原则,我们尽量在网关层处理整个系统的通用业务逻辑,网关层尽可能的“薄”一些。

合理的业务网关设计都应该包含哪些功能呢?接下来我们一起讨论一下如何设计一个合理的业务网关。

OpenResty、Kong、Zuul 等开源网关通常被称为流量网关,文中讨论的业务网关更加贴近业务层,在实际场景中可以根据公司的业务规模和业务形态选择把流量网关和业务网关合二为一或者分别开发。下文中我们说的网关默认指业务网关。

场景分析

通过上图我们可以看到,网关处在连接网络请求和业务服务的中间位置,起到了承上启下的作用。 网关最先接收到所有的网络请求。一个实例创建的连接数是有限的,处理能力也是有限的,所以当请求量超过一个网关实例的负载时,网关必须能快速的新增实例,也就是我们常说的扩容。要实现这一特性就需要实例是无状态的。

当一个请求到达网关时,网关需要根据请求的协议类型进行承接。然后根据以下内容判断请求是否需要继续处理。

  1. 是否符合浏览器的同源策略。
  2. 域名是否在白名单/黑名单中。
  3. IP是否在白名单/黑名单中。
  4. 是否符合其它安全策略。
  5. 是否为爬虫。

前面的考验通过后,我们给当前请求生成唯一标识

接下来需要解析请求的Header信息,然后检查请求内容是否完整、是否达到了限流的临界值。下一步,根据Header对请求进行鉴权,同时给请求生成会话(Session)。

然后就是网关服务的核心逻辑:请求转发。根据请求Header的参数及负载均衡策略把请求转发给业务服务。针对不同的业务场景,一些场景通用的逻辑也可以在服务转发的前后实现。

我们以时序图的形式梳理下上面的流程,方便理解:

关键技术点

逐一分析下网关层涉及的关键技术点:无状态、IP黑白名单、生成唯一ID、负载均衡、转发策略。

无状态

没有状态的服务才更容易做到快速伸缩。为了保证网关的无状态我们不能在内存中存储有状态的数据,比如Session信息。Session信息记录着用户的登录状态,如果我们把Session存储在一个实例的内存中,当请求发送到另外一个实例时,就获取不到用户的登录信息了,需要用户重新登录,这显然是不合理的。常用的解决方案有两种:

  1. 把Session存储在客户端,每次请求时携带Session信息。
  2. 把Session存储在服务端的外部存储(Redis)中。这就保证了服务是无状态的。

如果能把每一个Session信息同步到所有的网关实例中,也可以保证网关无状态,不过这种方式成本太高,不是优雅的解决方案,实际场景中不会使用。

IP黑白名单

当数据量比较小的时候,我们把需要过滤的黑白名单加载到内存中,根据规则查找即可。但是当配置信息很庞大时,数据直接加载到内存中是不可行的,此时可以采用外部存储比如Redis。如果我们对配置信息依次查找的话,平均时间复杂度就是O(n),很浪费性能,此时可以考虑布隆过滤器布谷鸟过滤器先做一层筛选,提升查找效率。

生成唯一ID

常用的几种方法UUID、NanoID、依赖Redis/MySQL等三方存储生成、Snowflake。其中UUID、NanoID是无法保证生成ID顺序的,当需要ID有序时优先考虑Snowflake算法。在高并发场景下为了提升ID生成效率可以采用预生成的策略。

负载均衡

网关通常支持的负载均衡算法有:轮询、随机、加权轮询、Hash(根据原地址/其它配置信息)、一致性Hash、最少链接。开发网关时,我们需要提供能力让用户通过配置选择合适的负载均衡策略。

转发策略

业务网关的转发策略通常不用向流量网关那么灵活(比如Nginx的转发策略支持非常灵活的配置方式),适配业务规则,够用就好。如果要支持正则表达式配置的话一定要注意配置权限的控制和对每一个正则表达式的检查,防止意外引发线上故障。

总结

不同公司对网关的拆分方式不太一样,根据我的工作经验,绝大多数公司会把网关拆分为通用的流量网关个性化的业务网关,各业务统一接入流量网关,各自实现自己的业务网关。

本文我们主要讨论了开发业务网关常见的问题及实现方式,总体讲述的比较笼统。以上纯属个人观点,如有不同意见欢迎私信交流。

0 人点赞