原创 吴就业 127 0 2024-03-02
本文为博主原创文章,未经博主允许不得转载。
本文链接:https://www.wujiuye.com/article/c0ad881c23064597a28b3a574cd9394a
作者:吴就业
链接:https://www.wujiuye.com/article/c0ad881c23064597a28b3a574cd9394a
来源:吴就业的网络日记
本文为博主原创文章,未经博主允许不得转载。
上传虽不是业务非常重视的能力,但却也是业务不可缺少的能力。
我们内部研发的罗马上传中间件,主要解决通用的文件上传场景,为业务提供简单的接入能力。
该中间件通过统一的上传API,屏蔽S3、OSS、OBS、MinIO、Ceph、MFS等文件系统的差异,支持分片上传API。业务使用同一个SDK可将文件上传至任意的文件系统,并可客户端直传文件到S3等云存储服务,可动态切换文件系统等。
基于云原生背景做的架构设计,对于mfs和ceph这类文件系统,我们并未采用挂盘的方式去使用,因为当时缺少运维提供PVC能力,所以mfs我们采用基于底层通信协议去读写文件,我们找到了开源的sdk。而ceph则用官方提供的go-ceph库。从上线开始到现在,遇到非常多棘手的问题,都是因为这两个文件系统所致。
根本原因是因为我们hold不住mfs和ceph这两个文件系统。以至于只要出现问题,都是非常头疼的问题,有的耗时一周、一个月解决,有的甚至无能为力。
在测试阶段,我们发现通过这个中间件上传文件到moosefs后,moosefs上存储的文件的md5与本地原文件md5不一致,如果是图片,能很明显的看出少了一块像素。
问题的根因是我们找的开源组件在实现文件读写存在协议上的bug,这个开源组件的start数只有几个,应该是一个demo组件,并未经过生产的验证。
关于bug的详细描述可以阅读这篇文章:“被开源组件坑惨了,文件上传到MFS后MD5不一致”
这个之所以成为难题,是因为moosefs官方只推荐挂盘方式使用,内部的api是不暴露的,所以没有任何的文档资料。我是通过去阅读moosefs的c++源码,从源码中找出我们用到的协议。
这个问题难在几个容器基本同一时间一起挂掉,而且不是内存慢慢涨上去挂掉的,而是突然说挂就挂,没有一丝丝防备。通过jemalloc的dump信息也看不出来任何的问题。
虽然这一篇文章(“Go写的文件上传中间件内存泄露问题排查”)说通过用例覆盖找到了问题,但实际上只是找到了另一个隐藏的内存泄漏问题,一个开源webp库存在内存泄露,后面找到google开源的webp库替代解决。但上线后一段时间还是出现了一次内存泄漏,现象一致,但出现的频率低了,所以猜测是存在两个内存泄漏问题的,与ceph相关的我们还是没找到原因。
文件上传后首次下载耗时非常慢,正常最慢都不可能超过1秒,文件的大小只有几十byte,耗时也要几秒,这个现象非常奇怪。
我们经过go语言提供的pprof和trace工具,问题定位到go-ceph这个库依赖的cephfs这个libc库的Open和Read方法非常耗时,但是ceph服务并不存在性能问题。详细描述可看这篇文章:“文上上传ceph首次下载耗时慢问题排查”
我并无法像排查mfs问题一样去排查ceph,即便我们用bpftrace等eBPF工具追踪到底层。因为我对ceph一无所知,一样无法解决问题。
关于bpftrace可以阅读这篇文章:“如何使用bpftrace追踪系统调用性能问题”。
经过一年的折磨,对mfs文件系统算是很了解了,但是ceph文件系统,还是非常的陌生,无奈,我们只能重构ceph,通过PVC挂盘ceph使用,把难题抛给专业运维人员。
前期的技术选型非常重要,理想的架构自然好,但要考虑团队有没有人能hold住,出了问题是否能解决。如果hold不住,技术选型应该保守一点,可以不那么完美。
本文经「原本」原创认证,作者吴就业,访问yuanben.io查询【2T7J4YA6】获取授权信息。
声明:公众号、CSDN、掘金的曾用名:“Java艺术”,因此您可能看到一些早期的文章的图片有“Java艺术”的水印。
代码中,与tls有关的地方就是发送https请求从s3下载文件,所以检查下载文件调用链路上是否存在可疑的内存泄漏,发现如下疑点。统计了访问日记,发现确实经常出现响应403。所以问题就清晰了,由于403是有body的,没有close响应的body导致的内存泄漏。
记录一次工作中实战的Java内存泄漏问题排查,Pod重启后无法查看现场,但通过gc日记可以确认存在内存泄露,并通过运行一段时间发现有个Java类的实例数量非常高。
订阅
订阅新文章发布通知吧,不错过精彩内容!
输入邮箱,提交后我们会给您发送一封邮件,您需点击邮件中的链接完成订阅设置。