SmartBear
微服务架构是一种独特的软件系统开发方法,其核心在于构建单一功能模块,这些模块具有明确定义的接口和操作。
近年来,随着企业希望变得更加敏捷,并向 DevOps 和持续测试转型,微服务架构逐渐流行起来。
正如 Martin Fowler 所指出的,Netflix、eBay、Amazon、Twitter、PayPal 等科技巨头都已从单体架构演进为微服务架构。这对敏捷开发和 DevOps 团队带来了诸多优势。
单体架构 vs 微服务架构
与微服务不同,单体应用(Monolith)是作为一个单一、自治的单元构建的。因此,对应用的任何修改都非常缓慢,因为它会影响整个系统。即使只是对一小段代码进行改动,也可能需要重新构建并部署整个新版本的软件。此外,若要扩展应用中的某个特定功能,也必须对整个应用进行扩展。
模块化是关键
微服务通过极致的模块化解决了单体系统的挑战。最简形式下,微服务帮助我们将应用构建为一组小型服务,每个服务运行在自己的进程中,并可独立部署。这些服务可以用不同的编程语言编写,甚至可以使用不同的数据存储技术。
虽然这种方式提升了可扩展性和灵活性,但也需要一套动态的配套机制。微服务通常通过 API 相互连接,并可充分利用 RESTful 和 Web 服务生态系统中已有的工具和解决方案。如今,API 测试已成为确保微服务部署质量不可或缺的一环,它通过验证通信路径和数据流来保障系统可靠性。
微服务的优势
更简单的部署
可以逐个部署组件,而不影响其他服务。更易于理解
由于功能隔离且依赖较少,代码更容易阅读和维护。跨业务复用
可在企业内共享小型服务,如支付或登录系统。更快的缺陷隔离
当测试失败或服务宕机时,能迅速定位问题。降低变更风险
避免被特定技术或语言锁定,可灵活切换,风险极小。
理解微服务架构
尽管“微服务”尚无正式定义,也没有适用于所有系统的标准模型,但大多数微服务系统都具备一些共同特征。
微服务的六大特性
多组件性(Multiple Components)
应用可拆分为多个组件服务,每个服务可独立部署、调整和重新部署,而不影响整体应用完整性。这意味着你只需修改一个特定服务,而无需重新部署整个应用。但这也带来了一些缺点,例如远程调用成本更高(而非进程内调用)、远程 API 更粗粒度,以及在组件间重新分配职责时更加复杂。面向业务(Built For Business)
微服务架构通常围绕业务能力与优先级组织。不同于传统单体开发中按 UI、数据库、技术层或服务端逻辑划分团队,微服务采用跨职能团队。每个团队负责基于独立服务构建特定产品,并通过消息总线通信。正如亚马逊著名的信条:“你构建它,你运维它”(You build it, you run it),团队对其服务拥有全生命周期责任。简单路由(Simple Routing)
微服务的行为类似于经典的 UNIX 系统:接收请求、处理、返回响应。这与企业服务总线(ESB)等系统形成鲜明对比——后者依赖复杂的高技术系统进行消息路由、编排和业务规则应用。微服务强调“智能端点 + 哑管道”(smart endpoints and dumb pipes):端点处理逻辑,管道仅传输数据。去中心化(Decentralized)
由于微服务涉及多种技术,传统的集中式治理方式不再适用。微服务社区推崇去中心化治理,鼓励开发者创建可被他人复用的工具。同样,微服务也倾向于去中心化数据管理。单体系统通常使用单一逻辑数据库,而微服务中每个服务通常管理自己的独立数据库。容错性强(Failure Resistant)
微服务设计时就考虑了故障应对。由于多个异构服务相互通信,某个服务可能因依赖方不可用而失败。此时,客户端应允许其他服务继续运行,而自身优雅降级。当然,监控机制可帮助预防故障风险。但这也使微服务比单体架构更复杂。演进式设计(Evolutionary)
微服务是一种演进式架构,特别适合那些无法预知未来访问设备类型的应用。许多应用最初基于单体架构构建,但随着不可预见的需求出现,可逐步重构为微服务,并通过 API 与遗留单体系统交互。
微服务的实际案例
- Netflix:其架构已从单体演进为 SOA(面向服务架构)。每天接收超过 10 亿次来自 800 多种设备的 API 调用,每次调用平均触发约 5 次后端服务调用。
- Amazon:也已迁移到微服务架构。其系统需处理来自各种应用(包括管理 Web 服务 API 和网站本身的应用)的海量请求,这在旧有的两层架构下根本无法实现。
微服务的优缺点
是否采用微服务架构,取决于你的具体需求。以下是其主要优缺点:
优点
- 开发者可独立开发和部署服务
- 可由小型团队开发
- 不同服务可用不同编程语言编写(尽管实践中常不鼓励)
- 易于集成和自动化部署(可使用 Jenkins、Hudson 等开源 CI 工具)
- 代码更易理解与修改,新成员可快速上手
- 可使用最新技术
- 代码围绕业务能力组织
- Web 容器启动更快,部署速度提升
- 修改某部分功能时,仅需重新部署相关服务
- 更好的故障隔离:一个服务失败,其他服务仍可运行(而单体中一处问题可能拖垮整个系统)
- 易于扩展,并可轻松集成第三方服务
- 无需长期绑定特定技术栈
缺点
- 分布式部署使测试变得复杂繁琐,常抵消部分扩展优势
- 服务数量增加可能导致信息孤岛
- 开发者需处理容错、网络延迟、消息格式多样性和负载均衡等额外复杂性
- 作为分布式系统,可能造成重复劳动
- 服务数量激增后,集成与整体产品管理变得困难
- 开发者必须应对分布式系统的固有复杂性
- 需自行实现服务间通信机制
- 跨多个服务的用例若不使用分布式事务,实现难度大且需团队协作
推动微服务向前发展
微服务并非银弹。实施微服务会暴露沟通、协作等方面原本隐性的问题。但可通过以下方式缓解:
- 使用 API 网关可大幅减少构建和 QA 的时间和精力
- 通过 Pactflow 实现契约测试(Contract Testing),可减少对复杂端到端测试的依赖
一个常见问题是跨服务共享 Schema 或验证逻辑。服务 A 所需的数据有效性规则未必适用于服务 B。最佳实践是:
- 采用版本控制
- 通过共享库分发 Schema
库的变更会引发团队间的讨论。但强版本控制也会带来依赖管理开销。建议:
- 规划时注重向后兼容性
- 接受来自外部服务/团队的回归测试,以便在影响他人业务流程之前展开沟通,而非事后补救。
微服务架构如何运作?
1) 单体架构与康威定律(Conway’s Law)
康威定律:“设计系统的组织……其产出的设计结构必然复制该组织的沟通结构。”
设想公司 X 有两个团队:客服与财务。我们本能地将高风险活动分离,但像“客户退款”这类职责归属常存争议。例如:
- “财务团队是否有足够人力同时处理退款和信用额度?”
- “是否应让客服人员处理信用额度,以更好安抚不满客户?”
最终,公司制定新政策:客服可发放信用额度,但退款必须由财务处理。这种职责划分既提升了客户满意度,又降低了风险。
软件设计初期,公司通常组建一个团队启动项目。随着团队扩张,多个项目在同一代码库上并行开发,导致目标冲突:两人若在同一代码区域反向工作,必然引入妥协;人越多,问题越严重(正如 Fred Brooks 所言:“九个女人不能一个月生出一个孩子”)。
此外,公司优先级频繁变动,导致沟通断层。上月全力交付的功能,本月可能因用户反馈问题而无人修复——这正是采用面向服务架构(SOA,包括微服务)的核心动因。SOA 承认管理变更、领域知识与业务优先级之间的摩擦,并提供应对机制。当然,这也需要协调,但能将摩擦集中化、高效化,而非忍受无数小低效。
更重要的是,实施 SOA 或微服务架构强制应用接口隔离原则(Interface Segregation Principle)。在成熟系统中排查问题时,通常是在系统中找到“接缝”或通信点,然后画一条虚线将其分为两半。
但若缺乏深思熟虑,可能意外创造出两个更小但仍在增长的“单体”,仅通过某种“桥”连接。后果可能是关键代码被错误隔离:A 团队不愿维护,B 团队又急需,只能重新实现。
2) 微服务:避免新单体
如何部署相对独立又集成的服务,而不意外生成新单体?
假设你有一个大型应用(如公司 X 示例),正计划拆分代码库和团队以实现扩展。与其寻找一大块完整功能剥离,不如关注应用依赖图的边缘部分——即没有其他模块依赖的部分。
在示例中,“Printer”(打印)和“Storage”(存储)就是理想候选:它们被多次调用,功能明确,且不易被重新发明。将其抽象为外部服务,既能避免单体问题,又符合复用逻辑。
3) 服务对象与数据识别
如何从单体走向服务?一种方法是引入服务对象(Service Objects)。
无需立即移除代码,而是先将其结构化为仿佛已是外部服务。首先,需区分可执行的操作与这些操作的输入输出数据。
例如,以下 Ruby 代码模拟一个任务及其状态:
# 模拟核心事务并执行
class Job
def initialize
@status = 'Queued'
end
def do_useful_work
# ...
@status = 'Finished'
end
def finished?
@status == 'Finished'
end
def ready?
@status == 'Queued'
end
end
要使其更像微服务,可重构为:
# 执行有用工作的服务
class JobService
def do_useful_work(job_status)
# ...
job_status.finish!
return job_status
end
end
# 任务状态模型
class JobStatus
def initialize
@status = 'Queued'
end
def finished?
@status == 'Finished'
end
def ready?
@status == 'Queued'
end
def finish!
@status = 'Finished'
end
end
现在,我们清晰区分了数据模型(JobStatus)与操作逻辑(JobService)。重要的是,JobService 几乎无状态——只要输入数据相同,无论调用多少次,结果一致。
即使 JobService 未来通过网络调用,原有单体应用也无需感知。将其封装为库,并用网络客户端替代原实现,即可平滑演进为可扩展的外部服务。
这就是六边形架构(Hexagonal Architecture):应用核心与协调逻辑居中,外部组件围绕其协同工作。
4) 协调与“哑管道”
微服务与传统 SOA 的关键区别之一在于副作用(side effects)——微服务尽量避免副作用。
以 Unix 管道为例:
ls | wc -l
两个程序串联:前者列出目录文件,后者统计行数。若改为:
ls | less
依然有效。这种组合依赖于可重复的结果、标准的输入输出机制和退出码。
Unix 管道是“哑”的——它没有控制语句,仅按单一职责原则(SRP)将数据从 A 传到 B,由管道成员自行判断输入是否有效。
回到公司 X 的任务与发票系统:两者均可独立使用,也可协同工作。但若无全局策略,难以统一规则。
于是,我们提取出可复用的核心操作:
- 发送发票
- 更新任务状态
- 更新发票状态
这些操作与数据持久化完全解耦。由此可构建两条清晰的流水线:
场景一:用户手动创建发票
- 添加发票数据,状态设为“已创建”
- 调用
BillingPolicyService确定客户付款时间 - 向客户发送发票
- 持久化至发票数据服务,状态更新为“已发送”
场景二:用户完成任务并生成发票
- 验证任务可完成
- 添加发票数据,状态设为“已创建”
- 调用
BillingPolicyService - 发送发票
- 持久化,状态更新为“已发送”
由于发票计算步骤是幂等的,我们还能轻松实现“草稿发票”或“预览应付金额”等功能。
与传统 SOA 不同,微服务暴露的是底层细节+简单接口,而非执行完整业务动作的高层 API。高层 API 往往抹去了可组合的“接缝”,使微组件难以灵活重组。
传统做法常将业务逻辑、策略和规则推入服务总线或集中式工作流引擎。但微服务的真正优势在于:将业务规则封装为与业务需求对齐的离散包。这不仅使策略分布化,还让你能安全地变更业务流程。
SOA 与微服务的区别
“等等,”你可能会问,“这不就是 SOA 的另一个名字吗?”
SOA(面向服务架构)在本世纪初兴起,微服务确实与之相似。一些人认为微服务是 SOA 的精炼形式,另一些人则拒绝将其归为 SOA。
我们认为二者存在足够差异,值得单独定义“微服务”概念(至少可视为 SOA 的一种特殊形式)。
典型区别包括:
- 传统 SOA 重度依赖 ESB(企业服务总线),而微服务使用更轻量、更快的消息机制
- SOA 倾向命令式编程,微服务倾向响应式-Actor 编程风格
- SOA 常使用大型关系型数据库,微服务则常用 NoSQL 或微型 SQL 数据库(可连接传统数据库)
但根本区别在于构建集成服务集的方法论。
在数字世界瞬息万变的今天,能跟上软件演进需求的敏捷开发技术至关重要。微服务的多数实践源自为大型企业开发软件的开发者,他们深知终端用户期望在各类设备上获得动态且一致的体验。
因此,可扩展、可适应、模块化且快速访问的云原生应用需求激增,推动开发者转变思路。
微服务架构的未来
无论微服务是否成为未来主流架构,它无疑是一个强大理念,为企业应用设计与实现带来显著优势。许多开发者和组织虽未使用“微服务”之名,甚至未自称为 SOA,但其 API 驱动的实践本质上已属微服务范畴。
过去,SOAP 通过 WSDL 描述端点操作与发现位置,UDDI 理论上可广告服务能力与位置。但因实现复杂,这些技术在新项目中鲜有采用。REST 服务也面临类似问题,尽管可结合 WSDL,但并不普及。
即便服务发现已解决,在无关应用间共享 Schema 与语义仍是难题——微服务和 SOA 是少数尝试解决此问题的架构。
RDFS、OWL、RIF 等标准化技术虽存在,但未被广泛采用。JSON-LD 和 Schema.org 展示了开放 Web 共享定义的愿景,但在大型私有企业中尚未普及。
不过,标准化定义的力量正在政府领域取得进展。data.gov 和 data.gov.uk 等平台已提供大量结构清晰的关联数据集。
若未来能就大量标准定义达成共识,下一步很可能是智能代理(agents):小型程序可跨厂商编排微服务以实现特定目标。
考虑到 SaaS 应用、可穿戴设备和物联网(IoT)带来的复杂性与通信需求,微服务架构前景光明。