Chap 2 演化式架构师
三个层次:
- 战略目标
- 架构原则
- 设计和交付实践
Chap 3 如何建模服务
What makes a good service?
松耦合,高内聚
Bounded context 限界上下文
一个给定领域都包含多个限界上下文, 每个限界上下文中的模型一部分需要与外界通信,另一部分不需要。
Or define as:
一个由显式边界限定的特定职责
- 共享特定的模型,而非内部表示。
- 一般来说,微服务应该清晰地与限界上下文保持一致。
- 避免过早划分边界。逐步划分上下文
- 考虑功能,而非共享数据
- 即首先“这个上下文干什么”,再考虑“它需要什么样的数据”。
Chap 4 集成
理想的集成技术
- 避免破坏性修改:
- 更改某个服务导致其消费方发生改变
- 保证API的技术无关性
- 使服务易于消费方使用
- 隐藏内部实现细节
数据库集成
最常见,但应当避免,因为:
- 暴露内部实现细节
- 绑定了特定技术
- 破坏内聚性
服务间通信
同步与异步(加回调)
- 即请求/响应或基于事件
服务间协作
编排与协同 Orchestration and Choreography
- 协同可降低耦合度,但需要跨服务的监控
(Orchestration of Microservices, Choreography of SOA ?)
请求/响应
对于请求/响应方式,考虑两种技术:RPC和REST
RPC
- SOAP, Thrift, protocol buffers, RMI
- 技术耦合,过度抽象
REST
- RPC的替代方案
- 资源的概念
- 底层协议常使用HTTP
- 动词复用(GET,POST
- 生态系统(Varnish HTTP缓存代理,mod_proxy LB)
JOSN Or XML
JSON
基于HTTP的REST的缺点
- 无法生成客户端的桩代码,RPC可以
- 超媒体控制需要自行实现
- 一些Web框架无法支持所有HTTP动词(PUT,DELETE)
- 性能,不如二进制协议(Thrift)
- 序列化自行实现
异步协作
对于基于事件的异步协作方式,考虑:微服务发布事件机制和消费者接收事件机制
- MQ或者HTTP(ATOM)
事件驱动架构和异步编程有一定复杂性,谨慎选用。(监控和并联ID)
响应式扩展(Reactive extensions, Rx)
- 组装多个调用的结果,并执行操作
DRY
- 微服务内部避免,跨服务情况下可适当违反(减少耦合)
客户端库
- 简化服务的使用,避免不同消费者间重复代码
- 不要包含与目标服务相关的逻辑
按引用访问
- 避免资源失效
- 缓存,取舍
版本管理
- 破坏性修改:及早发现,尽可能延迟
- 语义化的版本管理
- 不同版本的接口共存
UI
- 不同交互形式的约束
- API组合
- UI片段的组合
- BFF(Backends For Frontends,为前端服务的后端)
- API聚合接口层,对多个后端调用进行编排,为不同设备定制
Chap 5 分解单块系统
接缝
分离数据库:
- 打破外键
- 共享静态数据(e.g. 国家代码)
- 共享数据:抽象为提供数据的服务
- 共享表:拆成两张
事务边界
分布式事务
- 事务管理器
- 两阶段提交(所有投票成功则提交)
Chap 6 部署
- CI
- 每个微服务都有一个源代码库和CI构建
- 构建流水线和CD(持续交付)
- 定制化虚拟机镜像(可作为构建物)
- 不可变服务器
- 服务与主机间的映射(尽量单服务-单主机/容器)
- 自动化一切
虚拟化:
- Hypervisor+虚拟机
- Vagrant: 用于开发和测试
- Linux容器(内核相同)
- Docker
Chap 7 测试
测试类型
测试象限 -》 右图
测试范围
- 测试金字塔:
- 用户界面测试
- 服务测试
- 单元测试
- 服务测试
- 绕开UI,直接针对服务的测试
- 端到端测试
- 覆盖整个系统, 打开浏览器操作UI
减少测试所用时间,加强反馈
元版本
- 整个系统使用一个版本号:加强了耦合
测试场景,而非故事
消费者驱动的测试
- CDC, consumer-driven contract
部署后再测试
- 冒烟测试
- 蓝/绿部署:两个版本,只有一个接受真正的请求
- 金丝雀发布:部分生产流量引至新部署的版本,并检验其预期
MTBF
Chap 8 监控
- ELK
- 更多日志
- 综合监控
- 合成事务 /语义监控
- 关联标识:跟踪调用
- 级联故障:监控系统间的集成点
对于每个服务:
- 最低限度:请求响应时间,下游服务的健康状态
- 标准化如何收集和存储指标
- 标准格式,记录到标准位置:方便聚合
- 监控底层操作系统:跟踪流氓进程,进行容量规划
Chap 9 安全
核心:
单点登录(Single Sign-On)
服务间身份验证和授权
- 边界之内允许一切
- 很常见
- 无法抵抗中间人攻击
- HTTPS
- 避免通信窃听或篡改
- SSL证书管理麻烦
- 不能被反向代理服务器缓存
- SAML/Open ID Connect
- 为客户端创建账户/服务账户
- 客户端证书
- TLS
- 似乎比SSL更麻烦
- 特别重要的数据通信时考虑使用
- HMAC
- 基于哈希的消息码
- Part of OAuth specification
- e.g. AWS S3 API
- API密钥
静态数据的安全
- 使用众所周知的加密算法
- 自行实现非常不靠谱
- 一切系于密钥
- 单独的密钥库或者安全设备
- 选择加密目标
- 更细粒度的服务,区分不同安全级别
- 按需解密
- 首次加密,按需解密,且不保存结果
- 加密备份数据
深度防御
- 防火墙
- 日志
- 入侵检测(和预防)系统
- IDS Intrusion Detection Systems
- IPS Intrusion Prevention Systems
- 启发式,可信范围内积极寻找可疑行为
- 网络隔离
- 服务放在不同网段,控制之间的通信
- 定义对等互连规则(peering rules)
- e.g. VPC of AWS
- 操作系统
- 持续打补丁
社会工程学
Chap 10 康威定律和系统设计
康威定律(Conway’s law)指出:
organizations which design systems … are constrained to produce designs which are copies of the communication structures of these organizations.
- 任何设计系统的组织,最终产生的设计等同于组织之内、之间的沟通结构。
松耦合组织与紧耦合组织
服务所有权分配
- 共享服务
- 特性团队
- 所有服务共享
试图将服务所有权与同地团队匹配,两者亦与组织限界上下文匹配
Chap 11 规模化微服务
故障无处不在
- 假设一切都可能失败
多少是太多?
- 跨功能需求
- 响应时间/延迟
- 可用性
- 断路器
- 超时
- 舱壁(bulkhead)隔离
反脆弱
- 主动引发故障,拥抱故障
- e.g. Netflix Chaos Monkey
幂等操作
- HTTP的GET和PUT具有幂等语言,但是仍需要自行实现
扩展(无状态的服务)
- 目的:
- 可用性与性能
- 方案:
- 更强大的主机
- 拆分负载
- 分散风险
- 负载均衡(避免单点故障)
- 基于Worker的系统
- 重新设计
扩展数据库
- 扩展读取
- 缓存
- 只读副本
- 扩展写操作
- 分片
- 共享数据库基础设施
- CQRS模式
- Command-Query Responsibility Segregation 命令查询职责分离
缓存
- 缓存在哪里?
- 客户端缓存
- 反向代理/CDN缓存
- 服务器缓存
- HTTP缓存
- 为写使用缓存
- 后写式(writebehind)缓存
- 为弹性使用缓存
- 使用失效但可用的数据
- 隐藏源服务
- 保护源服务
- 后台异步重建缓存
- 保持简单
- 缓存越多越难追踪
自动伸缩
CAP定理
- 一致性(Consistency)
- 访问多个节点能得到同样的值
- 可用性(Availability)
- 每个请求都能获得响应
- 分区容忍性(Partition Tolerance)
- 集群中的某些节点无法联系之后,整体还能继续服务的能力
- 此三个方面最多只能保证其中的两个
(CAP theorem is considered incomplete in many papers, an extended version PACELC theorem is preferred)
AP系统
服务发现
- DNS
- 标准化,支持多
- 部署麻烦
- 动态服务注册
- Zookeeper
- Consul
- Eureka
文档服务
Chap 12 总结
微服务的原则
- 围绕业务概念建模
- 接受自动化文化
- 隐藏内部实现细节
- 让一切都去中心化
- 可独立部署
- 隔离失败
- 高度可观察