“灵魂拷问
分布式系统需要统一的网关吗?
网关会带来哪些优势?
引入网关会带来灾难吗?
分布式系统的设计大体上分为中心化和非中心化,像现在流行的微服务模式,本质上是把各种业务拆分为独立的进程来实现业务的扩展性。伴随着业务的不断被拆分,整体的系统性能也有所提高,但是系统又往往面临着中心化的需求,这个世界就是这么有趣,我们不但要非中心化的优势,还要保证中心化的优势。
统一的需求
说到非中心化需求,最简单最常见的就是鉴权,简单来说就是判断用户是否有执行某种动作的权限。以鉴权为例,当有N个微服务有同样的鉴权需求的时候,有以下几种解决方案:
每个服务自己实现一遍
写一个公共的服务接口,每个服务都调用这个接口
写到统一的流量入口处,只需要实现一次
有人说第一种方案没人用,是吗?在服务数量不是太多的情况下,据我所知有很多公司初期都是每个服务都实现自己的鉴权,不要说这种做法一无是处,首先在各个团队技术栈不同的情况下,这是一个团队可以快速实现功能的一种解决方案,而且不依赖于任何其他服务,这意味着这个服务不会受到别的服务的影响,这体现的是非中心化最核心的价值之一。
至于第二种解决方案是典型的集中式处理的方案之一,他按照业务功能把鉴权独立成单独的服务,所有使用鉴权服务的系统都依赖于这个服务,所以这个统一的鉴权服务需要保证高可用,而且对性能比较敏感,稍有不慎,流量高峰就有可能对整个系统造成致命打击。但是,还是有不少公司在用这种架构模式,你说奇怪不奇怪,正所谓,存在即合理。
至于第三种使用网关模式,可以说是目前市面上文章吹捧最多的解决方案。当然得到广大程序员的吹捧自然有它的优势,但是请记住,它并非没有劣势。
从上图清晰的可以看到,来自于客户端的所有流量都经过网关,所以理论上来讲,所有统一化的需求都可以在网关进行实现,这样每个后端的业务服务代码都不会有任何的侵入性。至于这些需求最常见的有:
网关可以屏蔽后端服务的协议细节,比如有的服务可能采用的rpc方式,有的服务采用的restful方式,有的甚至可能采用的比较古老的web Service,在网关这一层我们可以统一通信协议,这样客户端调用起来会方便很多。
可以统一整个系统的认证和授权功能,甚至可以统一不同的客户端采用的不同认证方式,比如Cookie认证,Session认证等。
可以统一设置后端服务的保护策略,比如:不同的服务可以设置不同的白名单系统,不同的服务可以采用不同的限流策略等。
在网关这个统一的入口,更容易做日志的收集工作。
虽然网关很香,但是一旦整个系统引入网关,就会随之带来一些问题:
增加了网关,在请求的整个过程中就至少多了一层转发,性能会有稍微下降。
网关如果出现问题,降造成整个系统不稳定,甚至down机,这就是网关的单点问题。所以一般网关都会有多个节点。
如何引入网关
在没有网关的时候,系统一般都会有一个无状态的web层,这一层的主要作用是根据业务组织后端服务结果来响应客户端的请求,例如:一个订单详情的请求,web层会同时请求订单服务来查询订单信息,请求用户服务来查询下单人信息,请求商户服务来查询商家信息,然后把这些信息组合成客户端想要的数据格式,然后返回客户端数据。
如果做鉴权,限流等操作,同样也是做在这个web层,在引入了网关之后,这个web层到底还要不要呢?不同的公司有不同的做法,不过我还是建议保留web层,用它来做服务的聚合层,这样整体架构就变成了这样
网关和负载均衡
通过以上阐述可以看到,网关在部署架构上和负载均衡器很像,但是它们其实是两种东西。虽然它们都会承载统一的入口流量,但是负载均衡器只是单纯的对请求的转发,而网关除了对请求的转发之外,更重要的职责是统一的业务处理,就像鉴权,限流,降级等。
所以从功能角度来说,网关几乎可以代替负载均衡器。
写在最后
你的系统是否需要网关不仅仅要看系统的需求,还要看公司的整体技术运维能力,毕竟一旦引入网关,它对技术上的要求比较高,而且对高可用和性能比较敏感。但是网关对于那些统一化的需求有着天然的优势,无论是鉴权,还是服务的治理,所以很多公司引入了网关。无论是采用自建还是开源来实现网关,我们都要考虑它的扩展性。现在比较流行的网关有:Kong,Zuul,Tyk 等,详细信息可以参见它们的官网。