golang项目工程实践
背景
这几年一直都是在golang相关的服务端开发,经历过几个项目组,发现一些好的实践和一些不好的实践。这里把好的实践总结一下。
仓库与项目规范
- 仓库规范
一个团队一个仓库,比如GoTeam,所有模块放在下面,每个模块的命名用短横线分隔,比如: demo-server, 以-server结尾。其中,协议文件单独放在以proto命名的仓库中, 公共proto放在proto/common 下, 各个server的proto放在各自的目录下,比如proto/demo-server/demo-service.proto,公共库放在common仓库下面。这样我们的项目目录就是:
GoTeam
-proto
--common
---common.proto
---common.pb.go
--demo-server
---demo-service.proto
---demo-service.pb.go
-gocommon
--common
-demo-server
模块名之所以按照这种规范定义,是因为后面建CI/CD流水线的时候,有一个规范的命名和目录接口,方便建立统一的模板。
- 项目部署规范
项目是通过k8s平台去部署的,建立项目名和workload的命名,也需要规范起来。一般来说,一个团队的项目下的模块可以放在一个项目下面,但是要区分环境,比如开发环境,测试环境,预发布环境,正式环境。每个环境作为一个项目,这样我们就有了4个项目:
GoTeam_后端_开发环境
GoTeam_后端_测试环境
GoTeam_后端_预发布环境
GoTeam_后端_正式环境
然后各个模块就可以在各个项目下单独建一个workload, 命名规范和仓库名类似,但是正式环境会有多地部署,需要加上地域后缀做区分,比如:
GoTeam_后端_正式环境
- demo-server-gz
- demo-server-nj
- demo-server-tj
备注:把各个模块放到一起,易于管理,比如加权限的时候不会因为有多项目(每个模块一个项目的方式)而加多次。
框架与公共库
- rpc框架
我们选择的rpc框架是grpc, 主要考虑是开源的,社区完善,有完善的文档和资料,支持http2, 性能足够好。
- 序列化协议
protocol buffer, 这个就不解释了。
- 公共库
我们维护了一个公共库,封装一些组件的使用,比如log, config, mysql, kafka, redis, es, 错误码定义与处理等。其中,配置最好用配置中心,配置中心的配置更易于管理,安全性和时效性也好。
- 自动生成代码
提前创建好一个demo-server, 将公共库的一些基本能力,如日志,配置,拦截器放在demo-server里,然后根据这个demo-server可以通过脚本,基于proto协议文件生成新的服务代码。
分支管理
特性开发的分支管理有两种方式。
一种是基于开关的主干开发模式,这种开发模式是适用于一个模块只有很少人参与开发,一般2-3人以内。基于开关的主干开发模式优点是不用维护多个分支,分支合并的时候冲突解决,它需要维护一些功能开关,每个新特性如果对已有逻辑有影响,则需要新维护一个功能开关。
另外一种是基于分支的特性开发,分支开发,新特性开发拉一个分支,分支开发完成合入到master分支,这里为了避免其他人把你的合入master特性代码发布线上,这里引入一个test分支,待测试的代码都合入测试分支,有修改先在feature分支上修改,修改完成后合入test分支,最后测试通过,将feature分支的代码合入master分支。
CI/CD流水线建设
- 创建服务流水线模板
k8s平台虽然时候可以手动创建服务,但是每次手动创建服务的过程也挺繁琐的,比如需要配置镜像地址,配置端口,基础配置文件,环境变量等。k8s平台会提供一些接口,可以通过流水线创建一个模板,新服务创建的时候自动创建,并部署到对应的集群上。
- 服务更新
服务的更新也可以由流水线触发,这里有两种模式,一种是基于master或者test代码的发布,比如一个feature分支开发完成之后,合入test分支或者master分支,会自动触发测试环境部署流水线。如果要发布线上,需要先手动触发预发布更新流水线,并且在预发布流水线上创建一个tag。更新正式环境的时候,可以用预发布创建好的tag进行发布更新。
日志监控与告警
- 日志
业务系统是不用感知日志系统的存在,正常用日志库打日志即可。在我们服务的基础镜像里,会包含filebeat进程,自动采集日志并发送到ES上。为了方便查询,日志打印的时候需要按照固定的规范,比如可以支持解析trace_id列,后需要查日志的时候可以根据trace_id进行日志查询。
日志的索引最好按照业务线进行创建,并且是天级日志,这样可以通过trace_id将各个模块的日志都能串起来,方便跟踪一个请求的所有日志。
- 监控
监控也是依赖日志,filebeat识别出,对于监控类型的日志,特定的前缀,并且消息体用json格式,将日志记录发往ES(监控索引,方便kibana配置面板), 另外也会发送到kafka, 后续发送到专门的监控平台或者统计平台。
关键的监控项包括:
- 接口成功率
2)接口平均耗时,最大耗时等
-
接口调用量
-
等
- 告警
我们不可能一直盯着监控,当服务异常的时候,通过发消息的方式告警出来,最好将告警通过机器人的方式发送到群里,并且明确指出这个接口是谁负责的,最好也能打印出报错的trace_id,方便查问题。
转载自:https://juejin.cn/post/7397030700455723049