手记

为什么你的文件微服务是个错误(以及应该怎么做)

构建可扩展且易于维护的系统并非易事。当我们在追求系统的优雅时,有时我们所作的决定反而会带来更多问题,而非解决问题。今天我想和大家分享一个真实的故事:为了上传文档而创建了一个专门的 FileService 微服务。剧透警告:事实并不像听起来那么美好。

让我们一起深入情境中,分析挑战,并寻找一个更好的替代方案。

我们正在解决的问题

我们正在为企业建立一个银行平台。CEO管理现金流,给员工发放支付卡,并处理会计所需的收据,进行记账。在应用程序中会发生以下情况:

  1. KYC 验证(了解您的客户):在开户之前,CEO 上传敏感文件,如身份证件、地址证明和公司注册证书。
  2. 员工管理:员工加入平台并上传个人照,这些照片可供所有人查看。
  3. 费用追踪:员工在付款后上传收据(PDF 或照片),CEO 审核后会将其导出到外部会计软件。

回顾之前的步骤

每个步骤都涉及上传文档,我们需要一个强大的解决办法。我们团队的答案就是一个 FileService——一个用来管理所有文件上传的专门微服务,并将 AWS S3 的操作抽象为一个简洁的界面。

听起来挺优雅,是吗?不过慢着。别急着下结论。

为为什么要有专用的 FileService 理由

这就是为什么团队认为这是个好主意:

共享文件服务

  • 简化界面:一个围绕S3的单一抽象让界面更加简化,就像使用了“仓库模式”一样。
  • 灵活性:更改存储系统(比如从S3切换)会变得更加容易。
  • 微服务理念:一个单独的服务更符合微服务的模块化理念。

但是这种逻辑站得住脚吗?我们来把这个逻辑拆解一下。

逻辑上的破绽

优雅 ≠ 可维护性
代码的优雅是主观的,每个人对优雅的定义都不尽相同。在实践中,FileService API 与 S3 非常相似,以至于前端也能看出 S3 正在被使用,打破了抽象的假象。

更换存储服务提供商就像做白日梦
你上次换云服务商是什么时候?这些迁移简直就是噩梦,涉及数据一致性、冗余等问题。无论代码多么抽象,都无法让这一切变得简单。

关于微服务的误解
微服务应当聚焦于业务领域,而不是技术细节。而不是像将这些上传归为一类,把个人资料照片、KYC文件和收据上传归到一个类目里?这反而会带来复杂性。

隐藏的 FileService

到现在为止,你可能会想:“虽然不够完美,但还是能用。”我们来看看这种方法为什么还会带来新的麻烦:

1. 单点失效.

FileService 变成了一个一级组件。如果它挂了,你的整个系统就会宕机——不管是关键的 KYC 文件还是非重要的个人头像。

第2点 读写不一致

个人头像经常被查看但很少更新。收据经常上传但不常查看。一个同时管理这两者的服务需要应对高读取和高写入的负载,这会增加系统的复杂性和成本。

3. 业务逻辑泄露到 FileService

领域驱动设计提倡每个业务领域有一个服务,而不是按技术需求来划分服务。创建一个通用的FileService可能会带来风险,你可能会将不同领域的业务逻辑混入其中。

  • 文件类型和大小:个人资料照片应保持较小,但护照扫描件需要高分辨率以防止欺诈。文件大小的验证应该放在哪里?同样地,文件格式验证呢?您是否允许用户上传苹果设备的 HEIC 格式文件?
  • 缩略图:当用户上传个人资料照片时,系统会自动生成缩略图,但不会为收据生成缩略图。您是否会将缩略图生成器集成到 FileService 中?还是构建一个单独的微服务 ThumbnailGeneratorService?谁负责调用它?
  • 缓存:您可以缓存文件以提高延迟,但这会牺牲强一致性。这对个人资料照片来说是有意义的,但对 KYC 文档来说则毫无意义。
  • 备份:KYC 文件需要长期存储(账户关闭后七年),而收据一旦导出即可删除。
  • 权限:个人资料照片公开,而 KYC 文档私有,需要严格的访问控制。如果您的存储系统混合了公开和私有文件,这会带来安全风险。相反,应将公开文档存储在公共 S3 存储桶中,而其他文档则存储在私有存储中,确保更好的数据隔离。

处理这一切在通用服务里简直就是噩梦。

更好的方式:基于领域的文件上传

与其使用通用的FileService,不如让每个领域特定地处理自己的上传。

为什么这样做有效?
  1. 封装:每个服务都拥有自己的业务逻辑——文件类型、大小、权限和备份。每个服务可以根据需求选择适合的存储类型。
  2. 可扩展性:服务可以针对自己的需求进行优化(例如,读取与写入的优化、为个人资料图片设置缓存层、为KYC文件设置长期存储)。
  3. 弹性:某个组件(例如,个人资料照片上传)的故障不会影响整个系统。

每个服务都负责自己的上传

应对DRY的批评

但这代码重复了!这就不符合DRY原则啊!

不要重复自己(DRY原则)并不意味着把一切都集中起来。它的重点是避免重复的知识,而不是代码。适度的重复是更干净、更易于维护的系统的一个合理权衡,是值得的。

最后的, 思考

通用的 FileService 听起来很吸引人,但它实际上是个陷阱。试图简化可能会反而创建一个更难维护和扩展的瓶颈。虽然拥抱特定领域的要求可能感觉不够优雅,但这确实是更实际和更具弹性的选择。

你认为呢?你在架构中遇到过类似的问题吗?在评论里告诉我哦!

0人推荐
随时随地看视频
慕课网APP