对微服务的简单思考

今天阅读了文章《微服务架构在Netflix的应用:架构设计的经验教训》,引发了我对微服务的一些感想。大约这些感想平日都在大脑里装着没有声响,这篇文章算是酵母,投进去,发了酵,开始有些微醉薄醺的味道了。

这篇文章介绍了Cockcroft的微服务架构经验。Cockcroft是Battery Ventures公司的技术人员,是微服务和云架构方面著名的布道者,目前供职于Nginx技术咨询委员会。

一直以来,微服务虽然风生水起,不过却没有什么靠得住的定义可以得到多少人公认的。Cockcroft对微服务的定义却引起了我的注意。定义如下:

由松耦合的有相应语境的元素构成的一种面向服务的架构,松耦合意味着你可以独立更新这些服务。更新其中一个服务并不会改变其他的服务。

最后一句话可以看做是验证服务设计是否合理的一个标准。这里提到的“更新”,不仅意味着服务实现的变化,关键是它意味着“部署好的服务”的更新,如此才能体现服务的物理边界,而这正是微服务所要解决的单块架构的弊病。

在向微服务迁移的时候人们常常会把数据库的耦合看的过重,也就是所有服务都连的是同一个数据库,更新其中一个服务就意味着要改变数据库的schema。这种情况你需要对数据库进行拆分。

我只能表示部分同意这个观点,因为我们需要考虑数据库拆分的成本,因为它可能会带来维护成本的增加,此外还有拆分数据库会产生的影响,例如需要考虑数据的同步、分布式事务等系列问题。

在文章末尾,作者旗帜鲜明地强调了这一观点,并将其列入微服务架构设计最佳实践的第一原则:“每个微服务的数据单独存储”。但我觉得这个约束可能会导致微服务的粒度过粗,且可能导致微服务的设计者过度地考虑数据库Schema,而忘记从领域的角度去划分服务边界。正如Jan Stenberg的文章《微服务架构设计须避开工程师思维》就认为“开发者最好能站在用户的角度像一个设计师一样去设计规划”,他认为:

以数据层开始着手从内向外构建服务,然后通过业务逻辑将数据层往外迁移,这也就意味着API的设计工作接近尾声了。如果说真的是按照这个流程来执行的话,只能说制作这样一个API从业务逻辑上来说是有意义的,但是并不能满足庞大的用户需求。

服务的分离并不绝对代表数据应该分离,从具有悠久历史的ORM框架的存在就已经证明数据Schema与领域逻辑必然是“阻抗不匹配”的,强调这个约束,可能会导致设计陷入“数据驱动设计”的危险境地。

个人认为,降低数据约束的设计原则是尽可能避免多个服务对同一个数据存储进行写操作。而读操作则不在限制之列。在我们开发的产品中,CData微服务会在HDFS上创建Parquet格式的数据集,而另一个微服务则会对这个数据集的数据进行读取。虽然这两个服务共享了存储的数据,但读写却是分离(或者说命令查询分离)的,无论从性能、可扩展性还是其他质量属性去考虑,这样的设计都是无可厚非的。没有数据存储的约束,我们就可以从业务角度去划分微服务。

文中提到了Bounded Context,这是我非常认可的,甚至觉得DDD与Micro Service的理念是天然融合的,BC就是驱动出Domain Service的最佳起点。

在微服务这个概念兴起之前,我们有项目就已经通过BC驱动出各个粒度较小且松散耦合的Domain Service,并基于RESTful的架构风格设计服务API。所以微服务并不是什么时髦新潮的玩意儿,数十年前的DDD已经这么要求了,只是没有一个概念来清晰定位罢了。

如果我们再结合Robert Martin提出的Clean Architecture的概念,那么,一个微服务就与Application相对应,而Application则可以映射为一个Feature级别的Use Case,恰好对应了DDD分层架构中应用服务层中的应用服务。还可以引入Cockburn的六边形架构,它可以帮助我们分清楚服务的物理边界和逻辑边界。

许多人在理解物理边界时,会错误地以为只要模块分为独立的Jar包(或者.NET平台下的DLL)即可以认为是物理分隔,实则真正的物理分解是要从运行视图的角度去判断。在同一个JVM中运行的Jar包,都应该视为是逻辑分离,而非真正意义上的物理分离。微服务定义中的服务必须是物理分离的服务,如此才能满足真正意义的服务独立进化。

Netflix团队提出了几条设计和实现微服务架构的最佳实践:

  • 每个微服务的数据单独存储
  • 使用类似程度的成熟度来维护代码
  • 每个微服务都单独进行编译构建
  • 部署到容器之中
  • 将服务器看做是无状态的

除了针对第一条原则我心存疑虑外,后面诸条原则我均表示一百二十分的赞成。

原文发布于微信公众号 - 逸言(YiYan_OneWord)

原文发表时间:2016-03-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏编程之旅

简单的编程体会

今天的这篇博文,我不谈及具体的编程技术,只想从这段时间的学习以及写代码的过程中,分享一下自己的编程体会。

704
来自专栏编程微刊

我是如何快速积累工作经验

1405
来自专栏企鹅号快讯

写最少的代码,避免给自己找麻烦

软件开发的一个最基本的事实是:我们必须要写代码,但对于这样的一个事实的最大一个误解是:我们的工作就是写代码。作为软件程序员的最初几年,我一直被这样的思想所迷惑,...

1876
来自专栏web前端教室

【完工】仿制 豆瓣电影 app beta(二)

今天小年,长话短说,先祝大家小年快乐。 然后用vueJs做的这个仿制豆瓣电影的web app,就算是搞定了,看下面的视频演示, 虽然界面依然是很简陋,但基本逻辑...

3127
来自专栏Java学习网

你与其他程序员可能常犯的 6 个错误

你与其他程序员可能常犯的 6 个错误  我担任 CTO 已经有一段时间了,我觉得这是一个非常好的锻炼机会,因为我不仅可以编写代码,还要带领团队,管理项目,设计架...

22810
来自专栏程序员互动联盟

【编程基础第六讲】需要掌握什么知识才能做项目?

存在问题: 什么是做项目?因为大家学习的时候都是有人指导,又书可循,但项目是加上的时间以及一些不确定因数的集合,我们真正做项目要知道些什么呢? 解决方案: 常常...

3336
来自专栏企鹅号快讯

学会这五种编程语言,再来研究DevOps也不迟

如何确保我们采用的DevOps能够成功?是否有某些语言非常适合应用于DevOps?今天,我们来看看众多编程语言中,哪个才是最适合DevOps的(顺序与排名无关)...

1936
来自专栏诸葛青云的专栏

要想精通C语言,必须先学习汇编吗?

编程语言里面很少有人直接说出精通两个字,特别是一些入行好多年的程序员,从语法来讲C语言相对来讲入门还是比较容易,在高级语言还没有完全展开的年代,C语言算入门比较...

240
来自专栏编程

前端开发的中年危机

最近一年前端也在飞速发展着, 很多前端(比如我)感觉有时候就会莫名其妙的冒出各种不明觉厉的概念: redux刚看了一点, 突然不知道哪来的mobx, rxjs...

1797
来自专栏互联网杂技

2017 Web开发技术的路线图 (前后端+运维)

主要是技术方面,归纳得非常全面,分为前端,后端和运维: ? 下面是前端技术路线 ? jQuery也算是基础中的基础了; 响应式web也是非常重要的一块知识; 语...

41510

扫描关注云+社区