聚合国内IT技术精华文章,分享IT技术精华,帮助IT从业人士成长

你真的了解微服务吗?

2021-09-02 17:05 浏览: 3346332 次 我要评论(0 条) 字号:

作者 | Charles Mahler
译者 | 平川
策划 | 万佳

本文最初发布于 freeCodeCamp 博客,由 InfoQ 中文站翻译并分享。

过去几年,微服务已经从一个夸大其词的流行语变成了一个是个软件工程师就应该了解的东西。

根据 2020 年 O'Reilly 开发者调查:

  • 2019 年,有 61% 的公司已经在使用微服务;

  • 29% 的公司表示,他们的系统至少有一半是使用微服务构建的;

  • 74% 的公司表示,他们的团队会分步骤构建 / 测试 / 部署应用程序。

随着微服务生态的成熟,采用微服务越来越容易,上述数值将继续增长。

这不是说,为了找份工作,你要成为微服务专家,但至少,理解基本原理还是有好处的。

事实上,关于微服务的基础知识并不难理解。最大的问题是,与此相关的大部分资料都是为了哗众取宠,而不是为了让读者掌握相关知识。

另一个原因是,微服务没有一个准确而具体的定义。于是就出现了大量语义上存在重叠的定义和术语,让试图了解微服务的人陷入困惑。

在这篇文章中,我将去芜存菁,重点介绍微服务的核心概念。我将使用各种真实世界的例子和类比,帮助你理解相关的抽象概念和思想。本文将介绍以下内容:

  • 软件设计简史;

  • 单体架构的优缺点;

  • 微服务架构的优缺点。

1如何理解微服务:以自主创业做类比

假如你是一名软件工程师,你决定通过自主创业来赚钱。一开始,你有一些客户,事情进展很顺利。你把大部分时间都用在编写代码上,客户也很满意。

但是,随着时间推移,业务规模扩大,你的速度慢下来了。你把越来越多的时间用在客户服务、回复邮件、为之前的客户做一些小的修改以及其他一些无助于增加收入的事情上。

你意识到,作为一名软件工程师,你并没有以最佳方式利用好自己的时间,因此,你雇了一名员工,专门负责客户服务。

随着业务规模继续扩大,你雇佣了更多具有专门技能的员工。你雇佣了一名营销人员,专注于吸引新客户。你增加了项目经理、软件工程师,最终又增设了 HR 部门来帮助你管理这些员工。随着业务规模的扩大,所有这些都是必要的,都不是你一个人能完成的,但是,不可避免的还有成长之痛。

有时候,客户或部门之间会存在沟通上的不畅,而客户会因为细节上的不足感到沮丧。企业要承担支付员工工资的直接成本,团队之间会存在内部竞争,还会有其他随着企业发展而出现的问题。

这是软件公司从单体转向微服务的一个多少有些代表性的例子。一开始一个人做所有的工作,然后逐渐变成多个专门的团队一起来实现公司的共同目标。

这非常像技术公司从单体迁移到微服务架构。虽然这些例子与微服务不能一一匹配,但所要考虑的一般问题是一样的:

1、扩展——理想情况下,你希望可以快速雇佣新员工,实现生产力的线性增长;

2、沟通——增加员工意味着增加组织的沟通协作成本。在这个远程工作的时代,企业有许多办法可以实现高效的沟通;

3、专门化—— 让组织中的某些团队可以自主解决问题,采用最有效的方式,而不是在所有情况下都遵循同样的标准程序。有些客户可能会有不同于其他客户的需求,因此,让团队在处理事情时有一定的灵活性是有好处的。

2如何从单体转到微服务

理解上图有助于我们了解过去。传统上,软件设计采用单体风格,所有东西都在一个应用程序中一起运行。和生活中的其他事情一样,这种应用程序设计也是优缺点并存。单体并不一定差——许多微服务倡导者实际上也建议从单体入手,如果没有问题,就一直沿用单体即可。如果遇到了问题,就可以随着时间的推移自然而然地将单体拆分成微服务。


3单体架构的优点
 初始开发速度快

刚开始时,在一个小团队里,单体的开发速度相当快。这是因为项目小,每个人都了解整个应用,事情进展非常顺利。团队成员非常清楚各种功能是如何协同的,新特性的实现速度很快。

 部署简单

由于单体只有一个工作单元,像测试、记录日志这样的事情都很简单。与部署多个独立的微服务相比,构建并部署一个单体更简单。

4单体架构的缺点

虽然单体架构早期有诸多好处,但随着公司发展,采用单体架构的应用程序经常会遇到一些组织和技术层面的问题。

 模块紧耦合

为了便于组织管理,大多数有单体应用程序的公司,都试图根据应用场景将单体合理地拆分成功能模块。考虑下诸如身份验证、评论、用户和博客帖子这样的东西。

问题是,这需要严格的工程纪律保障才能长期保持下去。当最后期限临近时,许多已有的规则经常被抛诸脑后。这会导致关键时刻走捷径,产生关联关系复杂的代码,技术债务随着时间推移不断增加。

现实世界的例子——遵守单体开发的纪律非常像坚持有规律的运动或节食。许多人都是那样,在开始几周很兴奋,可以坚持节食,但最终,生活妨碍了节食计划,你又退回到了习惯的状态中去。

在单体中强制实现松耦合就是这样,当时间紧迫时,很容易禁不住诱惑偷工减料。

 新人参与困难

新员工需要花更长的时间才能具备生产力,因为他们需要先理解单体中各个相互关联的部分是如何协同工作的,然后才能冒险修改应用程序的某个部分。

我们肯定听说过,新员工花了几个月的时间才真正熟悉了一个大型代码库。而且,人们总是会有潜在的担心,就是怕推送新代码会弄坏整个应用程序。

与现实世界对比——培训某个人做一件事,如钉钉子 vs 培训某个人做建筑工地上的每一项工作。

把有关整个工作的所有东西都教给一名新入职的员工,无疑会增加雇佣新员工的成本。

 资源需求冲突

在一个单体中,不同的模块可能有不同的硬件需求。有的任务可能是 CPU 密集型的计算,有的可能需要大量的内存。但是,由于整个应用程序运行在相同的服务器上,所以你无法使用针对特定任务的硬件。

现实世界的例子——某些类型的车辆更适合某些类型的任务。

如果你想来一场公路旅行,那么一辆具有绝佳燃油经济性的汽车将是最佳选择,因为可以帮你节省油钱。如果你要搬到新公寓,那么空间更大的车辆无疑更合适,因为可以减少来回趟数。

 一个 Bug 就可以让整个应用宕掉

由于整个应用程序是一个部署单元,所以任何团队都有可能在无意间制造一个 Bug,使得整个单体宕掉。

现实世界的例子——为了防止一个地方漏水使整艘船沉没,如果某个区域开始大量进水,就会使用隔板将其封住。

微服务的工作方式类似——每个服务都是独立部署的,这样可以减少一个 Bug 搞宕整个应用的机会。

 限制了试验

在构建单体时,你差不多就困在了用来编写单体的编程语言生态中。一个简单的例子是低级编程语言和高级编程语言的取舍。

在微服务架构中,如果某个服务扩展困难,那么你就可以考虑使用一种性能更好的语言如 C++ 或 Go 重写它。而对于其他并不需要太关注性能的服务,你就可以使用像 Python 或 JavaScript 这样更高级的语言来提高开发速度。

单体架构让团队看不到其他解决问题的方案。当你只有一把锤子在手时,看什么都是钉子:

与现实世界对比——披萨很棒,但你应该不会希望余生每餐都吃披萨。

而且,在某些情况下,与其他东西相比,做个披萨来吃并不方便。有时候,随便吃点快餐或吃点更健康的东西就不错。

 部署会变得很慢

在上面提到的单体架构的优点中,有一个会慢慢变成缺点。对于大型单体来说,整个应用一起部署会成为问题,因为部署整个服务会需要很长时间。这会降低团队迭代和修改应用的速度。

每次做个小更改,都得等着应用构建、部署,然后测试。

现实世界的例子——你的梦想是做出世界上最好的曲奇饼干。达成这个目标的最快方式是尽可能多的测试,并逐步调整和改进配方,直至它趋于完美。

如果你只有一台烤箱,那么与有 10 台烤箱相比,你测试不同曲奇配方的速度就会慢许多。

5微服务的优点

现在,你已经知道了单体架构的优缺点,让我们看下微服务。

 提升开发速度

因为部署的不再是单体,所以团队可以更快地增加新特性。各团队有自己单独的发布计划,不用再过多考虑与其他团队的协同。

只要外部接口(提供给其他微服务用于和本服务交互的接口)保持不变,开发团队可以根据需要使用另一种编程语言完全重写系统。

各个服务单独部署的另一个好处是,每个构建的规模变小,速度变快。也就是说,仅仅因为构建变快就可以提升迭代速度。

现实世界的例子——当你从餐馆购买食物时,只要食物口味好就行,你并不关心后厨有什么变化。

也许他们有了新烤箱或炸锅,但只要食物的口味不变,就没有关系。外部消费者唯一关心的是最终产品。

 新人上手更快

新员工只需学会一个简单的系统就可以开始做出贡献了。随着时间推移,他们可以继续学习更多关于整个应用程序的内容,但不必马上就学。

现实世界的例子——装配线通过把事情分解改变了生产方式。每一名员工都不必知道如何从头开始创建一个完整的产品,他们只需要学习他们参与的那一部分。这可以节省新员工培训时间,更有利于企业发展。

 容错性

虽然微服务经常会依赖于其他微服务来完成工作,但设计良好的微服务架构会内置冗余和失败保护机制,可以防止其他服务宕掉时导致整个系统失败。

通常,这包括请求重试,而且随着请求次数增加,请求之间的等待时间也会增加,或者如果服务不可用,就返回一个默认的备用值。

现实世界的例子——如果 Netflix 的推荐服务中断,那么把完整的故障信息返回给用户是没有意义的。

因此,在这种情况下,Netflix 会默认返回当前流行的影片,而在后台则继续重试访问推荐服务,直到它返回为用户客制化的观影建议。

 扩展灵活

由于每个服务都是单独部署的,所以每个服务都可以单独复制和扩展。如果是单体,那么公司就只能扩展整个应用程序,即使只有一个特性的流量超出了平常。

在微服务架构中,公司可以单独扩展需要处理更多流量的服务,这样更高效,也更省钱,因为这减少了资源浪费。

现实世界的例子——考虑下亚马逊的网购星期一,订单会比平时多,但大多数人其实已经提前选好了他们想要的东西,并放到了购物车里。

所以,订单服务的流量会比平时高,但搜索服务及其他特性的访问情况可能和平时差不多。

如果一个服务特别消耗某种资源,这会尤其有用,因为可以针对这种任务使用专门的硬件。

如果一个服务需要大量的 CPU 资源,但需要的内存不多,那么为了节省成本,公司就可以不购买通用服务器。使用纯单体的公司就别无选择,只能使用通用服务器了。

6微服务的缺点

微服务架构还远称不上完美。从单体转到微服务缓解了一些问题,但也带来了新问题。

 增加整体复杂度

虽然单个的服务更容易理解,但整个系统本身更加复杂了。这种复杂性催生了像 Docker 和 Kubernetes 这样的工具,为的是尽可能地把这种复杂性抽离出来。

这些工具的目的是让软件工程师可以和以前一样专心构建特性,而不必考虑其他事情,比如它们在后台是如何运转的。

 通信

在微服务架构中,其中一个最大的问题是明确微服务之间彼此如何通信。

用户发起的一个外部请求,可能需要多个服务协同来满足。让我们以在线下单为例来看看这个过程。

  • 用户在 App 中下单;

  • 负载均衡将请求发送给可以处理该请求的服务;

  • 购物车服务提供订单的物品清单;

  • 库存服务确认相应的物品有库存;

  • 发货服务计算预估费用和发货时间;

  • 支付服务确保客户支付有效;

  • 推荐服务未来会使用订购的物品为客户生成新的购物建议;

  • 评论服务会按计划向客户发送一封邮件,请客户评价。

在上述步骤中,其中任何一个服务失败都会导致整个过程失败或引发客户不满,很快就会积累一批愤怒的客户。

在微服务架构中,处理所有服务之间的交互,应对局部失败,是一项很大的挑战。

 数据处理

关于微服务,其中一项最大的挑战是处理跨多个服务更新数据的请求。

在这个过程中,如果请求的一部分失败了,一个服务更新了数据,而其他服务没有更新,怎么办?不能说因为服务宕掉了,你收了用户的钱,用户却没有收到货。

在单体中,如果出了什么问题,你可以利用 ACID 事务回滚数据库更改。但在微服务架构中,要复杂得多,这会涉及跨服务的分布式事务。

 开发环境

大多数工具是针对单体架构而设计的,在开发微服务架构应用时一般会更难一些。

测试需要能够模拟与其他服务的交互,调式也更难,因为事情不是发生在单个进程中,日志必须能够跨多个服务进行记录。

即使像“跟踪一篇博客为什么加载慢”这样简单的事情,其困难程度也会超出你的预期。

假如你从分析工具中看到,页面加载博文突然需要 5 秒了。在单体中,这个问题很容易跟踪,但在微服务架构中,你需要使用专门的工具来跟踪外部请求,因为它们是由不同的服务处理的。

7小结

希望本文可以帮助你了解什么是微服务以及为什么要采用微服务,并对微服务的工作原理有一个直观的认识,指导你了解底层的技术细节。

将来我还会发布关于微服务的视频和文章,感兴趣的话可以在 YouTube 上订阅或在 Twitter 上关注我。

今日好文推荐
估值高达380亿美元!大数据独角兽Databricks官宣16亿美元新融资
Azure 曝史上“最严重”漏洞?微软也难以回应云安全质疑
如何用研发效能搞垮一个团队
最高法明确“996”严重违法;新浪回应“花钱买热搜”;活久见,苹果App Store允许第三方支付|Q资讯


 活动推荐

编程语言热门榜评选来了!编程语言作为技术人的入圈工具,与每个技术人的职业生涯息息相关~

近期,InfoQ 特别推出了【InfoQ 编程语言排行榜】,精心挑选了当前最流行、最受欢迎的编程语言,同时设置了八个有代表性的问题。扫描图中二维码,为你看好的编程语言投上一票!

点个在看少个 bug 



网友评论已有0条评论, 我也要评论

发表评论

*

* (保密)

Ctrl+Enter 快捷回复