一个超简洁API网关的设计思路

Posted chen陈序猿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个超简洁API网关的设计思路相关的知识,希望对你有一定的参考价值。

API网关对于互联网应用,实在是太重要了,有了API网关,对于微服务来说,将服务治理和安全授权的功能统一放置在API网关处,会减少不少的重复功能的开发量。这不仅提高了整体后台架构的简洁和清晰度,也能让后台更关注业务逻辑,提升代码质量。


无网关架构下的服务调用模式

现在来看一下,如果没有API网关,一些微服务常用功能如何在后台实现:

限流和熔断:

请求签名:

一个超简洁API网关的设计思路

上面的图片表示了整体业务请求签名的全过程,我们可以发现上面的架构存在以下问题:

1,每个接口都需要执行一次与业务无关的合法请求鉴定,多了一次rpc调用。

2,签名逻辑需要每一个业务方参与,不仅繁琐,且及其容易出错。

3,消息扩散风暴:签名认证服务的并发量是其他业务的总和。

黑白名单:

很多时候,我们有以下需求:鉴定到某ip发生的请求为恶意请求,比如利用系统漏洞薅羊毛,我们想针对此服务将其ip封禁,如果每一个服务都有这样的需求,我们就需要重复开发类似的黑名单功能,造成代码互相拷贝。


实际上,重复的功能在每一个服务重复开发,最大的问题是不可控,会造成整个后台系统架构的加速腐败:你不能保证每一个使用者都能正确的使用了SDK从而不发生差错。

网关架构下的服务调用模式

网关架构下的服务调用模式:

一个超简洁API网关的设计思路

API网关专为重复逻辑而生,只在入口统一解决限流,熔断,认证,请求签名验签,黑白名单等功能。http负载均衡,http请求转dubbo请求等请求协议转换功能。

一个争议:

网关只在请求入口处做对外约束还是内部服务调用也通过API网关转发?比如内部服务每一个服务仍然都保留熔断功能。

笔者认为,网关只限制入口处请求就可以了,如果内部服务调用也通过API网关,因为多个rpc调用连起来一起成功才能保证数据的完整性,在没有可靠的分布式事务解决方案出现之前,如果熔断了多个写请求的某一个步骤,会导致错误的数据产生。(两个系统的数据对不上)另外一个问题就是增加了系统的复杂性,网关系统反而变的臃肿,所以不建议对内部调用做网关层转发。

好了,说明了搭建API网关系统的好处,下面简述一下如何设计一个比较简洁的API网关。

API网关需要保证哪些要求

一,无状态,可以平滑扩容。

二,高性能,可以承载海量并发。

三,易扩展,可以轻松实现组件的扩展。

四,动态化,各项配置皆可动态配置,免重启实时生效。


下面就以笔者自研API网关 easy-gateway说一下整个网关中间件的设计思路。(下附架构图)

一个超简洁API网关的设计思路

一个超简洁API网关的设计思路

--geteway-core:网关的控制逻辑实现。

--geteway-service:网关的启动配置和业务逻辑实现。(组件逻辑)

--gateway-common:网关的公共依赖。

--gateway-admin:网关可配置管理控制台。(未实现)

--zip: 配置中心模版zip,网关建库脚本,war.zip为网关熔断所使用组件hystrix的面板web程序。


网关采用Netty框架的NIO通讯模型来保证Http请求的高性能处理,但是也保证了你可以随时更新其他的HTTP实现。

一个超简洁API网关的设计思路

httpService接口作为了web容器的可扩展接口,内置了基于Netty的高性能实现。

一个超简洁API网关的设计思路

wapper包封装了与具体http容器无关的request和response模型。它本身是一个抽象类,每一个http容器负责继承requestwapper将自己的实现映射到通用模型上,例如,Netty有Netty的requestWapper,servlet容器则有servlet的wapper。这使得程序更加面向对象。

一个超简洁API网关的设计思路


getWayExecutor作为网关执行器,用于执行一系列的前置后置运行时处理器。

一个超简洁API网关的设计思路

HandlerContext则为网关一次执行的上下文,用于在各种组件中通过Handler获取通用请求模型对象和API,以及在调用成功后的后置组件获取响应对象。

一个超简洁API网关的设计思路

PostHandler和PreHandler以及RuntimeHandler则是开发的对网关插件扩展的接口,用于处理对请求的拦截。

RouteInvocation则为最终的路由组件,用于将请求发送到对端的http服务或者dubbo服务。

一个超简洁API网关的设计思路

exception包为网关异常,以及网关异常执行组件ExceptionHander,在网关程序处理发生异常时,会调用ExceptionHandler做请求返回。

一个超简洁API网关的设计思路

invocation包则封装了rest和rest转dubbo调用的逻辑:

一个超简洁API网关的设计思路


以上则为网关核心组件抽象层的基本叙述。下图是完成一次调用的整个流程,即为GateWayExecutor的控制逻辑:

一个超简洁API网关的设计思路

不妨看一下NettyHandler的逻辑:

一个超简洁API网关的设计思路

让我们看一下gateway-service中的业务逻辑,实际上就是实现了一系列的Handler,例如,黑名单组件:

一个超简洁API网关的设计思路

easyGateWay如何实现网关的各项要求

一,无状态,可以平滑扩容

实际上网关是有状态的,内存cache里存储了网关的各项组件配置。但是zookeeper可以同步多节点之间的状态,而且网关的配置本身就可以允许最终一致性。因此,前台架设一台nginx即可轻松实现平滑扩容。

二,高性能,可以承载海量并发。

高性能是靠以下能力保证:

1,可以随时扩容

2,采用高性能网络编程框架Netty实现NIO非阻塞请求通讯。

3,网关弱依赖db,配置更新机制如下:mysql更新以后,zookeeper通知各节点去数据库重新获取最新的网关组件配置。

4,使用Hystrix对异常请求进行熔断,使用信号量隔离机制和自建线程池实现超时控制。相关代码逻辑如下:

一个超简洁API网关的设计思路

一个超简洁API网关的设计思路

实际上,为了避免Handler组件代码异常本身耗时造成整个网关系统的不可用。我们可以不直接使用Netty本身的工作线程池,而且像Dubbo一样维护一个专门的业务线程池,业务线程池阻塞不影响Netty本身处理请求的性能。


三,易扩展,可以轻松实现组件的扩展。


网关面向扩展开放的原则,你可以随便编写PreHandler,RuntimeHandler和PostHandler的实现类来在请求调用前/调用时/调用中完成自己的个性化网关逻辑。


四,动态化,各项配置皆可动态配置,免重启实时生效。


基于zookeeper的配置中心机制和内存池监听机制来实时同步配置,一切的东西都是动态的。

总结

以上,就是easy-gateway的API网关能力相关介绍

未来可能会实现基于SPI机制的扩展行为自动发现功能。

github: https://github.com/chenhaiyangs/easy-gateway 

另外安利笔者的TCC分布式事务实现框架:

github: https://github.com/chenhaiyangs/rpc-tcc-transaction

(完)

chen陈序猿|一起学技术吧

微信ID:echo_陈

以上是关于一个超简洁API网关的设计思路的主要内容,如果未能解决你的问题,请参考以下文章

亿级流量架构网关设计思路,常用网关对比,写得太好了。。

7个点5 种 API 网关技术选型,yyds

5G+煤矿智能化-煤矿专用5G智能工业网关设计思路

5G+煤矿智能化-煤矿专用5G智能工业网关设计思路

日均处理请求超600亿次的云时代架构设计思路

旷视张祥雨:神经网络架构设计新思路