网关是什么?

网关(Gateway)是转发其他服务器通信数据的服务器,接收从客户端发送来的请求时,它就像自己拥有资源的源服务器一样对请求进行处理。API网关也是随着对传统庞大的单体应用(All in one)拆分为众多的微服务(Microservice)以后,所引入的统一通信管理系统。用于运行在外部http请求与内部rpc服务之间的一个流量入口,实现对外部请求的协议转换参数校验鉴权切量熔断限流监控风控等各类共性的通用服务。

之前的做法都是在RPC服务之上在开发一个对应的WEB服务,WEB服务可以想象成Spring MVC的服务,在Spring MVC的工程中调用RPC服务,最终提供HTTP接口给到应用中来使用。

网关架构设计

如果希望实现一个能支撑百亿级吞吐量的网关,那么它就应该是按照分布式架构思维做去中心化设计,支持横向扩展。让每一台网关服务都成为一个算力,把不同的微服务RPC接口,按照权重策略计算动态分配到各个算力组中,做到分布式运算的能力。

要把网关的通信模块、管理服务、SDK、注册中心、运营平台等依次分开单独开发实现,这样才能进行独立的组合包装使用。就像官网的通信不应该一开始就把 Netty 相关的服务全部绑定到 Spring 容器,这样即增加了维护成本,也降低了系统的扩展性。

https://gitcode.net/KnowledgePlanet/gateway/api-gateway-core/-/tree/master

整个API网关设计的核心内容可以分为以下五块:

通信协议处理:这是API网关最基本的功能,需要使用NIO框架如Netty来处理HTTP请求,并进行协议转换和泛化调用到RPC服务,然后将返回的数据信息返回给客户端。

注册中心:API网关作为一个算力资源,每次部署一个网关服务,都需要向注册中心注册一个算力。注册中心还需要接收RPC接口的注册,可以通过SDK自动扫描注册或者手动管理。一旦RPC接口注册完成,注册中心会根据AHP权重计算将其分配到一组网关算力上进行使用。

路由服务:每个注册的Netty通信服务都会与其对应的分组网关相关联。例如,通过配置Nginx的路由规则,将不同的接口调用请求路由到相应的Netty服务上。这样可以确保接口请求能够正确地到达目标服务。

责任链下的插件模块调用:鉴权、授权、熔断、降级、限流、流量切分等服务虽然不是API网关的核心功能,但通常也会作为共性通用的服务放置在网关层进行统一设计、实现和使用。

管理后台:作为一个完整的API网关项目,管理后台是必不可少的。管理后台提供接口的注册维护、模拟测试、日志查询、流量整形、网关配置管理等功能,方便对API网关进行管理和监控。

序号 系统 描述
1 api-gateway-core 网关核心系统:处理网络通信转换,接收和处理HTTP请求,调用RPC服务,以及负责责任链模块的调用。
2 api-gateway-admin 网关管理系统:用于管理网关接口的后台系统,包括接口的注册、下线和停用的控制等功能。
3 api-gateway-sdk 网关注册组件:通过注解方式采集接口信息并发送消息进行接口的注册。
4 api-gateway-center 网关注册中心:提供网关注册中心服务,负责登记和管理网关接口的信息。
5 api-gateway-test-provider 网关测试工程:提供RPC接口的测试服务。
6 api-gateway-test-consumer 网关测试工程:消费RPC接口的测试服务。希望以上整理满足你的需求。如果还有其他问题,请随时提问。

api-gateway-core开发

HTTP请求会话处理

HTTP请求到API网关,网关再去调用对应的RPC服务,之所以被称为会话,是因为一次HTTP请求,

根据这份协议,拿到必要的信息去调用对应的RPC请求。

SessionServer是用来启动Netty服务的,也就是启动Socket的过程

Netty除了端口需要配置们还需要把对数据的处理一并初始化到Channel管道当中,也就是对应的SessionChannelInitializer的功能

在 SessionChannelInitializer类当中包装HTTP GET/POST协议的解析,要完成网络请求也就是SessionServerHandler的内容

RPC泛化调用

为了把 HTTP与 RPC 建立连接,就像你把 DAO 与SQL执行建立连接 样两个服务的中间需要被绑定。也就是把 HTTP 地址中的接口方法与 RPC 对应的服务建立起一种关联关系,这样才能满足在调用 HTTP 网关接口时,调用到对应的 RPC 服务上。

就像如图所示 HTTP 经过网关调用到 RPC 中间的执行逻辑就是把两个模块用绑定的方式建立起连接,生成一个代理对象。代理对象中包装的就是执行网关接口泛化调用的参数准备和执行以及返回结果的操作。
这里的第一个知识点是泛化调用,它是 RPC 接口设计中提供的一种反射调用机制,只需要提供接口的方法名称、入参信息,即可调用到对应的 RPC 接口服务。可以参考官网文档: https://dubbo.apache.org/zh/docs/advanced/generic-reference这里的第二个知识点是代理包装,虽然 RPC 框架提供了泛化调用,也就是说这里可以拿到网络协议转换的 HTTP 请求信息以后,就能直接调用到 RPC 接口。但这样的操作方式不太方便使用,存在硬编码的风险,后续不好迭代升级,也不好扩展其他的接口。因为每一个RPC 的实现,泛化调用的方法名称还是有所不同的,另外是扩展非 RPC 框架的逻辑,也不方便外理。所以这里需要单独提供一个代理包装逻辑这里的第二个知识点是Calib,因为有第二个知识点中代理操作的存在,我们就需要选择一种方式来做代理处理,而Calib 可以满足我们自定义创建接口的方式进行代理,同时又可以在让一个代理类有多个接口。注意:多个接口的意思是,一个接口是用于标准的描述,在于使用上。另外一个接口是自主生成的,生成的是我们的 RPC 描述性接口,相当于自主生成了class字节码。

分治处理会话流程

将连接(RPC\HTTP\其他)抽象为数据源

进行代码重构: 划分session和socket两大块 把之前NettyServer的部分放到socket部分,把反射调用dubbo的那块留在session部分 更加细化出mapperedMethod,这一块是仿照Mybatis的处理,根据打进来的不同类型 (GET,PUT,POST,DELETE)方法,switch不同的处理方式。后续应该更细化拆分出 Executor。

HTTP请求参数解析