目录
第Ⅰ部分 云原生概述
第1 章 什么是“云原生”应用程序 11
1.1 迄今为止的故事 12
1.2 什么是云原生? 14
1.2.1 可扩展性 .15
1.2.2 松散耦合 .16
1.2.3 韧性 17
1.2.4 可管理性 .19
1.1.5 可观察性 .20
1.3 为什么云原生很重要? .21
1.4 小结 .22
第2 章 为什么Go 语言统治云原生世界 23
2.1 Go 语言诞生的动机 .23
2.2 云原生世界的特性 24
2.2.1 组合与结构化类型 .25
2.2.2 可理解性 .27
2.2.3 CSP 风格的并发 27
2.2.4 快速构建 .28
2.2.5 语言稳定性 29
2.2.6 内存安全 .30
2.2.7 性能 31
2.2.8 静态链接 .32
2.2.9 静态类型 .33
2.3 小结 .34
第Ⅱ部分 云原生Go 结构
第3 章 Go 语言基础 39
3.1 基本数据类型 .39
3.1.1 布尔值 40
3.1.2 简单的数字 40
3.1.3 复数 41
3.1.4 字符串 42
3.2 变量 .42
3.2.1 简短的变量声明 43
3.2.2 零值 44
3.2.3 空标识符 .45
3.2.4 常量 46
3.3 容器类型:数组、切片和映射 47
3.3.1 数组 .47
3.3.2 切片 48
3.3.3 映射 53
3.4 指针 .54
3.5 控制结构56
3.5.1 for 循环 56
3.5.2 if 语句 59
3.5.3 switch 语句 .60
3.6 错误处理62
3.7 可变参函数和闭包 63
3.7.1 函数 64
3.7.2 可变参函数 68
3.7.3 匿名函数和闭包 70
3.8 结构、方法和接口 72
3.8.1 结构 72
3.8.2 方法 73
3.8.3 接口 75
3.8.4 通过类型嵌入实现组合 77
3.9 并发 .80
3.9.1 Go 协程 80
3.9.2 通道 80
3.9.3 select 语句 83
3.10 小结 85
第4 章 云原生模式 87
4.1 Context 包 .88
4.1.1 Context 可以做什么 89
4.1.2 创建Context 90
4.1.3 定义Context 的截止日期和超时 .91
4.1.4 定义请求作用域的值.91
4.1.5 使用Context 92
4.2 本章的主要内容 93
4.3 稳定性模式 94
4.3.1 断路器模式 94
4.3.2 防抖模式 .97
4.3.3 重试模式 102
4.3.4 节流模式 104
4.3.5 超时模式 108
4.4 并发模式. 111
4.4.1 扇入模式 112
4.4.2 扇出模式 114
4.4.3 未来模式 117
4.4.4 分片模式 122
4.5 小结 128
第5 章 构建云原生服务 129
5.1 构建一个服务! .129
5.2 需求 130
5.2.1 什么是幂等性,为什么幂等性很重要? 131
5.2.2 最终目标 133
5.3 第0 代:核心功能 .133
5.4 第一代:单体架构 .135
5.4.1 使用net/http 构建HTTP 服务器 135
5.4.2 使用gorilla/mux 构建HTTP 服务器 137
5.4.3 构建RESTful 服务 141
5.4.4 确保数据结构的并发安全 146
5.5 第2 代:持久保存资源状态 .148
5.5.1 什么是事务日志? 150
5.5.2 将状态存储到事务日志文件 151
5.5.3 将状态存储到外部数据库 165
5.6 第3 代:实现传输层安全 .174
5.6.1 传输层安全 .175
5.6.2 私钥和证书文件 176
5.6.3 使用HTTPS 保护Web 服务 177
5.6.4 传输层总结 .179
5.7 键值存储的容器化 .179
5.7.1 Docker 的基础知识 .181
5.7.2 构建键值存储容器 188
5.7.3 外部化容器数据 193
5.8 小结 194
第Ⅲ部分 云原生属性
第6 章 可信任性 . 197
6.1 云原生的意义 198
6.2 可信任性.198
6.3 什么是可信任性以及为什么可信任性如此重要? 199
6.4 实现可信任性 203
6.4.1 故障预防 205
6.4.2 容错 .206
6.4.3 故障排除 207
6.4.4 故障预测 208
6.5 十二要素应用 209
6.5.1 基准代码 210
6.5.2 依赖 .210
6.5.3 配置 . 211
6.5.4 依赖服务 213
6.5.5 构建、发布、运行 214
6.5.6 进程 .215
6.5.7 数据分离 216
6.5.8 可扩展性 217
6.5.9 易处理性 217
6.5.10 开发环境与生产环境等价 .218
6.5.11 日志 219
6.5.12 管理进程 219
6.6 小结 221
第7 章 可扩展性 . 223
7.1 什么是可扩展性 .225
7.2 四个常见瓶颈 226
7.3 状态与无状态 228
7.3.1 应用程序状态与资源状态 228
7.3.2 无状态的优势 .229
7.4 推迟扩展:效率 .230
7.4.1 使用LRU 缓存的高效缓存 .231
7.4.2 高效同步 234
7.4.3 内存泄漏可能会致命错误:运行时:内存不足 .240
7.4.4 高效 .244
7.5 服务架构.244
7.5.1 单体系统架构 .245
7.5.2 微服务系统架构 246
7.5.3 无服务器架构 .248
7.6 小结 253
第8 章 松散耦合 . 255
8.1 紧密耦合.256
8.2 服务之间的通信 .260
8.3 请求响应消息 261
8.3.1 常见的请求响应实现262
8.3.2 通过net/http 发送HTTP 请求 263
8.3.3 使用gRPC 实现远程过程调用 267
8.4 利用插件实现本地资源的松散耦合280
8.4.1 带有插件包的进程内插件 281
8.4.2 基于RPC 的HashiCorp 插件系统 288
8.5 六边形架构 297
8.5.1 架构 .297
8.5.2 实现六边形服务 299
8.6 小结 307
第9 章 韧性 . 309
9.1 为什么韧性很重要 .310
9.2 系统失效是什么意思? 311
9.3 级联失效.313
9.4 重试请求.321
9.4.1 退避算法 322
9.4.2 断路器 325
9.4.3 超时 .327
9.4.4 幂等性 333
9.5 服务冗余.337
9.5.1 设计系统时考虑冗余338
9.5.2 自动扩展 340
9.6 健康检查.341
9.6.1“健康的”实例意味着什么? .342
9.6.2 三种类型的健康检查343
9.6.3 故障打开 348
9.7 小结 348
第10 章 可管理性 351
10.1 什么是可管理性,为什么我应该关注可管理性? 352
10.2 配置应用程序 354
10.2.1 有关配置的良好实践 355
10.2.2 环境变量配置 355
10.2.3 命令行参数配置 .357
10.2.4 配置文件 363
10.2.5 Viper:配置包中的瑞士军刀 381
10.3 利用特性标志管理功能 386
10.3.1 特性标志的进化 .387
10.3.2 第零代:最初的实现 388
10.3.3 第一代:硬编码特性标志 .388
10.3.4 第二代:可配置标志 390
10.3.5 第三代:动态特性标志 391
10.4 小结 395
第11 章 可观察性 397
11.1 什么是可观察性? 398
11.1.1 为什么我们需要可观察性? .399
11.1.2 可观察性与“传统的”监控有何不同? 399
11.2 “可观察性的三大支柱” 400
11.3 OpenTelemetry 402
11.4 追踪 404
11.4.1 追踪的概念 405
11.4.2 使用OpenTelemetry 进行追踪 407
11.4.3 整合:追踪 420
11.5 指标 427
11.5.1 推式与拉式指标集合 429
11.5.2 OpenTelemetry 的指标 432
11.5.3 整合:指标 444
11.6 日志记录 447
11.6.1 更好的日志记录实践 448
11.6.2 使用Go 标准的log 包记录日志 .452
11.6.3 Zap 日志包 455
11.7 小结 462