来源:developer.aliyun.com/article/889271
本文准备围绕七个点来讲网关,分别是网关的基本概念、网关设计思路、网关设计重点、流量网关、业务网关、常见网关对比,对基础概念熟悉的朋友可以根据目录查看自己感兴趣的部分。
什么是网关
网关,很多地方将网关比如成门, 没什么问题, 但是需要区分网关与网桥的区别,
网桥 工作在数据链路层,在不同或相同类型的LAN之间存储并转发数据帧,必要时进行链路层上的协议转换。可连接两个或多个网络,在其中传送信息包。
网关 是一个大概念,不具体特指一类产品,只要连接两个不同的网络都可以叫网关,网桥一般只转发信息,而网关可能进行包装。
网关通俗理解
根据网关的特性,举个例子:
假如你要去找集团老板(这儿只是举个例子), 大家都知道老板肯定不是谁想见就能见的, 也怕坏人嘛, 那么你去老板所在的办公楼,假如是集团总部, 大楼这个门就充当了网关的角色, 大门一般都有看门员 ,看门员会做哪些事情呢?
首先所有想见老板的人肯定都得从这个门进(统一入口 ), 这个门相当于将办公室和外界隔离了,主要为了保护里面的安全以及正常工作, 来到这个门之后, 门卫肯定会让你出示相关证件(鉴权检验 ), 意思就是判断你要见老板这个请求是否合理, 如果不合理直接就拒绝了, 让你回家等消息 , 如果鉴权之后, 发现你找老板其实只是为了和他谈谈两元店的生意, 门卫会跟你说这个用不着找老板, 你去集团投资部就行了(动态路由 , 将请求路由到不同的后端集群中), 此时会对你进行一些包装 ,例如给你出具一个访问证类似的,然后告诉你路该怎么走,等等。
你看看,网关的作用是不是就是这三个, 最终目的就是减少你与集团的耦合,具体到计算机上就是减少客户端与服务端的耦合,如果没有网关意味着所有请求都会直接调用服务器上的资源,这样耦合太强了,服务器出了问题,客户端会直接报错, 例如老板换工作的地方了,如果没有网关你直接去原来的地方找, 肯定会被告知老板不在这儿。
为什么需要网关
当使用单体应用程序架构时,客户端(Web 或移动端)通过向后端应用程序发起一次 REST 调用来获取数据。负载均衡器将请求路由给 N 个相同的应用程序实例中的一个。然后应用程序会查询各种数据库表,并将响应返回给客户端。微服务架构下,单体应用被切割成多个微服务,如果将所有的微服务直接对外暴露,势必会出现安全方面的各种问题,另外内外耦合严重。
客户端可以直接向每个微服务发送请求,其问题主要如下:
网关与服务器集群
回到我们服务器上,下面图介绍了网关(Gateway)作用,可知 Gateway 方式下的架构,可以细到为每一个服务的实例配置一个自己的 Gateway,也可以粗到为一组服务配置一个,甚至可以粗到为整个架构配置一个接入的 Gateway。于是,整个系统架构的复杂度就会变得简单可控起来。
这张图展示了一个多层 Gateway 架构,其中有一个总的 Gateway 接入所有的流量(流量网关 ),并分发给不同的子系统,还有第二级 Gateway 用于做各个子系统的接入 Gateway(业务网关 )。可以看到,网关所管理的服务粒度可粗可细。通过网关,我们可以把分布式架构组织成一个星型架构,由网络对服务的请求进行路由和分发。下面来聊聊好的网关应该具备哪些功能,也就是网关设计模式。
网关设计思路
如果你想系统学习最新的基于 Spring Cloud Gateway 的微服务,建议你报名栈长的《Spring Cloud 微服务课程》,一次订阅,永久免费提供更新。
一个网关需要有以下的功能:
1. 请求路由
网关一定要有请求路由的功能。这样一来,对于调用端来说,也是一件非常方便的事情。因为调用端不需要知道自己需要用到的其它服务的地址,全部统一地交给 Gateway 来处理。
2. 服务注册
为了能够代理后面的服务,并把请求路由到正确的位置上,网关应该有服务注册功能,也就是后端的服务实例可以把其提供服务的地址注册、取消注册。一般来说,注册也就是注册一些 API 接口。比如,HTTP 的 Restful 请求,可以注册相应 API 的 URI、方法、HTTP 头。这样,Gateway 就可以根据接收到的请求中的信息来决定路由到哪一个后端的服务上。
3. 负载均衡
因为一个网关可以接收多个服务实例,所以网关还需要在各个对等的服务实例上做负载均衡策略。简单点就是直接 Round-Robin 轮询,复杂点的可以设置上权重进行分发,再复杂一点还可以做到 session 粘连。
4. 弹力设计
网关还可以把弹力设计中的那些异步、重试、幂等、流控、熔断、监视等都可以实现进去。这样,同样可以像 Service Mesh 那样,让应用服务只关心自己的业务逻辑(或是说数据面上的事)而不是控制逻辑(控制面)。
5. 安全方面
SSL 加密及证书管理、Session 验证、授权、数据校验,以及对请求源进行恶意攻击的防范。错误处理越靠前的位置就是越好,所以,网关可以做到一个全站的接入组件来对后端的服务进行保护。当然,网关还可以做更多更有趣的事情,比如:灰度发布、API聚合、API编排。
灰度发布
网关完全可以做到对相同服务不同版本的实例进行导流,还可以收集相关的数据。这样对于软件质量的提升,甚至产品试错都有非常积极的意义。
API 聚合
使用网关可以将多个单独请求聚合成一个请求。在微服务体系的架构中,因为服务变小了,所以一个明显的问题是,客户端可能需要多次请求才能得到所有的数据。这样一来,客户端与后端之间的频繁通信会对应用程序的性能和规模产生非常不利的影响。于是,我们可以让网关来帮客户端请求多个后端的服务(有些场景下完全可以并发请求),然后把后端服务的响应结果拼装起来,回传给客户端(当然,这个过程也可以做成异步的,但这需要客户端的配合)。
API 编排
同样在微服务的架构下,要走完一个完整的业务流程,我们需要调用一系列 API,就像一种工作流一样,这个事完全可以通过网页来编排这个业务流程。我们可能通过一个 DSL 来定义和编排不同的 API,也可以通过像 AWS Lambda 服务那样的方式来串联不同的 API。
网关设计重点
网关设计重点主要是三个, 高性能、高可用、高扩展:
1. 高性能
在技术设计上,网关不应该也不能成为性能的瓶颈。对于高性能,最好使用高性能的编程语言来实现,如 C、C++、Go 和 Java。网关对后端的请求,以及对前端的请求的服务一定要使用异步非阻塞的 I/O 来确保后端延迟不会导致应用程序中出现性能问题。C 和 C++ 可以参看 Linux 下的 epoll 和 Windows 的 I/O Completion Port 的异步 IO 模型,Java 下如 Netty、Spring Reactor 的 NIO 框架。
2. 高可用
因为所有的流量或调用经过网关,所以网关必须成为一个高可用的技术组件,它的稳定直接关系到了所有服务的稳定。网关如果没有设计,就会成变一个单点故障。因此,一个好的网关至少要做到以下几点。
集群化 。网关要成为一个集群,其最好可以自己组成一个集群,并可以自己同步集群数据,而不需要依赖于一个第三方系统来同步数据。
服务化 。网关还需要做到在不间断的情况下修改配置,一种是像 Nginx reload 配置那样,可以做到不停服务,另一种是最好做到服务化。也就是说,得要有自己的 Admin API 来在运行时修改自己的配置。
持续化 。比如重启,就是像 Nginx 那样优雅地重启。有一个主管请求分发的主进程。当我们需要重启时,新的请求被分配到新的进程中,而老的进程处理完正在处理的请求后就退出。
3. 高扩展
因为网关需要承接所有的业务流量和请求,所以一定会有或多或少的业务逻辑。而我们都知道,业务逻辑是多变和不确定的。比如,需要在网关上加入一些和业务相关的东西。因此,一个好的 Gateway 还需要是可以扩展的,并能进行二次开发的。当然,像 Nginx 那样通过 Module 进行二次开发的固然可以。
另外,在运维方面 ,网关应该有以下几个设计原则。
业务松耦合,协议紧耦合 。在业务设计上,网关不应与后面的服务之间形成服务耦合,也不应该有业务逻辑。网关应该是在网络应用层上的组件,不应该处理通讯协议体,只应该解析和处理通讯协议头。另外,除了服务发现外,网关不应该有第三方服务的依赖。
应用监视,提供分析数据 。网关上需要考虑应用性能的监控,除了有相应后端服务的高可用的统计之外,还需要使用 Tracing ID 实施分布式链路跟踪,并统计好一定时间内每个 API 的吞吐量、响应时间和返回码,以便启动弹力设计中的相应策略。
用弹力设计保护后端服务 。网关上一定要实现熔断、限流、重试和超时等弹力设计。如果一个或多个服务调用花费的时间过长,那么可接受超时并返回一部分数据,或是返回一个网关里的缓存的上一次成功请求的数据。你可以考虑一下这样的设计。
DevOps 。因为网关这个组件太关键了,所以需要 DevOps 这样的东西,将其发生故障的概率降到最低。这个软件需要经过精良的测试,包括功能和性能的测试,还有浸泡测试。还需要有一系列自动化运维的管控工具。