目录

利用gRPC构建Python微服务(一)——关于微服务

微服务架构目前仍然是一种主要的开发方式,笔者从2010年开始接触OpenStack,对OpenStack架构略有了解,于是在后期的产品研发中,沿用这一框架。但是随着项目的进行,也逐步发现了该框架中在实际应用中的缺陷,以及入门成本比较陡峭的问题。所以想结合gRPC思路,来分析一下是否有对现有框架优化的可能性。

本文大部分内容出自:https://realpython.com/python-microservices-grpc/,结合了笔者个人经验进行了整理,并非完全的翻译。国内很多网站翻译的版本并非完整版,此篇几乎完整的还原了原文,请关注老孙正经胡说网站关注后续更新。

在完成了通篇的翻译工作后,不禁为作者的细致程度点赞,细节程度“令人发指”,这种匠人精神是值得国内的技术人员学习的。

全文导航

为了方便大家阅读,这里将全部目录进行一下索引,方便大家在老孙正经胡说(https://sunqi.site)中查看相关文章:

前言

微服务架构反映了开发人员在技术迭代中最朴素的愿景,即不把鸡蛋放在一个篮子中。解决随着项目发展,所有代码放在一个项目中时,开发运维成本陡增的问题。同时也提高应用可扩展性,尽可能的降低由于需求的增加而对原有架构重构的风险。

通过该教程,你可以学会:

  • 使用Python构建微服务模块,并且通过grpc进行通讯
  • 实现中间层(middleware),实现对其他微服务监控
  • 如何对中间层和微服务模块进行单元测试和完整性测试
  • 将微服务模块部署在Kubernetes集群中

为什么要使用微服务(Microservices)?

假设你要开发一个在线销售图书的网站,你的团队里有几百人,他们都在实现某部分具体的功能,例如管理购物车、推荐、处理交易等功能。

如果按照传统方式实现,将所有的代码写入一个巨大的项目中,所有的研发人员需要耗费时间理解全部代码。同时由于代码间的关联性,测试的时间成本也会被拉长,在版本控制上,代码与数据库结构的一致性也成了管理和开发上的难题。最重要的一点,这样的架构并不适用于快速变化的需求,开发一个新功能的周期将成倍的增加。

基于以上在传统开发中的难点,就应运而生了微服务的理念。将原有模块化开发中的功能模块,拆分成一个一个微服务,微服务通过统一的接口对外通讯,模块内部的变化不会影响其他模块。在示例应用中,可以将购物车,物品清单中等都作为一个微服务模块进行拆分。

模块化开发

假如产品经理需要实现一个功能:图书买二赠一。那么作为研发人员,可以增加一个检查购物车的逻辑,发现购物车有两本以上时,直接减去最便宜的一本书的价格即可实现该功能。

接着又出现了一个新需求,需要对这一活动的效果进行跟踪,由于之前的逻辑是在购物车实现的,开发人员需要在结账时,更新一下关系型数据库中的字段

1
buy_two_get_one_free_promo = true

接下来,产品经理告知你,该优惠活动每个用户只能享受一次,所以呢你需要在显示页面的时候检查你上面设置的标记,如果用户已经使用过该优惠,则需要隐藏掉宣传的Banner,如果没使用过则需要发邮件告知用户。

随着时间推移,关系型数据库数据量越来越大,所以希望更换共享型数据库(shared database),但是由于这样的标记太多,导致业务逻辑和数据库之间的羁绊越来越严重。这就是为什么不在一个项目中实现所有代码的原因,从长期角度来看,边界非常重要。

交易数据库只能被交易微服务所访问,其他服务访问时都应该通过抽象的接口实现,这样可以控制代码变更后的”爆炸半径“。

灵活性

微服务为代码构建提供了灵活性,一方面每一个微服务模块的开发语言不受限制,另外一方面你还可以灵活的扩展微服务模块。根据应用的特性,你可以将微服务模块运行在不同的硬件上。

稳定性

单点瓶颈问题是单体应用面临稳定性最大的挑战。另外,由于单体应用代码变更而引起的“爆炸半径”往往不可控。

所有权

在大型单体项目中,由于每个人对于整体架构理解不同,所以在实现过程中需要有经验的人进行严格的代码检查,这样让迭代速度变慢。

微服务架构让每个开发工程师只需要关注自己的代码部分的架构,这也降低了增加新功能时对其他模块产生影响的风险。

如何划分“微”服务?

这其实是一个极具争议性的话题,就像Restful一样,并非是一种协议规范,只是一种风格、一种建议。关于这一话题有太多争议性的讨论,甚至有文章说”微服务已死“的论调。其实我们不必纠结于此,“一千个人心中有一千个哈姆雷特”,从结果导向来讲,“黑猫白猫能抓到老鼠就是好猫”。从原文作者角度看,“微”是一种不恰当的命名,而我们重点关注的是应该放在“服务”上。

所以在设计微服务时有以下几点建议:

  • 微服务太小会破坏代码的模块化,微服务中的代码实现是有价值的,这类似类的数据和方法之间的关系。所以微服务的范围要适当,不要太大也不要太小,这也是为什么上面提到微服务的拆分因人而异,没有绝对的对与错
  • 微服务的开发和测试其实比单体应用更难,因为如果一个开发人员想要开发一个模块,必须要知道如何启动其他模块,这就对CI/CD流程提出了更高的要求,几个微服务模块手动可以启动,但是如果是十几个,则相当耗时耗力
  • 微服务的设计是一门艺术,也要结合团队的实际情况,如果你团队有5个人,但是微服务模块有20个,这是相当危险的;如果你的团队负责一个微服务模块,却被其他五个团队共享使用,这也可能会导致问题
  • 微服务在拆分时,不要意味的追求“微”,某些微服务模块可能会很大,但是也要注意,如果一个微服务模块做了两件或以上不相关的事情,也说明那个功能实现并不属于这个模块

这是对于在线书店的微服务模块拆分:

  • Marketplace:用户访问网站的逻辑
  • Cart:用户购物车及购买流程
  • Transactions:付款流程和发送收据
  • Inventroy:库存管理
  • User Account:用户登陆注册、密码修改等
  • Reviews:评价管理

这只是一些例子,并不是全部,每个团队的逻辑相对独立,这样更容易控制“爆炸半径”,例如评价系统出现问题,并不会影响购买流程。

微服务架构和单体架构的平衡

在产品研发初期,选择单体架构能够更快速的添加各种功能,快速完成产品。但是随着开发的进行,产品逐渐变得越来越臃肿。使用Python构建微服务架构,短期内会消耗你一定的精力,但是具备很好的扩展性。

典型的硅谷创业周期都是从单体开始,以便企业能够快速迭代。公司可以雇佣更多的工程师后,可以考虑使用微服务架构,但是要注意选择合适的时间点。

关于微服务架构与单体架构的平衡请参考《什么时候开始使用微服务架构》(https://www.youtube.com/watch?v=GBTdnfD6s5Q