106

Discord 怎么用 Go 和 C++ 来每天 Resize 1.5 亿张图片

 6 years ago
source link: https://zhuanlan.zhihu.com/p/31066649?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Discord 怎么用 Go 和 C++ 来每天 Resize 1.5 亿张图片

编程话题下的优秀答主
简评:Discord 开源了自家基于 C++ 和 Go 的图片大小调整库 - Lilliput,看起来性能还不错。

Discord 是一款国外的免费实时通话软件,主要面向游戏玩家,因此你可以简单的将其理解为国外的 YY。

尽管 Discord 主要是一个语音和文字的聊天应用程序,但其每天还是会处理超过一亿张图片,而处理这么大量的图片算是一个挺大的技术问题了。如果直接链接图片会把用户的 IP 地址泄露图片主机,并且大图片还会占用大量的带宽。为了避免这些问题,就需要一个中间服务来从用户获取图片,然后调整它们的大小以减少宽带使用。

Image Proxy

在一开始,Discord 创建了一个名为 Image Proxy 的 Python 服务,从远程 URL 获取图像,然后使用 pillow-simd 包来调整图片大小。在此之上还设置了一个缓存层,会缓存部分已经调整了大小的图片。HAProxy 层会将基于 URL 哈希了的请求路由到 Nginx 缓存层,可以很大限度的减少所需调整图片的数量。缓存和代理的组合也足以应对数百万的用户了。

不过,随着用户数量的进一步增长,Image Proxy 也开始出现了不足的地方。最大的问题是没有平均分配工作量,这阻碍了吞吐量。响应时间的差异也很大,有些甚至需要几秒钟才能完成。

正好 Discord 也打算更多的使用 Go,这里也正是个尝试新技术的好地方。

Media Proxy

重写一个正在工作的服务不是一个轻松的决定,不过 Image Proxy 比较简单,因此重写和替换所需的工作也相对比较少。除了更快的响应请求,新服务还可以从 .mp4 和 .webm 视频中获取第一帧。因此新服务叫 Media Proxy。

首先,当然是先对 Go 语言已有的调整图像大小的包进行了测试,但结果并不怎么好。虽然 Go 相对于 Python 普遍情况下会更快,但没有一个已有的包在性能上能优于 Pillow-simd。Go 虽然在处理 HTTP 方面能稍微快一点,但更多的性能瓶颈其实还是在调整图像大小的操作上。

没办法只能动手创建了自己的 Go 语言 Image Resize 库 - Lilliput,通过 Cgo 包装了 OpenCV,并集成了现有的成熟 C 类库(例如,libjpeg-turbo 用于 JPEG,libpng 用于 PNG,giflib 用于 GIFs,libavcodec 用于视频)来处理图像,并通过 fasthttp 处理 HTTP 请求。

顺带还修改了下 giflib 的行为,以便让系统能够逐帧进行解码、调整大小、然后进行编码和压缩,并将第一帧输出为 PNG。并优化了很多问题,比如在 RGB 颜色模式下对 GIF 进行调整。具体实现,可以查看源码。

最后经过测试这个组合的表现大多数情况能优于 pillow-simd。

目前,Discord 已经将 Lilliput 以 MIT 协议开源了出来。如果,你也有高性能调整图片大小的需求的话,不妨试一试这个库。

原文:How Discord Resizes 150 Million Images Every Day with Go and C++

日报扩展阅读:

极光日报,极光开发者旗下媒体。

每天导读三篇英文技术文章。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK