第 1 章 微服务入门
微服务架构是一种将应用程序构建为一组小型服务的方法,每个服务运行在自己的进程中, 服务之间通过轻量级机制(通常是 HTTP/REST API 或消息队列)进行通信。
1.1 单体服务的特点
服务是什么?
简单来说,服务就是一组功能的集合,以标准的接口对外提供功能。 在软件工程中,服务通常指一个独立的程序或进程,它通过网络提供特定的功能。
单体服务(Monolithic Service)是将所有功能都打包在一个程序中的传统架构模式。 它具有以下特点:
开发简单: 所有代码在一个代码库中,容易理解和调试
部署简单: 只需要部署一个应用
测试简单: 可以进行端到端测试
初期开发效率高: 不需要处理分布式系统的复杂性
但随着系统规模的增长,单体服务会面临以下挑战:
代码库膨胀: 代码量增大,难以维护
部署风险高: 任何小的改动都需要重新部署整个应用
技术栈锁定: 整个应用被限制在同一技术栈
伸缩性差: 无法针对特定模块进行水平扩展
可靠性低: 一个模块的故障可能导致整个系统崩溃
1.2 拆分微服务
1.2.1 分而治之以降低复杂性
软件工程中管理复杂性的核心策略就是 分而治之。
1. 分层 (Layering)
经典的应用程序分层:
层次 |
职责 |
|---|---|
表示层 (Presentation) |
用户界面和交互逻辑 |
业务层 (Business) |
核心业务规则和逻辑 |
持久层 (Persistence) |
数据访问和存储 |
数据层 (Database) |
数据库引擎和存储 |
2. 分块 (Modularization)
将系统按业务域划分为独立的模块,每个模块拥有自己的数据和逻辑。 这是微服务架构的前身 —— 领域驱动设计 (DDD) 中 限界上下文 (Bounded Context) 的体现。
1.2.2 分而用之以提高可重用性
将通用功能提取为独立的服务,如:
用户认证与授权服务
通知服务(邮件、短信、推送)
文件存储服务
配置管理服务
这样不同的应用可以复用相同的服务,避免重复建设。
1.2.3 分而做之以提高开发效率
微服务架构允许不同的团队独立开发、测试和部署自己负责的服务, 大大提高了并行开发效率。这与 Conway 定律相吻合:
"设计系统的架构受制于产生这些设计的组织的沟通结构。"
—Melvin Conway
1.3 微服务的特点
1.3.1 微服务架构的特点
微服务架构具备以下核心特点:
服务组件化: 每个服务是一个独立的组件,可以独立部署和替换
围绕业务能力组织: 按业务域而非技术层次来组织团队和服务
产品而非项目: 团队负责服务的全生命周期
智能端点与哑管道: 服务之间通过简单协议通信
去中心化治理: 每个服务可以选择最适合的技术栈
去中心化数据管理: 每个服务管理自己的数据
基础设施自动化: CI/CD 和自动化运维是必需的
容错设计: 服务必须能够优雅地处理故障
演进式设计: 架构应该能够随需求演进
1.3.2 微服务架构的特征
Martin Fowler 总结了微服务的九大特征:
服务组件化
围绕业务组织
产品而非项目
智能端点和哑管道
去中心化治理
去中心化数据管理
基础设施自动化
容错设计
演进式设计
1.3.3 微服务架构的风格
常见的微服务架构风格:
RESTful 微服务: 基于 HTTP/REST 的同步通信
事件驱动微服务: 基于消息队列的异步通信
CQRS 微服务: 命令查询职责分离
Saga 模式: 分布式事务管理
1.3.4 微服务的分类
类型 |
说明 |
示例 |
|---|---|---|
无状态服务 |
不保持会话状态,易于水平扩展 |
API 网关、计算服务 |
有状态服务 |
维护会话或连接状态 |
WebSocket 服务、流媒体服务 |
数据服务 |
负责数据的存取和管理 |
用户服务、订单服务 |
聚合服务 |
聚合多个服务的结果 |
BFF (Backend for Frontend) |
1.3.5 多小的服务才是微服务
关于微服务的"微",有几个指导原则:
一个团队能负责: 通常 2-pizza team (6-10 人) 负责几个微服务
单一职责: 一个服务只做好一件事
可独立部署: 修改一个服务不需要修改和重新部署其他服务
代码量适中: 新人能在几周内理解整个服务
1.4 微服务之道
1.4.1 软件之道
KISS (Keep It Simple, Stupid)
简单是软件设计的最高原则。微服务应该尽量简单,接口清晰,职责单一。
DOTADIW (Do One Thing and Do It Well)
源自 Unix 哲学,每个程序做好一件事。微服务同样应该专注于一个业务领域。
Unix 的哲学
小即是美
让每个程序只做好一件事
尽快建立原型
选择可移植性而非效率
使用纯文本存储数据
充分利用软件的杠杆效应
使用 shell 脚本来提高杠杆效应和可移植性
避免强制性的用户界面
让每个程序都成为过滤器
Python 之禅
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
1.4.2 敏捷之道
敏捷开发强调:
个体和互动 高于流程和工具
工作的软件 高于详尽的文档
客户合作 高于合同谈判
响应变化 高于遵循计划
度量驱动开发与敏捷开发天然契合: 通过度量数据来验证 Sprint 目标的达成, 通过度量指标来指导迭代方向。
1.4.3 微服务的思考
微服务不是银弹,选择微服务架构需要考虑:
团队规模和技术能力
系统复杂度和业务需求
基础设施和运维能力
组织结构和沟通模式
小技巧
微服务架构适合大型、复杂的系统。 对于小型项目,单体架构可能是更好的选择。 可以从单体开始,在需要时逐步演化为微服务。
1.5 土豆微服务案例
本书以一个名为"土豆 (Potato)"的微服务示例贯穿全书。 它本质上是一个 Todo List 待办事项应用,被拆分为以下微服务:
微服务名称 |
职责 |
|---|---|
土豆管理微服务 (potato-server) |
提供待办事项的 CRUD API |
土豆提醒微服务 (potato-scheduler) |
定时检查并发送提醒通知 |
土豆网页微服务 (potato-web) |
提供 Web 前端界面 |
1.5.1 系统架构
整个系统使用以下技术栈:
语言: Java (Spring Boot)
数据库: MySQL
服务发现: Consul
度量数据库: InfluxDB
容器化: Docker + Docker Compose
┌─────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ potato-web │───>│ potato-server │<───│potato-scheduler │
│ (Web UI) │ │ (REST API) │ │ (定时任务) │
└─────────────┘ └──────────────────┘ └──────────────────┘
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ MySQL │ │
│ └──────────┘ │
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ Consul (服务发现) │
└─────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ InfluxDB (度量存储) │
└─────────────────────────────────────────────────────────────┘
1.5.2 快速启动
# 克隆仓库
git clone https://github.com/walterfan/mdd.git
cd mdd/potato
# 启动基础设施
docker-compose start consul influxdb mysql
# 构建并启动所有服务
fab redeploy
1.6 本章小结
本章介绍了微服务的基本概念、特点和设计原则。 从单体服务的局限出发,阐述了微服务的优势和挑战。 通过"土豆微服务"实例,展示了一个典型的微服务架构。
在接下来的章节中,我们将详细介绍度量驱动开发的概念、方法和实践, 展示如何通过度量来提升微服务的质量和运维效率。
注解
关键要点:
微服务不是银弹,需要根据实际情况选择
分而治之是管理复杂性的核心策略
微服务架构需要强大的基础设施和运维支持
度量是微服务成功的必要条件