Droplet——一款轻量的Golang应用层框架

Github地址
如标题所描述的,Droplet 是一个 轻量 的 中间层框架,何为中间层呢?通常来说,我们的程序(注意这里我们仅仅讨论程序的范围,而非作为一个系统,因此这里不设计如 LB、Gateway、Mesh等内容,因为它们都处于程序以外)按不同的职责可以分为不同的层次,而按照不同的设计风格,常见的如下:
  • 三层架构:UIL(UserInterfaceLayer), BLL(BusinessLogicLayer), DAL(DataAccessLayer)
  • DDD分层架构(参考ddd-oriented-microservice):ApplicationLayer,DomainLayer,InfrastructureLayer
  • 洋葱架构(参考Onion Architecture ):Application, Infrastructure, ApplicationService, DomainService, DomainModel 。
Tips
洋葱架构其实也是基于DDD的,它是DDD分层架构的升级版本 。
但是今天我想用于解释中间层的架构并非以上的任何一种,它也源自于DDD的分层架构,不过我配合了六边形架构来说明它,分层图如下:
Droplet——一款轻量的Golang应用层框架

文章插图
在六边形架构中有个规则:依赖只能是由外部指向内部 。因此从外层到最内层分别是:
分层职责Access程序的接入层(在六边形架构中这被称为输入适配器),通常位于整个请求 or 任务的起点,它可能是某种Web框架,也可能是一些队列的消费框架等 。Application程序应用层,包含了一些非业务的逻辑,如:业务逻辑的编排、参数绑定、校验、请求日志、链路上报、状态读取等等Domain & Utils在最中心的地方我放入了两个层次描述:Domain 与 Utils,这两个分层都应该是位于依赖的最底层,意味着他们不应该引用本项目的其他层次 。Domain层主要包含核心的业务逻辑,而Utils则是一些程序任何地方都可能会引用的代码段,比如常量定义、数据结构和语法糖等等Infrastructure基础设施层(在六边形架构中这被称为输出适配器),程序所有需要对外进行信息交换 or 功能依赖时都会放置在这一层实现,通常来说这些功能都是被依赖的那部分,因此我们如果要满足依赖约束的话,这里必须要引入 DIP(Dependency inversion principle),即在Application、Domain中定义依赖,而 Infrastructure 来实现它们,这样保证了它们是可被替换的六边形架构优点在于解耦程序中业务无关的部分,以保证它们都是可被替换与扩展的 。而 Droplet 就工作在 Application 层,它的核心能力只有一个:提供基于pipeline的请求/响应处理能力 。可能有人会疑问,几乎每个框架都会实现类似的能力,为什么我们需要 Droplet 呢?别急,我们来看看这些框架自带的 pipeline/middleware 存在什么弊端 。根据上面的架构图我们可以知道诸如 gin、go-restful、fasthttp 之类的http框架都是工作在 Access 层,因此框架自带的 pipeline/middleware 存在以下两个弊端:
  1. 框架绑定: 这个很容易理解,这些机制只能工作于特定的框架下,如果切换框架则需要需要调整代码,除了中间件的代码外,我时常也会见到程序在 API Handler 中耦合了大量框架相关的代码,比如:读取参数(header, query, body等)、根据业务结果回写响应等,这些代码渗透到了业务程序中(有时它们甚至会比业务代码占用了更多的行数),这加大了业务开发同学的维护成本,同时也降低了程序的可扩展性 。
一些相关的BadCase
想象一下: