1. 后台研发流程
- 缺乏成体系的研发标准导致遇到各种问题
- 作为入职新人,有没有研发流程和标准的文档参考?
- 刚接到一个需求,课堂标准的研发流程是怎样的?(Thanos、Coding、Edudocker、 蓝盾、Tolosty、NoHost、Apollo、七彩石、北极星…)
- 要开发一个 Go 服务,需要遵循哪些研发规范?(服务命名、PB 格式、目录分层、编码 规范、错误码处理、日志打印规范…)
- 都在说 DDD,那么课堂业务涉及哪些业务域,每个业务域分别包含哪些业务模块?
- 服务需要某个功能/函数/方法,有没有直接可以参考的? (比如分布式锁、分布式事 务、用户 UID 获取、两个 slice 求差集…)
- CR 有哪些注意、日志应该如何、错误码如何规范化?
- Git 分支命名提交有哪些规范?服务变更发布规范是怎样的,发布要检查哪些 CheckList,新建 STKE 集群有哪些标准化的?(研发流程一环,事故高发地)
- …
- 常见问题(吐槽较多、延期的部分原因)
- 方案评估:和产品、依赖研发沟通不足,导致后期产品需求变更或技术方案调整
- 需求分工:需求任务拆分不合理(最长路径挂 Owner 自己头上)
- 需求排期:需求排期过于乐观(研发环境、协调沟通、人员请假、紧急问题处理…)
- 需求分析:遗漏产品功能,测试、体验阶段发现
- 需求自测:缺乏自测验证,测试阶段来回返工
- 需求发布:缺乏对生产环境的敬畏,发布引发现网问题(缺乏服务依赖梳理、发布 CR、配置变更、遗漏、上线服务 panic…)
- 线上运营:缺乏监控告警,观测不足,导致对服务可用性存在担忧
- STKE 配置:没有开启 HPA、没有就绪检测导致服务更新告警
- ….
1.1. 在线需求 Owner 工作内容
1.2. 开发人员研发前\中\后节点关注
- 需求研发前(分析阶段)
- 需求预审:输出 tapd 单(出具产品 目标、内容、确认 Owner)
- 需求分析:方案调研选型&输出技术 方案文档(包含背景/架构设计/流程/ 存储/PB 设计/研发 Demo 等)
- 可行性分析
- 资源预估:Owner 预估人力、分工、 时间(确定人/事/时间)
- 需求研发中(编码阶段)
- 研发准备:依赖资源提前申请、代 码预研(准备测试环境/依赖服务/Git 分支)
- 代码编写:实际代码编写和调试 (包含服务分层/编码/CR/Bug 修复 /UT/接口测试…)
- 进度同步:Owner 拉开发群,定期 同步需求进度&风险(包含 PM/产品/ 研发/Leader 等干系人)
- 需求测试:先自测再联调测试(包 含 UT/接口/集成/联调/压力/测试团队 测试,减少返工)
- 需求研发后(发布阶段)
- 需求发布:遵循教育后台发布规 范(包括代码发布、SQL 执行、 配置变更、服务器调整等所有可 能影响线上结果的动作)
- 运营观测:需求涉及服务接口请 求量、资源负载、告警配置(配 备面板观察)
- 需求总结:回顾研发过程得失好 坏,总结经验
1.3. 技术方案模板(包含需求方案、架构设计模板)
- 需求方案模板
- 需求介绍: 需求介绍主要描述需求的背景、目标、范围等
- 需求分析: 全方位地描述需求相关的信息(5W 分析法)
- 复杂度分析: 复杂度常见的有高可用、高性能、可扩展等,要有详细的逻辑推导,避免完全拍脑袋式决策
- 方案对比评估:
- 方案罗列:1~3 个备选方案,每个备选方案需要描 述关键的实现,无须描述具体的实现细节
- 方案要点:性能、可用性、硬件成本、项目投入 、复杂度、安全性、可扩展性等
- 方案选择:不单单考虑性能高低、技术是否优越 这些纯技术因素,结合业务的需求特点、运维团 队的经验、已有的技术体系、团队人员的技术水 平综合评估选择
- 架构设计模板
- 总体方案: 总体方案需要从整体上描述方案的结构,其核心内容就是架构图,以及针对架构图的描述,包括模块或者子系统的职责描述、核心流程
- 架构总览: 从整体上描述方案的结构,给出架构图以及架构的描述包括模块或者子系统的职责描述、核心流程
- 核心流程: 业务或技术处理的核心流程图示说明
- 详细设计: 包括高可用、高性能、可靠性、扩展性、安全性
- 部署方案: 硬件要求、云 PaaS 服务配置、服务容量评估
- 演进规划: 规划和设计的需求比较完善,但如果一次性全部做完,项目周期可能会很长,因此可以采取分阶段实施,第一期做什么、第二期做什么
1.4. 研发进度同步 – TRobot 关联 tapd 单
添加 Robot 机器人 -> 需求进度 -> 需求关联 -> 自动同步
1.5. 课堂研发环境说明
- 研发平台:Coding (CICD、代码安检扫描)
- 代码管理:Git 工蜂平台
- 联调:Edudocker
- 测试:Nohost
- 后台服务快速发布:trpc_edu 脚手架二进制文件同步
- 配置中心:七彩石
- 服务注册:北极星、阿波罗 …
1.6. 需求单\Bug 单提单、关单规范
可以参考此规范要求测试完善 Bug 单内容,降低沟通成本
- BUG 单要求
- bug 标题包含发现版本号、模块、复现描述
- bug 复现地址链接
- bug 详细描述复现步骤
- bug 必现、偶现(偶现概率)
- bug 实际结果和预期结果(描述+截图+视频)
- 原视频和原图
- 附件 bug 验证素材包
- 上传 log,标注一下问题发生确切时间点
- BUG 单关单、转单规范: 尽量都把信息填完整,包括功能测试和现网反馈的单
- bug 单评论信息认真填写
- 码提交 git 时,带上 bug 单 id(
--bug=
),这样在 tapd 单上测试可以很直观的查看到
2. 微服务研发规范
Tips: 先搞清楚 What,才能思考 Why,最后才能去弄明白 How
我已经很清楚研发的流程步骤,那在研发过程中有哪些 规范需要遵循?
2.1. 理解微服务主要思想和原则
- 分治思想,微服务拆分的度?
- 康威定律/two 披萨思想,业务域/微服务拆分,RPC 等
- 拆分带来的挑战:一致性、全连监控、服务治理、服务维护…
- 数量众多的服务 CICD
参考:https://martinfowler.com/articles/microservices.html
2.2. 需求分析交付件 – iwiki 技术方案文档规范
2.2.1. 需求文档写在哪?
Tips: 业务域下尽量符合 MECE 原则,这样后 续找文档也会更加“内聚”
按业务域 > 业务需求 > 要点文档(序号 – 标题方式编写)
2.2.2. 需求文档标准模板内容参考
- 需求背景:说明清楚整体需求背景/核心问题/业务目标等
- 解决方案:产品/技术解决方案概述
- 技术选型:若存在多套可行方案,提供方案优劣对比
- 架构设计:画出整体架构设计
- 服务规划:规划采用哪些服务实现业务需求
- 核心流程:画出关键的业务流程/时序图
- 接口设计:设计服务提供的能力,输出接口 PB 设计
- 存储设计:使用的存储,缓存设计
- 容量预估:预估服务的调用量,后续做资源申请和压测评估
- 信息记录:每次群/会议/线下沟通的结论/待定信息做备注,方便回溯,避免遗漏
参考: https://iwiki.woa.com/page s/viewpage.action?pageId= 1049743017
2.3. 微服务初始化 – 业务域、所属模块确认
Tips:不合理的起微服务导致服务扩散过快,以至于服务边界不清晰、职责不够内聚,结果就是维护成本持续增加
2.3.1. 新起服务的流程
- 做好需求分析,明确服务提供的能力,敲定划分领域,起好服务名字
- 拉模块 Owner、Leader 沟通& 同步,确保服务定位清晰
2.3.2. 新起服务前,应该能够清楚回答下面几个问题?
- 新服务提供了哪些能力?(提供能力)
- 新增的命令字,是否一定需要新起服务?,是否有更合适的服务承载? (维护成本)
- 服务后续规划会扩充哪些能力?(扩展性)
- 服务归属的业务域/功能模块,是否能很好圈定所起服务?(DDD 思想)
- 服务是否边界清晰,职责明确?(单一职责)
- 服务是否涵盖太多能力,是否需要做进一步拆分?(KISS 原则、维护 成本)
- 服务命名是否清晰?(命名)
- 是否大家都有共同认识,组内有无其他建议?(共识)
2.3.3. 研发规范:遵循课堂业务域以及功能模块最新划分
Tips: 领域划分就是让所有人形成业务共识,清晰业务域边界,无论是业务、产品、研发
2.4. 服务领域、模块划分
参考: 腾讯课堂后台模块划分
2.5. 研发规范:微服务初始化 – PB 存放、命名约定
Tips: 上帝的归上帝,凯撒的归凯撒,PB 协议生成的内容,本应该与框架无关,仅与语言有关
2.5.1. PB 文件仓库
- java 服务 pb 管理:
git.woa.com/csig_edu_pay_service/edu-pb-collection.git
- bingo 服务 pb 管理(按业务域划分):
git.woa.com:ketang-service/pb/bingo.git
- trpc 服务 pb 管理(按业务域划分):
git.woa.com:ketang-service/pb/trpc.git
2.5.2. PB 命名约定
- pb 文件名:
go_edu_{server标识}.proto
,server 描述不应该超过 2 个单词 - Server 命名:
go_edu_{server标识}
- Service 命名:
go_edu_{server标识}
,trpc 的一个 server 对应多个 service,通常为 1:1 - package 命名:
trpc.ketang. go_edu_{server标识}
- go*package 路径:
git.woa.com/ketang-service/pb/trpc/{业务域标识}/{模块标识}/ go_edu*{server 标识}
2.6. 研发规范:微服务初始化 – PB 范例
2.6.1. package 和 go_package 约定
syntax
协议采用 PB3 版本,package 按格式约定package
名以 trpc.ketang 为固定前缀开头,后面接 server 名字全称,服务名仅支持小写、下划线,比如go_edu_lighthouse_manage
option
指明go_package
位置
|
|
2.6.2. 研发规范:微服务初始化 – PB stub 生成
|
|
2.6.3. 生成的 stub 桩代码 RPC、App、Server、Service、Method 名字
查看go_edu_lighthouse_manage.trpc.go
文件:
|
|
2.7. 研发规范:微服务初始化 – DDD 服务目录分层
2.7.1. 进入业务模块 & 初始化项目目录
|
|
2.7.2. 目录分层说明
app
为应用层,内部主要包含四层:application
: 应用层完成对业务领域进行服务编排,文件后缀用_app.go
结尾,另外像redis
这类操作需要在应用层来实时domain
: 业务领域层,业务核心逻辑实现,其内包含- 领域实体
entity
: 领域内的实体对象,后缀_entity.go
- 仓储接口
repository
: 领域服务依赖的接口,后缀_repos.go
,其内定义的仓储接口后续被基础设施实现 - 领域服务
service
: 领域对应用层提供的服务能力,后缀_service.go
- 领域实体
infrastructure
: 基础设施层包含对仓储接口的实现,文件后缀_infra.go
,常见有rainbown
、rds
、rpc
、db
、kafka
等操作等interfaces
:接口层,主要做参数校验、DTO 数据转换等操作,后缀_intf.go
- conf 为服务配置,通过后缀区分不同环境 yaml 配置:
\_pro.yaml、\_test.yaml、 \_dev.yaml、pre.yaml
- internal: 内部包,仅给服务内使用,暂不对外提供引用
2.7.3. 课堂 DDD 示例
- layout demo: https://git.woa.com/csig_edu_ketang_service/go_edu_ddd_layout_demo
- ddd 服务:
2.7.4. DDD 的相关知识了解
- https://km.woa.com/group/29048/articles/show/476578
- 极客时间 - 《DDD 实战》
2.8. 微服务初始化 – Handler 服务目录分层
// todo
2.9. 微服务初始化 – Yaml 配置(global, server)
trpc 的 yaml 配置包含 4 个部分: global、server、client、 plugin,yaml 的配置参数采用小写
yaml 配置文件位置放在 /conf
下:
- 开发:
/conf/trpc_go_dev.yaml
- 测试:
/conf/trpc_go_test.yaml
- 生产:
/conf/trpc_go_pro.yaml
2.9.1. 配置 yaml 示例
|
|
- global
- 环境空间 namespace: Prdouction/Test/Development
- 环境名 env_name: 可不填
- server
- server 定义的:格式:
go_edu_{srv描述}
,Git 仓库名、 Coding 平台、服务名、主调服务必须使用该名称,便于统一,示例:go_edu_lighthouse_manage
- server 定义的:格式:
service
定义,支持trpc
和qapp
协议- trpc 协议格式:
trpc.ketang.{二级模块名}.go_edu_tob_lighthouse
,端口奇数号(5 位数) - qapp 协议格式:
trpc.ketang.{二级模块名}.go_edu_tob_lighthouse_qapp
,端口奇数号+1
- trpc 协议格式:
2.9.2. client
Tips: yaml 的 client 部分,需要放到七彩石配置中, key 为 client.yaml
- client 用于配置被调服务,支持统一的 namespace、timeout,每个被调服务也有 name、protocol、target 部分
- service 部分
name
格式: 和被调服务命名保持一致target
格式: 使用北极星做服务发现timeout
: 支持针对下游单独配置超时protocol
: 支持 trpc/qapp
- yaml 的 client 部分,需要放到七彩石配置中, key 为
client.yaml
2.9.3. plugin
Tips: plugin 部分为 trpc 框架的组件依赖,默认必备组件:
selector
: 服务发现组件,限定使用北极星polaris
,用于当前服务通过何种 组件发现被调服务,最终会通过选择器获取注册 的被调服务的 IP、Port,用于后续的 RPC 请求log
: 日志组件,默认文件file
输出,用于当前服务的日志如何管理、 输出位置、切割方式等config
: 配置组件,默认采用七彩石rainbow
配置组件tracing
: 全链路跟踪组件,教育这边统一用trpc_edu_log
进行日志分析
2.10. 编码规范
2.10.1. main.go 文件编写
Tips: main.go 仅包含仓储实现和服务初始化,不包含其他代码处理逻辑
2.10.2. 研发规范:golang 代码规范参考
2.10.3. 研发规范:编码测试 - trpc 接口本地调试
安装 trpc_ui 工具,参考 iwiki 官网: https://git.woa.com/trpc-go/trpc-cli
~/.bashrc
配置一个别名,方便快速启动:alias trpc_ui_run='trpc-ui run --port=8000 >> /data/logs/trpc/trpc-ui.log 2>&1 &'
- 执行
trpc_ui_run
,然后通过访问 8000 端 口: http://localhost:8000/trpcui/#/tRPC-UI - 选择加载我们的 proto 文件,ip 端口配置下
- 本地运行服务,然后通过 trpc-ui 请求调试,完成了一个本地简单 CMD 闭环
2.10.4. 研发规范:编码测试 – 单元测试
测试框架选择: https://github.com/golang/mock
Golang 单测 Tips:
- 先从最简单的 testing 包学习(无外部依赖的输入/输出测试)
- 面向接口编程,了解依赖注入、控制反转的思想
- 利用 gomock 框架的 mockgen 尝试对 go 的接口打桩,实现简单 mock test case
- 尝试让自己的代码更易于测试(代码行数控制、面向接口编程、依赖注入)
- 搞清楚测试的目标,要验证哪些内容,不要为了测试而测试
- 单测代码也需要维护
2.10.5. 命令执行
|
|
2.10.6. 其他 UT 资料参考
2.11. 研发规范:GIT 使用规范 – 分支命名、提交规范、发布
2.11.1. Git 分支命名规范
分支名 | 命名规范 | 分支作用 | 示例 |
---|---|---|---|
主干分支 | master | 主干分支,和现网代码保持同步 | master |
特性分支 | feature/xxx_20220101 | 特性开发分支,提交和发布都需要先和 master 同步 | feature/login_tracelog_20211103 |
Bug 修复分支 | bugfix/xxxx_20220101 | 通常有 Bug 单和 Bug 排期 | bugfix/login_tracelog_20211103 |
Tag | v主.次.修订版本 | 多用于 Library 库 | v1.0.1 |
2.11.2. Git 分支管理流程
- 新建特性分支,比如
feature/lighthouse_20220323
,用作多人协作开发分支 - 开发人员基于特性分支 Check 出自己开发分支:
feature/lighthouse_20220323_mars
feature/lighthouse_20220323_gold
- 各种开发完代码后,合入特性分支,完成 CR:
- 同步
feature/lighthouse_20220323
feature/lighthouse_20220323_mars
->feature/lighthouse_20220323
- 同步
- 发布阶段
2.11.3. Commit message 规范
- bug 改动:
--bug=bugid+空格+本次改动说明
- 需求改动:
--story=tapdid+空格+本次改动说明
- 其他改动:
--other=本次改动说明
2.11.4. Git 分支操作规范
- 提交推送代码之前,必须先同步远端代码,解决冲突完后方可推送到远端仓库
- MR 被 Approve 合入过程,发现目标分支有冲突,需要提 MR 同学先解决冲突后,再次重新提交 MR
- MR 被 Merge 过程,需要提供 ChangeList 说明合入改动点和影响
2.11.5. 分支发布规范
走 Coding 发布,统一走主干发布,发布时候提供指定的 CommitID 或者 Tag 名称
2.12. 研发规范:CodeReview 规范
Tips: 新起的服务更应该把 CR 做扎实,避免“破窗效应”
2.12.1. CR 基本要求
- CR 平台:都在 GIT 平台上进行,便于回溯和统计
- CR 频次:
- developer 以 1 天维度,遵循小批量提交
- reviewer 最迟隔天完成 CR
- CR 规模:控制在 400 行代码以内
- CR 备注:提意见要具体,不要模棱两可(可以补充伪代码或示例代码)
2.12.2. CR CheckList
- 代码设计: 服务职责、代码架构设计、分层、文件命 名、接口设计
- 业务逻辑: 业务流程问题、边界问题、数据一致性等
- 运行性能: 锁冲突、协程泄露、SQL 索引
- 编码规范: 错误处理、可读性问题、测试用例、代码风格、注释、命名等(参考 go-standard 标准提升) 5 编码安全:账号越权问题、SQL 注入、CSRF、XSS 等问题
2.12.3. 其他资料参考:
- Go Readability 总结
- https://iwiki.woa.com/pages/viewpage.action?pageId=955680960
2.13. 研发规范: 微服务组件选型约定
组件 | 说明 | 必须使用 |
---|---|---|
RPC | 远程调用相关 Client 组件 | Share 库实现 |
DB | 数据库 Client 相关组件,包含 mysql、mongo、clickhouse、influxdb 等组件 | Mysql、TDSQL |
Cache | 缓存相关组件,包括 ckv、redis 等 | Redis |
MQ | 消息队列相关组件,主要包含 kafka、rabbitmq 组件 | Kafka |
Config | 配置组件,包含 etcd、七彩石、apollo 等组件 | Rainbow |
Storage | 存储组件,主要包含 cos、nfs 远端文件存储组件 | Cos |
Search | 搜索组件 | ES |
全链路 | 链路日志跟踪 | ELK+Jager |
面板监控 | 支持将 STKE、全链路 ES、腾讯云、Prometheus 等数据源收集起来,统一展示 | Grafana |
远程日志 | 远程日志 | CLS |
数据上报 | 服务内关键业务数据上报组件 | Atta |
第三方库选型,遵循无传染开源协议,优先采用扩展性、稳定第三方库:
- 第三方库对比:https://go.libhunt.com
- Awesome-Go: https://awesome-go.com/
- kit 工具使用: https://github.com/go-kit/ki
2.14. 研发规范:服务日志规范 – 日志级别、内容格式
2.14.1. 采用正确的日志级别打印日志
日志级别 | 日志作用 | 补充说明 |
---|---|---|
trace | 非常具体的跟踪信息,仅用于开发调试,问题处理完后,打印日志代码会被清理掉 | 开启 trace 级别,需要临时打印日志记录,过后需要删除 trace 跟踪日志 |
debug | 非常具体的调试信息,仅用于开发调试,原则不在现网使用,特殊情况(现网 Debug)过后,需要关闭 | 开启到 debug 级别,在特定的代码位置,输出 debug 信息,为问题分析提供详细日志(开发调试、生产特殊情况) |
info | 现网日志信息,通常用于辅助问题定位和分析 | 特定的代码位置,输出 info 信息,用于辅助问题定位和分析,有时候还会起到统计作用 |
warn | 服务出现了一定问题,代码做了一定容错,仍然能继续运行 | 比如 DB 查询失败,有降级返回缓存信息 |
error | 服务出现严重问题,无法完成正常的业务处理,必须有人处理和跟进 | 比如数据库查询失败、RPC 网络调用超时、严重的业务逻辑或错误、nil 指针等 |
2.14.2. 日志格式要求
- 要求内容格式完整:用英文描述,包含主体、动作、事件,避免打印冗余的日志信息,避免有效日志信息被淹没
- 避免重复打印:避免每层函数打印重复日志,在最底层位置打印即可
- 携带上下文信息打印:通过 log.ErrorContextf、logInfoContextf 格式化输出,并附带请求上下文信息
- 特定标识区分关键信息:利用 “()”、“[]” 框出关键信息,比如 uid、aid 信息,用 log.Infof、logErrorf 格式化输出
2.15. 研发规范:错误码映射、划分、命名规范
2.15.1. 错误信息在接入层对外做错误码映射
2.15.2. 错误码管理
- 错误码:
服务ID(3位)
+错误类型(2位)
+错误编号(3位)
– 服务 ID 与录入 Coding 的服务 ID 对齐 - 命名:
ErrXxx=errs.New(code, msg)
,遵循驼峰命名,使用git.code.oa.com/trpc-go/trpc-go/errs
- 包名:错误码统一防止在根目录的
/errcode/errcode.go
文件内,包名为errcode
,示例:errcode.ErrInputParams
2.15.3. 错误码分段
|
|
2.16. 研发规范:七彩配置规范
Tips: 默认配置中心使用 Rainbown 七彩石服务作为配置中心
2.16.1. 七彩石配置文件
七彩石配置 key 文件,推荐统一使用 rainbowcfg
包名,放在服务的基础设施层:app/infrastructure/rainbowcfg/rainbowcfg.go
|
|
2.16.2. 七彩石配置键名规范
- 键名格式:必须全部用小写、点、下划线组成,通常以模块开头,通过点号
.
分割模块,名称支持下划线_
分割 - 过期时间类:
ttl.
开头,示例:ttl.uid_info、ttl.contact_info - 服务配置类:
conf.
开头,示例:conf.redis、conf.mysql、conf.kafka、conf.clickhouse_dsn - 业务配置类:模块.开头,实例:user.phone.dft_head_url、user.guest.dft_head_url
2.17. 研发规范:缓存使用规范
2.17.1. 缓存配置文件
缓存配置关联的 key 文件,推荐统一使用 rds
包名,同基础设施放一起:app/infrastructure/rds/rdkey.go
对应缓存读写实现,放app/infrastructure/rds/rds.go
,涉及非常多模块的缓存读写,可以继续拆分rds.go
文件,比如user_rds.go
、course_rds.go
2.17.2. Redis 键名规范
键名格式:全部采用小写模式,名称支持下划线_
,均采用%d
进行 format 格式替换
依赖库:git.woa.com/edu-online/share/component/cache/rdshand
示例:
|
|
2.18. 研发规范:MYSQL 库、表、列、索引创建使用规范
2.18.1. 命名规范
库、表、列、索引命名均采用小写和下划线_
,禁止使用大写、连字符来命名,命名不要太长或太短,应该确保语义清晰
- 库名::尽量保持与应用名一致,库名选定应该和存储业务数据范围有关联关系
- 表名::
- 必须
t_
前缀 - 表名使用集合术语或名词,不使用复数
- 禁用保留字做表名
- 必须
- 列名:
- 禁用
f_
前缀 - 列表必须包含字段
- 主键 ID,统一采用
id unsigned bigint
- 记录变跟时间,
created_at
,格式采用 DateTime,加好索引 - 记录更新时间,
updated_at
,格式采用 DateTime,加好索引 - 记录删除时间,
deleted_at
,格式采用 DateTime,加好索引(不要用 del_flag)
- 主键 ID,统一采用
- 特定字段约束
- 后台运营操作,需要包含统一
operator
操作记录人
- 后台运营操作,需要包含统一
- 禁用
- 索引名:
- 采用
idx_
开头,例如idx_phone_number
- 采用
2.18.2. 存储规范
优先考虑业务的扩展性,尽可能规避业务增长需要改表存储宽度的问题,具体显示宽度参考 MYSQL 存储占用
- 数字:正数都加上
unsigned
;较小枚举类型,统一用unsigned tinyint(1)
或unsigned tinyint(2)
类型 - 文本:长度较小字符串,统一采用
varchar(255)
,存储占用 length 为1+length(实际字符)
;中等长度字符串可以采用varchar
或者text
- 日期时间:优先采用
DateTime
格式
2.18.3. 索引规范
- 针对
where
条件、order by
、having
、join
等 SQL 查询,优先考虑增加索引 - 关联索引注意列查询的顺序,通过
explain
检测索引命中情况
2.18.4. SQL 编写规范
- 关键字大写,比如 SELECT、FROM、WHERE 等
- 适当分行增加可读性
- 连表数量尽量控制在 3 张表以内,过多连表 Join 操作危害占用过多 DB 内存和计算资源
2.18.5. Mysql 规范更多学习参考
- https://git.woa.com/standards/sql
- https://www.sqlstyle.guide/
- 极客时间 - 《Mysql45 讲》
2.19. 编码安全规范:通用、业务代码安全规范
2.19.1. 业务代码安全规范
- 输入校验:请求数据量上限、查询类型等
- 访问控制:通过权限控制,防越权问题
- 日志记录:人为操作需要有操作日志流水记录表
- SQL 操作:预编译+参数绑定
- 文件上传:限制上传大小、文件类型
- Web 跨域:CORS 限制等
- 会话管理:CSRF 防护、防重放攻击
- 并发控制:使用并发安全的 map、数据一致性问题
- 表单处理:入参检测、入参类型限定、XSS 防护
- 内容过审:接入信安等防护检测系统,确保平台内容输出内容符合国家安全法规
2.19.2. 通用安全规范
- 内存安全:协程泄露、nil 指针、panic 等
- 文件操作:文件、目录的权限控制,授权校验,防止越权访问
- 系统接口:限定安全 CMD 等
- 通信安全:TLS 等、Token 票据校验
- 数据安全:加密存储、打码脱敏输出
- 加密解密:秘钥不存代码、不用弱密码
2.19.3. 更多参考
- https://git.woa.com/standards/security/blob/master/Go安全规范.md
- 腾讯基础安全库 Iwiki 文档
3. 服务发布变更规范
我的服务已经开发完成准备发布,应该关注哪些内容?
3.1. 发布规范知悉 - 前\中\后动作
Tips: 发布动作包括代码发布、配置发布、SQL 执行、服务器调整
3.1.1. 发布前准备
- 是否完成有效的 CR
- 是否是核心模块,提前知会
- 确认容量评估和压测指标
- 确认灰度方案和回滚方案
- 确认发布检测方法
- 确认是否高峰期/禁止发布期
- 通过 Leader 发布评审
- 发布群周知
3.1.2. 发布中执行
- 按量灰度,不要一把梭
- 有效检测,确认发布正常(配置/接口流量/服务日志/错误码/DB 存储/产品体验…)
- 发布异常要及时上升 Leader
- 发布异常要确认,不能存侥幸
3.1.3. 发布后值守
- 常规模块值守
> 1H
- 核心模块值守
> 2H
,例如接入层、账号、资料、房间、课详、下单、支付、入口页等 - 关注告警群是否有异常
- 亲自体验功能是否符合预期
- 发布结果同步
- 发布收尾(代码合并、发布单关单等)
3.2. 服务容量评估(业务规模、压测、服务性能等)
Tips:发布之前做好服务容量评估,做到知己知彼
3.2.1. 容量评估
- 业务规模:预估系统的访问规模(基于业务方提供的数据,结合分布式链路的依赖推断)
- 服务性能:选定运行容器的 CPU、内存后,通过压测得到服务单一 Pod 的性能情况(控制 CPU 利用率在 70%以下)
- 机器资源:业务规模/服务阈值得到预估实例数(结合 STKE 平台的 HPA 做到弹性扩缩容)
3.2.2. 压测类型选定
- 单命令字压测:针对高频命令字,在星海平台进行压测测试(示例参考)
- 全链路压测:针对课堂线上环境产品进行全量系统的压测(通常在大型需求/活动上线前后)
- 场景压测:针对特定模块场景下进行压测(比如房间百万 PCU 压测)
3.2.3. 压测结果分析
- 性能指标:失败率、RT 时延、吞吐量、错误信息为压测最常关注指标
- 分析与优化:针对压测性能不符合预期,结合代码做优化,重复压测流程直至性能达标
- 结果同步:在发布 CheckList 中罗列服务容量以及压测结果数据,方便关系人知悉服务性能基本情况
3.3. DB 变更操作规范
3.3.1. 操作平台:DBS
统一采用 DBS 操作,禁止使用 MYSQL 客户端对生产 DB 数据进行变更操作
3.3.2. 账号授权:最小授权原则
- 业务 DB 读写账号按权限开发,禁止使用 root 账号
- 业务日常管理的账号,仅开放 Select 查询权限,最小权限开放
- root 账号由业务模块负责人统一管理
3.3.3. 现网 DB 变更流程:SQL 自测验证、风险评估、灰度操作、避开高峰期操作、操作知会
- 自测验证:
- 在测试 DB 自测验证无误后,方可在提交生产执行
- 风险评估:
- 清楚 SQL 执行后对现网用户的影响(比如更改大表长时间锁表对用户使用造成影响)
- 执行性能评估(比如 SQL 批量导出更新,通过 Explain 评估耗时)
- Select/Update/Delete 操作增加 Limit 限定
- 涉及 DB 迁移类的处理,必要时拉上腾讯云 DB Helper 一起评估
- 灰度操作:
- Update、Delete 批量操作,增加限定 Limit,评估性能、结果是否符合预期
- 避开高峰期操作:
- 常规业务高峰:上午 8:00~10:00、下午 2:00~4:00、晚上 7:00~9:00
- 特定业务高峰:疫情高峰、指定大会等,通常都有指定的发布时间窗口
- 特殊情况需要走 Leader 申请审批
- 操作知会:
- 变更周知 Leader 以及相关模块核心人员
3.4. 服务监控告警
tips: 通过服务监控清楚知道服务业务访问情况、有哪些应用和系统错误,是否对业务有影响 包括服务调用量、错误监控、资源使用情况等
3.4.1. 监控内容
- 全链路监控:配置 ke.oa.com 上的服务监控,配置服务命令字的 RT、错误码监控
- SKTE 资源监控:默认 Coding 自动配置 SKTE 资源监控
- 云服务监控:云上告警各个组相关配合注意事项
3.4.2. 监控面板
相比离散的监控图表,可以将全链路、STKE 资源通过 Grafana 进行聚合呈现,让监控更体系化!
面板示例参考: 账号质量看板、账号机器资源看板、直播间监控看板、课堂核心指标看板
3.4.3. 告警群关注
全链路告警、STKE 告警、在线云资源告警、拨测告警
3.5. 发布 CheckList
tips: 对生产环境抱有敬畏之心
3.5.1. 发布须知
- 心态和清晰的头脑是至关重要的,清晰完备的 CheckList 可以尽可能规避人为因素的影响
- 不管是成功还是失败,都要做好发布同步周知,不要闷头处理
- 发布期间遇到问题时,优先保证恢复服务可用性,再来分析导致问题原因
3.5.2. 发布 CheckList 清单参考
- 发布前知会:对生产做的任何变更都需要提前知会 Leader 和干系人,避免突发状况无法应对
- 遗留问题:是否还有代码 Bug 没有解决,是否影响发布的节奏
- 变更知会:发布后功能用户是否有感知,是否会对用户有影响,提前同步客服同学
- 性能测试:服务是否高频核心服务,是否满足业务性能指标
- 埋点/上报:新功能按需做好数据上报、日志埋点,用于后续数据对比和分析
- 日志完善:日志级别是否改成 info 级别日志,info 级别的日志是否能够快速定位问题
- 开关控制:支持特性/灰度/白名单开关控制,快速控制影响范围(比如代码重构、新产品功能特性)
- 代码 CR:发布前,确保代码通过组内 CodeReview
- 资源申请:提前走流程申请好云上资源
- 服务配置:DB、Redis、依赖服务等配置信息提前准备
- 服务依赖:确定服务发布依赖顺序,以及依赖服务是否需要扩容,做到提前知会依赖服务负责人
- 数据备份:涉及存储数据批量变更,需要提前做好数据备份
- 灰度方案:灰度方案是否合理,参考灰度发布规范
- 功能验证:提前准备好服务正确性校验方法(比如 Toltoy、Curl、Postman、产品主流程体验等)
- 突发预案:提前准备好回滚流程、异常处理方案应对突发预案,降低失败发布影响面和时长
- 人员安排:大型需求发布后,需要安排人值守观察,方便遇到问题第一时间同步(比如手机号、大型活动)
- 进度同步:发布进行/成功/失败,在发布群同步周知
- 代码合并:发布完成后,是否完成分支代码的合并
3.6. 灰度发布,尽可能控制发布的影响面
tips:必须有服务灰度过程、有效的发布检测以及发布失败处理方案
3.6.1. 灰度发布过程
- 自行校验:踢流量,发布节点后自行校验
- 灰度校验:
- 按名单灰度:针对名单内的 UID,服务走灰度逻辑
- 按用户灰度:针对命中规则(比如特定尾号)的用户 UID,服务走灰度逻辑
- 按流量灰度:通过负载均衡,控制访问服务的真实用户流量
- 灰度周期:
- 核心基础服务(比如 CGI、Tiny 通道、账号、 订单支付、直播房间、资料等基础服务)需要拉长灰度时间
- 有效的发布检测:
- 后台服务:通过 Tolsoty 接口+用例,检测 CMD 是否符合预期
- CGI 检测:通过 Curl、Postman、Paw 等工具,检测 CGI 的 URL 是否符合预期
- 存储查询:请求服务处理后,查询存储写入是否符合预期、消息队列有无消息等
- 产品体验:通过预发布环境产品亲自体验,检测灰度是否符合预期
- 关注监控指标: 关注监控指标(全链路/云监控/STKE 监控)
- 发布回滚: 遇到异常立即启动应急预案(踢流量、回滚 Pod 镜像)
- 全量发布:通过负载均衡,分批扩大用户校验,直至全量 发布窗口期(特定节假日前、高峰时间段、晚间时间发布),需要向 Leader 申请发布报备
3.6.2. 服务发布:SKTE 配置要点
STKE 关键指标汇总:https://iwiki.woa.com/pages/viewpage.action?pageId=944586615
3.6.3. STKE 工作负载配置标准化指标
- 固定 IP、PreStop 停止前冷静时间、服务就绪探针、服务存活探针
- 内核参数(somaxconn)
- HPA 弹性扩缩容(3 ~ 5 倍,结合服务容忍度配置,通常高并发服务 25~30%负载比较合理,常规服务 45%左右比较合适)
- STKE 事件告警(工作负载扩缩容、Pod 调度、销毁事件)
3.6.4. 容灾部署
- 核心服务应用,必须多区域工作负载,避免区域资源扩容限制
- 核心服务存储,同城多活、异地灾备(成本考虑)