模块一 Web 框架
教学目标:
- 掌握如何设计并且实现一棵前缀路由树,支持通配符匹配,路径参数
- 掌握 HTTP Server 和 Context 的设计,并且提供丰富 API
学习和工作中的痛点:
- 用过很多 Web 框架,但是并不了解 Web 框架的原理,并不知道怎么注册路由,怎么执行路由匹配
- 面试的时候无法清晰阐述前缀路由树的原理,在实际开发中,不知道如何快速定位 404 之类的错误
- 不知道如何设计统一的 Session 抽象,支持 Session 运行在本地内存或者 Redis 上
- 无法灵活运用 Web 框架提供的 AOP 方案解决登录校验、鉴权、日志、tracing、logging 等问题
实践练习
- 设计一个 HTTP Server,该 HTTP Server 将会基于前缀路由树支持路由通配符匹配、路径参数、正则匹配
- 为 HTTP Server 添加静态资源支持(CSS、JS 等),并且提供缓存和内存控制功能
- 为 HTTP Server 添加 Session 功能
- 为 HTTP Server 添加模板引擎功能,并提供基于 Go 模板的默认实现
- 利用该 HTTP Server 实现简单的用户 API,支持注册、登录等
- 利用该 HTTP Server 的 AOP 方案解决登录校验、日志、tracing 和 metric 问题
- 利用该 HTTP Server 的 Session 功能,维护登录态
详细内容
第一周
- Web 框架概览与核心设计:Server、Context 和路由树
- 核心接口设计:Server 抽象和 Context 抽象
- 开源实例:Gin、Beego 中的 Server 和 Context 抽象
- 开源实例:HttpRouter、Gin、Beego、Echo 和 Iris 中的路由树设计
- 代码演示:实现前缀路由树,支持通配符匹配和路径参数
第二周
- Kratos 中 Middleware 的设计与实现
- 代码演示:为 Web 框架提供 AOP 支持,并且支持
第三周
- 开源实例:Gin、Beego、Iris 和 Echo 中的文件上传和下载功能
- 开源实例:Gin、Beego、Iris 和 Echo 中的静态资源支持
- 代码演示:设计并实现一个可配置、可扩展的静态资源处理器
- 开源实例:Beego 中的 Session 模块、Gin 的 Session 扩展
模块二 数据库查询 —— ORM 框架
教学目标
- 掌握对象-SQL 映射,掌握不同数据库查询语言差异
- 掌握数据库查询结果集-对象映射,能够使用反射和 unsafe 高性能处理结果集
- 掌握 ORM 对数据库事务的支持,以及常见的事务扩散解决方案
- 掌握 Web 框架、微服务框架和 ORM 框架结合的全链路观测
学习和工作中的痛点
- 在日常工作中,数据库查询占了相当大比例的工作内容,但是大多数时候只会使用简单的增删改查,不知道如何观测数据库查询的性能,也不知道如何使用 ORM 框架的高级查询
- 只知道当使用 ORM 框架的时候,它会把对象转化为查询,再把结果集转成对象,但是不知道这个过程是怎么进行的,在面试的时候就无法解释清楚
- 无法结合 WEB 框架、微服务框架、ORM 框架等整条链路上的各个中间件设计高级解决方案,如全链路观测
实践练习
- 设计并实现一个 Buffer Pool,并且能够控制内存使用量
- 实现简单的 SELECT、UPDATE、DELETE 和 INSERT 支持
- 支持复杂查询,包含 JOIN、子查询和 UNION 查询
- 支持使用反射和 unsafe 两种实现来构造 SQL 以及处理结果集
- 综合利用模板编程和 AST 编程,为 ORM 框架生成辅助方法
- 使用自己的 ORM 框架替换用户系统中的数据库查询模块
- 综合已有的微服务可观测性模块,集成 ORM 可观测性,做到全链路观测用户服务性能
- 为自己的 ORM 框架设计简单的 AOP 方案,并且支持慢查询监控
- 为自己的 ORM 框架添加事务支持,提供事务闭包 API
- 重构用户服务的缓存功能,改用 ORM 的回调机制支持缓存
详细内容
第四周
- SELECTOR 起步:支持 FROM 和 WHERE
第五周
- 进阶语法:context 和 channel 编程
第六周
- 支持 MySQL、SQLite3 和 PostgreSQL
- INSERT、UPSERT 和 UPDATE 中的零值处理
- 数据库可观测性:接入 log、tracing 和 metric
- 开源实例:Beego、GORM 和 ENT AOP 方案
第七周
- 代码演示:结合 AST 编程和模板编程设计代码生成
模块三 缓存客户端
教学目标
- 掌握本地缓存设计和实现方案,控制本地缓存占用内存,过期时间处理
- 设计统一 API,同时支持 Redis 缓存和本地缓存
- 掌握缓存模式:cache aside、read through、write through、write-back
- 掌握装饰器模式、singleflight 模式、全局 singleflight 以及优化方向
学习和工作中的痛点
- 缓存在工作中大量使用,但是基本只会最简单的用法,也就是形如 cache-aside。无法利用装饰器等设计模式优雅封装缓存操作,以支持不同的缓存模式
- 不了解缓存击穿、缓存穿透和缓存雪崩,或者听说过,但是不知道在代码上怎么实践
- 知道或者使用过单机 singleflight,但是没有实践过全局 singleflight,也不知道有什么技巧可以避免全局锁
- 听过 Redis 可以用于实现分布式锁,但是不知道怎么写,或者写出来的分布式锁考虑不周全
- 缓存一致性的解决方案听过很多,但是落地到代码就不知道怎么处理
实践练习
- 手写一个本地缓存,能够控制缓存超时、控制内存占用量
- 为用户服务替换自己手写的本地缓存,同时为用户服务接入 Redis
- 使用装饰器模式实现缓存模式 read-through、write-through、write-back,并在用户服务中应用两种模式
- 综合利用缓存模式解决缓存穿透、缓存击穿和缓存雪崩问题
- 为用户服务的本地缓存提供预热功能和定时刷新功能,缓解数据不一致问题
- 利用 Redis 实现一个分布式锁,并且结合 singleflight 模式来减少分布式锁竞争
详细内容
第八周
- 进阶语法:sync.Mutex 和 sync.RWMutex
- 代码演示:如何用 sync.Mutex 将一个非线程安全的类型封装为线程安全的类型
- singleflight 模式和全局 singleflight 模式:
- 进阶语法:sync.WaitGroup、errgroup.Group 和 singleflight
- 代码演示:全局 singleflight 模式和性能优化
- 缓存预热、缓存异步刷新、缓存定时刷新、缓存随机超时时间
第九周
- 缓存击穿、缓存穿透和缓存雪崩详解,综合利用缓存模式、预热、缓存异步刷新、缓存定时刷新、随机超时时间等手段解决问题
- 业务相关负载均衡算法与 singleflight 方案
模块四 微服务框架 —— RPC 模块
教学目标:
- 掌握 RPC 协议的设计理念,了解 Dubbo 协议和 gRPC 协议设计
- 掌握代理模式和代码生成两种策略对应的 RPC 实现机制,并能选择任一策略实现一个简单的 RPC 框架
学习和工作中的痛点:
- 用过很多 RPC,却搞不懂 RPC 究竟是怎么运作的。既不清楚 RPC 是怎么把请求发过去服务端的,也不清楚服务端究竟是怎么解析请求、执行调用的
- 面试对 RPC 原理说不出所以然来,对业界常见的 RPC 协议也不甚了解,一问就哑口无言
- 遇到问题的时候,无法深入到源码定位问题,更加无法通过捕捉网络传输报文来定位问题
实践练习
- 为自己的 RPC 协议添加 one-way 调用支持
- 使用自己设计的 RPC 框架,实现一个简单的用户服务,完成注册、登录两个基本功能
详细内容
第十周
- 捕捉本地调用信息,获得调用的服务名、方法名、参数类型和参数值
- 结合 AST 编程和代码生成策略,捕捉本地调用信息
- RPC 协议设计详解,并且设计最简单的 RPC 协议
- RPC 头部字段设计,包含魔数、版本字段、消息长度字段、头部长度字段、消息 ID、序列化协议、压缩算法
- 在 RPC 协议里面携带链路元数据,如 trace id、AB 测试标记位、压测标记位
第十一周
- 服务端解析报文、重建调用上下文、查找本地服务、完成调用、回写结果
模块五 微服务框架 —— 服务注册与发现模块
教学目标:
- 了解常见的可以充当服务注册中心的中间件,包含 ZooKeeper、etcd、Nacos 等
- 掌握常见微服务框架的服务注册与发现的 API 设计,并能进一步阅读其源码
学习和工作中的痛点
- 不了解服务注册与发现的模型,也不了解客户端、注册中心和服务端三者究竟如何协作
- 面对业界各种中间件,不知道注册中心选型应该要考虑什么,不知道各个中间件之间的优劣
- 说不清楚服务启动、服务注册的顺序,不了解微服务优雅关闭的正确步骤
实践练习
- 为自己的 RPC 框架添加服务注册与发现功能,提供基于 ZooKeeper、etcd 或者 Nacos 的任意实现
- 设计统一的 API,允许用户接入自定义的服务注册与发现实现
- 为支持测试,提供一套绕开服务注册与发现的机制,直接指定目标节点的 IP 和端口
- 为自己的 RPC 框架添加优雅退出功能,并且暴露钩子函数,允许用户自定义自己退出的必要步骤
- 为用户服务接入优雅退出功能,确保用户服务在关闭之前能够结束当前事务并且释放数据库资源
详细内容
第十二周
- 开源实例:Dubbo-go、Kratos 中的服务注册与发现 API 设计
- Dubbo-go、Kratos 中基于 ZooKeeper 的实现
- 开源实例:EGO、Dubbo-go 和 Kratos 启动过程与注册过程分析
模块六 微服务框架 —— 节点筛选与负载均衡
教学目标:
- 掌握微服务框架 Cluster 算法、API 设计与实现
- 掌握业界常见的微服务框架的负载均衡 API 设计与实现
学习和工作中的痛点
- 对微服务框架如何筛选出目标节点的整个过程不了解,不了解 Cluster、路由和负载均衡三重抽象
- 在一些场景之下,不知道该怎么把请求同时发送到多个节点,也不知道怎么根据请求对服务端节点进行动态分组,并且把请求发送到特定的分组
- 不了解或者只在算法层面上了解负载均衡算法,没有真实落地写过实现
- 当需要自定义负载算法的时候,不知道怎么接入自己使用的微服务框架
实践练习
- 为自己的微服务框架添加 Cluster 功能,实现最简单的 fail over 策略,在服务端一个节点失效的情况下,自动选择另外一个节点重试
- 为自己的微服务框架添加路由功能,提供标签路由或者条件路由的实现
- 为用户服务接入分组功能,将用户分成普通用户和 VIP 用户两个分组,其中普通用户访问普通节点,VIP 用户访问 VIP 节点
- 为用户服务接入自定义负载均衡算法,该算法用用户 ID 来实现哈希一致性算法,并在服务端引入本地缓存,缓存用户数据
- 为用户服务接入路由功能,模拟 AB 测试将流量分别打到 AB 对应的服务节点上
详细内容
第十三周
- 筛选节点:Cluster、路由和负载均衡的三重抽象
- 开源实例:Dubbo-go 中 Cluster 的设计和主要实现
- 开源实例:Dubbo-go、Kratos 的负载均衡 API 设计与实现
模块七 微服务框架 —— 可用性和可观测性
教学目标
- 利用 AOP 解决方案接入可观测性:log、tracing 和 metric
学习和工作中的痛点
- 不了解或者只在算法层面上了解熔断、限流和降级的算法。时常对熔断、限流和降级感到困惑,搞不清楚它们之间的区别与联系,不知道什么时候应该用熔断、限流或者降级
- 听过很多可观测性的问题,但是不知道它包含什么。或者知道 log、tracing 和 metric,但是不知道怎么接入自己的项目,即便是在接入的时候,也不知道要观测一些什么样的数据
- 自己的业务需要有自定义的熔断、限流和降级的策略,但是不知道怎么实现,也不知道怎么在自己使用的微服务框架里接入
- 在读微服务框架源码的时候,总不太能理解这些框架是怎么利用统一的方案来解决可用性和可观测性问题的
实践练习
- 为自己的微服务框架设计 AOP 解决方案,可以考虑利用洋葱模式、责任链模式、拦截器等方案
- 为自己的微服务框架接入可观测性方案,其中 tracing 用 OpenTelemetry、metric 使用 Prometheus
- 为自己的微服务框架提供熔断、限流和降级的默认实现,包含固定窗口、滑动窗口、漏桶和令牌桶算法
- 为用户服务开启可观测性功能,部署 OpenTelemetry 的服务端和 Prometheus,查看采集的数据
- 压测用户服务,并且分别设置熔断、限流和降级的策略,采集压测数据并且观察使用策略的效果
- 在压测结束之后,为用户服务设置故障恢复策略,并且确认用户服务在一段时间后能够恢复正常处理请求的状态
详细内容
第十四周
- 开源实例:Beego、Dubbo-go、Kratos 中的 API 设计
- log:设计 Log API,允许用户接入自己的日志采集框架
- tracing:OpenTelemetry 简介以及接入 OpenTelemetry,微服务 tracing 采集数据
- metric:Prometheus 简介以及接入 Prometheus,微服务 metric 采集数据
- 开源实例:EGO、Beego、Dubbo-go、Kratos 中的可观测性实现
- 代码演示:为微服务框架添加 logging、OpenTelemetry、Prometheus 支持
- 开源实例:Dubbo-go、Kratos 中的 API 设计与实现
模块八 —— 课程总结与范式提炼
教学目标
学习和工作中的痛点
- 设计模式听了学了很多,但是始终无法在合适的场景中应用
- 不知道如何设计测试用例,也无法判断是否遗漏了测试用例
- 不懂得如何撰写技术设计文档,或者在工作中不需要撰写技术文档,导致接到一个需求,完全不知道该如何下手
实践练习
- 为 ORM 支持建表语句撰写技术文档,并且设计测试用例
详细内容
第十五周
- 总结在整个训练营中使用到的测试技巧和设计测试用例的技巧
项目案例
案例一:由浅入深手写 Web 框架实现用户注册登录
内容
- 设计并实现前缀路由树,支持通配符匹配、路径参数匹配和正则匹配
- 设计并实现 AOP 方案,提供 logging、tracing、metric、panic 恢复和错误页面支持
- 设计并实现一个静态资源服务器,利用缓存加速并且控制住缓存内存使用量
- 基于前两者,实现简单的用户注册、登录服务,并且利用 AOP 接口做用户级的限流
案例二:从 0 到 1 手写 ORM 框架优化服务性能
内容
- 支持 SELECT、INSERT、DELETE、UPDATE、UPSERT
- 支持反射和 unsafe 两种处理器,并压测比较两者性能差异
- 设计并支持 AOP 方案,提供慢查询监控、查询黑名单、logging、tracing、metric 支持
- 利用模板和 AST 为 ORM 框架设计代码生成命令行工具,生成用户友好的辅助方法
案例三:统一缓存 API 和 Redis 实现缓存模式提升缓存服务性能
内容
- 利用装饰器模式实现 read-through、write-through、write-back 缓存模式
- 利用 Redis 实现一个简单分布式锁,利用 singleflight 减少全局锁竞争
案例四:从 0 到 1 搭建微服务框架
内容
- 基于 RPC 协议支持 Cluster、路由和负载均衡功能
- 基于 RPC 协议设计 AOP 方案,并利用 AOP 接口支持熔断、限流和降级
- 将自己的用户服务从单体应用重构为微服务架构,并且添加完善的服务治理功能