复盘我从0开发文件上传中间件,上线一年多遇到的疑难杂症

原创 吴就业 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这两个文件系统。以至于只要出现问题,都是非常头疼的问题,有的耗时一周、一个月解决,有的甚至无能为力。

难题一:上传MFS文件MD5不一致

在测试阶段,我们发现通过这个中间件上传文件到moosefs后,moosefs上存储的文件的md5与本地原文件md5不一致,如果是图片,能很明显的看出少了一块像素。

问题的根因是我们找的开源组件在实现文件读写存在协议上的bug,这个开源组件的start数只有几个,应该是一个demo组件,并未经过生产的验证。

关于bug的详细描述可以阅读这篇文章:“被开源组件坑惨了,文件上传到MFS后MD5不一致

这个之所以成为难题,是因为moosefs官方只推荐挂盘方式使用,内部的api是不暴露的,所以没有任何的文档资料。我是通过去阅读moosefs的c++源码,从源码中找出我们用到的协议。

难题二:疑是go-ceph导致的内存泄漏

这个问题难在几个容器基本同一时间一起挂掉,而且不是内存慢慢涨上去挂掉的,而是突然说挂就挂,没有一丝丝防备。通过jemalloc的dump信息也看不出来任何的问题。

虽然这一篇文章(“Go写的文件上传中间件内存泄露问题排查”)说通过用例覆盖找到了问题,但实际上只是找到了另一个隐藏的内存泄漏问题,一个开源webp库存在内存泄露,后面找到google开源的webp库替代解决。但上线后一段时间还是出现了一次内存泄漏,现象一致,但出现的频率低了,所以猜测是存在两个内存泄漏问题的,与ceph相关的我们还是没找到原因。

难题三: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艺术”的水印。

文章推荐

Go服务几个副本同时OOMKilled的诡异问题排查

最近出现一个非常诡异的现象,这个服务部署4个节点,几乎每次4个节点都是同时挂的。挂掉的原因都是OOMkill。

文件上传ceph首次下载耗时慢问题排查

据业务反馈,AI生成图片上传后,首次立即下载耗时可能需要几秒,且出现概率极大,很容易复现。如果是上传后,过个几秒后再下载,耗时则只需要几百毫秒。

中间件服务上线,那跟电影里的拆炸弹一样刺激

而针对这种大迭代的发版,根本原因还是要解决灰度粒度问题,支持流量粒度,支持全链路的灰度。

全球化的IM产品技术架构调研

主要调研学习Slack和WhatsApp这两个产品的全球化架构,单数据中心或是多数据中心,怎样做架构设计,能够解决异地多活和延迟问题。

Go语言内存泄漏问题排查实战-记一次线上容器重启问题排查

代码中,与tls有关的地方就是发送https请求从s3下载文件,所以检查下载文件调用链路上是否存在可疑的内存泄漏,发现如下疑点。统计了访问日记,发现确实经常出现响应403。所以问题就清晰了,由于403是有body的,没有close响应的body导致的内存泄漏。

Java内存GC故障问题排查实战-推送系统频繁GC告警问题排查

记录一次工作中实战的Java内存泄漏问题排查,Pod重启后无法查看现场,但通过gc日记可以确认存在内存泄露,并通过运行一段时间发现有个Java类的实例数量非常高。