Contents

资格校验接口的微服务设计与实现

导语
当在设计微服务接口时,或许会遇到一个接口职责不单一时,此时应该如何处理呢? 本文就以资格校验服务为例,详细介绍一下如何使用工厂方法、流量镜像、流量回放等技术手段解决该问题。

资格服务的三层架构

由于在本接口中需要实现多种规则的校验工作,并结合实际需求,最终的代码设计遵循简洁架构设计,划分为如下几层:控制层(Controller)、业务层(Biz/Service)、存储层(Store)。 其中,从 Controller、Service 到 Store 的层级依次逐渐加深,具体代码架构如下图所示:

层与层之间导入包时,都有严格的导入关系,可以有效防止包的循环导入问题,即 Controller 能够导入 Service 的和 Store 的包。 但需要注意的是,如若没有特殊需求,Controller 要避免直接导入 Store 层的包,而是其业务功能都由 Sercive 层完成。

控制层(Controller)

Controller 负责接收 HTTP 请求,并进行参数的解析与校验、逻辑的分发处理、请求返回等操作。 Controller 将逻辑分发给 Service,Service 处理后返回,返回数据在 Controller 中被整合加工,最终返回给请求方,即实现了业务路由的功能。

业务层(Biz/Service)

Service,主要用来完成业务逻辑处理,可以把所有的业务逻辑代码放在本层。 Service 会处理来自 Controller 的请求,并根据需要请求 Store 完成数据的 CURD 操作。

存储层(Store)

Store,用来跟数据库/第三方服务进行 CRUD 交互,作为应用程序的数据引擎进行数据的输入与输出。 需要注意的是,Store 仅对数据库/第三方服务执行 CRUD 操作,不封装任何业务逻辑。

Store 同时也起到数据转换的作用:

  • 将数据库/微服务中获取到的数据转换为 Controller、Service 能识别的数据结构;
  • 将 Controller、Service 的数据格式转换为数据库或微服务能识别的数据格式。

层间交互

Controller、Service、Store 各层之间都是通过接口进行通信,如此,可使得相同的功能支持不同的实现(即插件化能力),同时也使得每一层的代码变得可测试。

  • Controller 依赖于 Service 层,意味着该层需要 Service 层来支持测试,此时可以通过 golang/mock 来 mock Service。

  • Service 依赖于 Store 层,意味着该层需要 Store 层来支持测试,此时可以通过 golang/mock 来 mock Store。

  • Store 依赖于数据库,如果调用了其他微服务,则还依赖于第三方服务,此时可以通过 sqlmock 来模拟数据库连接,通过 httpmock 来模拟 HTTP 请求。

资格服务代码设计

在了解本资格服务三层架构之后,我们就可以开始设计代码了。

由于在本接口中需要实现多种资格的校验工作,并结合实际需求,最终在 Service 层采用工厂方法设计模式,相关类图如下:

从图中明显可以看到,Server 接口定义了该服务所支持的功能,实现了接口就是规范的功能。 另外在 Server 的实现类 DjcRuleService 中持有 rule.Ruler 接口的引用, 该接口定义了 Ckeck 方法,rule.Ruler 接口的实现类(例如,DJCFFriendsRuleDJCfmVipRule)会实现 Ckeck 方法,从而实现规则的校验。

在 Controller 层中,我们定义了如下的代码结构:

它不仅持有 services.Servicer 接口,而且实现了 POST/HEAD/GET 等 HTTP 方法,实现了 HTTP 请求的响应、参数的解析与校验、Service 层业务逻辑的调用等操作。

整个软件体系采用了分层架构,即分为 controllersservices以及 rule 三个 Package,其中每一个 Packge 都采用了面向 interface 的编程范式。

微服务部署

接口测试之流量回放与镜像

Reference