微服务是什么?

2020-07-02 00:00:00 微服 分布式 业务 服务 系统

我:"你觉得我们这个架构用微服务怎么样?"

同事:"你的问题是什么?"

我:"没有问题,我就是感觉可以用微服务来做这个项目比较好,看了一些资料,微服务有 XXX 特点,感觉挺好的。"

同事:"所以,你设计这样一个架构,解决的问题是什么呢?"

我陷入沉思。

早期的时候,每一次和架构师同事讨论问题,当我想要说出我的技术方案时,他总是用这个问题反问我。一开始我被弄得莫名其妙,后来慢慢习惯这种对话方式。其实这是一种问题驱动的思维方式,并且对架构师来说,至关重要。

微服务架构几乎成为互联网公司架构的标准形态,我们在讨论如何划分、设计微服务架构,甚至领域驱动设计(DDD)时,我们应该回归初心,当我们开始讨论怎么划分微服务时,我们应该能回答下面的问题:

  • 需要解决的问题是什么?
  • 什么是微服务,和 SOA(面向服务的架构) 的区别是什么?
  • 为什么是微服务而不是其他架构方式(例如:SOA)?
  • 带来的好处是什么?
  • 微服务带来的成本有多大?
  • 对系统造成的影响是什么?

需要解决的问题是什么?

一个几个人的小团队提供的服务一般不会太过于复杂,另外应用也不会特别大,这个时候一个单体应用对团队是非常友好的。不用考虑集成、部署等分布式系统的各种麻烦。实际上,大部分应用程序,还达不到使用微服务这样复杂架构的必要条件。

当团队开始变大,或者应用变得越来越复杂时,会产生几个痛点:

  • 应用性能瓶颈,扩容困难
  • 故障和系统弹性无法隔离
  • 应用复杂到无法理解,模块耦合高,应用职责过多
  • 过多的人工作到同一个代码库中
  • 应用大到编译、部署时间长

其中,促使开发者从单体应用走向分布式系统大的动机就是应用性能瓶颈,扩容困难的问题。实际上,当下的工程师们都是在开发广义的 "分布式系统",因为真正的单体应用系统只存在于大型机、小型机时代了。客户端-服务器模式是一个基本的分布式系统,无论是 C/S 模式还是 B/S 模式。

"客户端-服务器模式" 把需要单体主机需要全部完成的工作分离到了客户端实现了一次扩容,这个过程对软件行业进行了一次革命。但是随着需求量日益扩张,单纯的"客户端-服务器模式"已经不能满足需求。高性能、大容量的需求往往来自于面向 C(customer) 端的系统,这也解释了为什么分布式系统由面向消费者的公司驱动。Google 和 Salesforce 有海量的在线用户,他们比微软、Oracle 更为热衷分布系统的研发。

当单纯的 "客户端-服务器模式" 不能满足需求时,人们开始寻找新的拓展方式。其中一个方向是将 B/S 模式下的服务器工作下放到浏览器,这就是 SPA(Single Page Application) 富客户端,让前端单页应用承载用户交互和界面相关的工作,让服务器专注于处理业务逻辑和运算。另外一个方向是服务器角色分化:状态和运算分离。将数据库和应用分开部署,将应用中的 Session 入库,让应用无状态化,然后大规模部署应用服务器;剥离和业务无关的组件,例如邮件、文件、推送,演化出独立的服务,分布式文件系统应运而生。然而痛点在于,前面是根据技术进行水平切分,那么如何根据业务模块进行拆分,继续拓展呢?

其次的痛点是故障和系统弹性无法隔离。故障隔离的意思是某部分相对独立的业务中断,不应该影响整个系统。例如一个电商系统,因为某些原因造成无法支付,但是不应该影响用户浏览商品的业务。系统弹性是指应用扩容的需求,单体系统无法做到针对某一部分业务单独扩容,例如秒杀的场景,我们无法针对下单或者结算进行单独扩容。下单造成大流量的访问会导致整个系统不可用。

上面这两个痛点,是从终用户体验的角度出发,这是真正推动技术进步的原因,也是技术变革产生业务价值的地方。另外三点都是从开发和运维的角度出发,这部分痛点来自开发者,但有可以通过各种方式在单体的应用下改善或克服。

当应用变得非常复杂时,程序变成了一个大泥球(A Big Ball of Mud)。模块之间的依赖关系变得极其复杂,程序开始变得混乱不堪,不过需要提前澄清的是单体或者分布式架构对这个问题无能为力。分布式架构的引入,会让大泥球的代码变成分布式大泥球,进一步增加系统熵 (Entropy,一种物理学概念,系统的混乱程度)。如何避免大泥球呢?后面会谈到可以通过良好的面向对象设计和重构完成。

其次,大的单体还会有编译时间长、部署时间长的问题。如果一个上百人的团队工作在一个代码库中,每天的工作除了在修复冲突之外,就是在等待编译。但这些都不是不可以克服的,Linux 内核就是一个超级单体系统,极长的编译时间和极多的参与人数,但 Linux 项目也能良好的运行。

所以这部分比较啰嗦,毛泽东思想告诉我们,分析问题的时候需要分清主要矛盾和次要矛盾。那么我们在分析系统问题的时候,不仅应该见微知著,也应该抓住关键。

所以问题的关键是系统的 "耦合","耦合" 的存在让我们难以拓展、故障隔离、开发困难、无法分开编译。

什么是微服务?

根据维基百科的定义,微服务是一种 SOA 的变体,特征是服务之间通过松耦合的方式集成。一般采用轻量级的传输协议(Http),以及不要求服务内采用同样的技术栈实现,通过暴露统一的 WEB API 实现相互通信。

业界对微服务的共识是:

  • 服务根据业务能力划分,能提供一定范围内完整的业务价值
  • 服务可以单独部署、运维
  • 服务可以基于不同的编程语言、数据库等技术实现
  • 服务之间使用轻量级的网络协议通讯,例如 HTTP
  • 服务有自己的独立的生命周期
  • 服务之间松耦合

"服务根据业务能力划分"和"松耦合"需要特别注意,这是微服务和 SOA 大的区别。

在解决扩容这个问题上,让我们看下 SOA 和微服务的区别。在解决拓展性的问题,有一个非常好的模型,叫做 "AKF扩展立方"。AKF可扩展立方 (Scalability Cube),来自于《可扩展的艺术》一书。

这个立方体中沿着三个坐标轴设置分别为:X、Y、Z。



  • X 轴扩展 —— 无差别的水平的数据和服务复制,具体的实践可以对应为加机器
  • Y 轴扩展 —— 根据应用中职责的划分,具体的实践为对各个业务线剥离
  • Z 轴扩展 —— 利用特殊属性划分数据集合,例如基于租户模型对用户进行切割

Z 轴拓展实际上非常常见,例如电信运营商基于地域对用户进行划分,北京和上海的用户使用不同的号码段进行管理。微服务出现之前,我们对系统的拓展更多的关注于 X 拓展,负载均衡、读写分离都是为了解决如何进行服务复制来承载更多的请求。SOA 应用进行了一部分的 Y 轴拓展,但是 SOA 和微服务的本质不同在于,SOA 拆分的不是独立的服务,而是组件,SOA 组件必须注册到企业总线或者其他机制中才能对外提供整体的服务。

一个典型的区别在于,SOA 往往将业务逻辑拆分成不同的 SOA 服务,但是数据依然是集中的。业界对微服务的共识在于数据应该被划分到各个微服务中,每个微服务可以独立演进、独立发布甚至独立运营,提供完整的服务能力,并通过松耦合的方式集成。这也是企业实现中台的基本能力。

相关文章