前言
由于某开发项目的特殊性,在开发过程中需要将一些核心的代码加密。但是项目一开始就是由swoft框架(一个基于swoole的PHP框架)进行开发,未找到swoft代码加密工具。因此想到了将核心代码迁移到Golang里面,两者通过rpc进行通信。
项目情况
后端服务是由一个golang开发的http服务(以下称gateway)以及swoft框架开发的rpc服务。gateway也需要开启rpc服务,给swoft调用核心代码。一个请求进来,先给到gateway,然后通过rpc请求到swoft,如果需要调用到核心加密代码,swoft会通过rpc调用gateway。项目是部署在k8s上面运行。大致的结构如下:
最近通过检查容器发现,部署的服务居然每个一段时间就会Resatrt一次。不对劲!
检查历程
在发现问题的第一时间,初步估计可能是程序有BUG,报错导致服务中断。立马查看gateway以及swoft的日志,但查看了一遍日志发现,日志都是新的。因为日志并没有做持久化,容器重启会清掉日志文件。那么只能通过k8s,挂载一个文件夹进去用于持久保存日志文件。
过去几天后,再次检查日志,却并没有发现任何报错信息,无论gateway和swoft,都没有发现服务有中断的情况。那究竟是什么原因导致容器重启?突然隐隐约约想到一个细思极恐的可能,那就是可能发生内存泄漏,导致了k8s节点内存爆了,k8s自动去重启容器。通过几天的观察,发现有些其他的容器,会莫名被销毁挤到另外的节点上去,更加深了内存泄漏的猜测。
既然是内存泄漏,那gateway与swoft都有泄漏的可能,只能都检查一遍了。通过呕心沥血的代码审查,终于发现了一处可疑之处。在gateway建立rpc连接的时候,并没有将其释放掉。苦煞我也!在开发的时候,并没有注意到这一点,导致内存泄漏。
另外,为了避免swoft也有内存泄漏问题,也对swoft框架进行了设置。由于swoft框架是用的是swoole,只需要通过设置max_request,给worker进程一个最大任务数。worker进程再完成此数量任务后,会释放所有内存和资源,退出进程。然后重新启动一个新的worker进程,避免内存泄漏。
通过gateway的代码以及swoft的配置后重新将项目部署上k8s。经过两周的观察,终于没再发现容器Restart的情况。
所以告诫各位开发者,在开发期间必须时刻注意释放回收变量,少用静态变量、全局变量,以免导致内存泄漏。开发时候一时爽,内存泄漏泪两行。
以上就是本期分享,如果大家对此感兴趣,欢迎各位关注、留言,大家的支持就是我的动力!
标签:泄漏,swoft,查障,rpc,内存,修复过程,日志,gateway From: https://blog.51cto.com/u_15345191/5886797