故事背景
最近在解耦一个微服务,这个微服务包含了两大块的功能,数据库运维以及项目构建部署,本身服务名称叫做dbm-service
,所以项目构建部署相关的功能,不应该放在这个服务里,要解耦出来
开搞
- 复制整个
dbm-service
仓库,新建一个project-service
project-service
删掉dbm
相关功能代码dbm-service
删掉project
相关功能代码- 重启
dbm-service
- 新开启
project-service
- 完事
要是有这么简单就好了,想得美
测试环境发现问题
在愉快地进行开发一段时间后,在某一天突然发现
1. 主机 CPU 飙高
2. 在Grafana日志平台上,发现报了大量etcd
连不上的信息,一直在重连
{
"level": "warn",
"ts": "2023-11-20T17:52:16.143+0800",
"logger": "etcd-client",
"caller": "v3@v3.5.1/retry_interceptor.go:62",
"msg": "retrying of unary invoker failed",
"target": "etcd-[endpoints://0xc05e2fa700/xx.xx.x.xx:2376]()",
"attempt": 0,
"error": "rpc error: code = DeadlineExceeded desc = latest balancer error: last connection error: connection error: desc = \"transport: Error while dialing dial tcp xx.xx.x.xx:2376: connect: cannot assign requested address\""
}
自从在测试环境起了 project-service
之后,
3. 之前也出现过类似的问题,定位如下
- 本次更新没改动代码,只改了配置,已查看上次版本更新确认不是代码变动导致
- 怀疑是加载配置有问题,回滚了配置,重启启动服务也失败
- 用了线上配置,本地运行服务,正常无误
- 怀疑是jekins打包程序有问题,本地打包程序放到线上运行,依旧失败
- 补充打印日志信息,报错 listen tcp :0: bind: address already in use
- 确认问题,获取不到空闲端口
- 查看当前tcp连接,发现 ESTABLISHED 占用了2万多个,大部分是连接etcd
- kill掉webhooks服务,然后就释放了这些tcp连接,重启服务就正常了
- 初步分析是webhooks服务,没有释放tcp连接,一直占用
- 但是之前服务已经运行了很久
- 前面提到etcd配置,发现最近确实更新了etcd配置,但都重启了服务
4. 现在定位的原因
- 今天发现测试环境机器的tcp端口号又被占满了
- 查看对应服务占用端口数变化情况:netstat -pnt | grep {对应服务进程id} | wc -l
- 发现project服务占用端口数保持不变,dbm和resource服务占用端口数一直稳步上升
- 怀疑最近新上project服务导致的
- 查看对应机器的tcp监控数据,端口号数量开始上升的时间,恰好跟project服务上测试环境时间一致
- 确定跟project服务有关,一顿测试后
- 发现【project服务少了心跳的rpc接口】,导致project服务虽然注册到etcd上,但是【其他服务却ping不通】
- 其他服务ping不通,就会进行重试,但【重试时只关闭了rpc的连接,没有close掉etcd连接】
- 导致etcd连接一直没有释放掉,而又不断重试,最终把机器的端口号占满
反思
- 对于一些错误,即使不做处理,也应该直接打印到日志里(如,此次调用心跳rpc接口,我定位了很久补上日志,才发现问题出在这里)
- 创建的一些tcp连接,要关注是否有重复创建情况或者有没有close掉(如,此次问题创建的etcd连接异常情况下就重复创建了)