一个完善的 IM 系统中通常充斥着大量的图片内容,包括:用户头像、图片消息、相册、图片表情等等,那么在做服务端架构设计时该如何存储这些图片呢?
本文分享的是典型 Web 应用中大量图片的服务端存储加构的演进过程,但基本的技术原理和架构思路对于 IM 系统而言同样适用,所以在阅读时可以根据自已 IM 的实际架构情况,酌情吸取适合您的内容即可。文中部分观点可作抛砖引玉之用,可能并非最佳实践,请勿迷信之。
实际上:旧式的 PC 端 IM 中,诸如图片消息这种业务形态,可能是通过长连接直接推送过去(所谓的实时图片传输嘛),这种情况理论上是不需要服务端存储的。但现今的主流移动端 IM,基于移动网络抖动大、 不稳定的特性和随时随地社交分享的现实,已很少使用实时传输这种技术手段。现在主流 IM 都是本文所述的这种:通过 Http 短连接从云(也就是服务端)“拉取”,这种方式的好处是:随时随地分享、对网络稳定性要求低(只要上传者一次上传,服务端可长时间存储,下一个阅读者通过 URL 按需随读随取即可,再次分享时只要分享 URL 而无需再次完整传输整个图片)。
以此类推:IM 系统中,实际上还存在其它类似于图片的小文件存储需求,比如:语音留言消息中的 AMR 短音频文件(有些 IM 中为了音质可能使用的是 AAC 音频格式,比如易信)、短视频功能中的小视频文件等,这些文件的存储和使用跟图片文件基本类似,所以考虑到通用性,如果能把这些小文件存储也纳入到图片的存储架构中,对于整体系统架构来说(尤其存储部分)就显的更通用。所以本文中虽然以图片存储为切入点,但您实际上完全可以套用到基它小文件的存储上哦。
单机时代的图片服务器架构(集中式)
初创时期由于时间紧迫,开发人员水平很有限。
所以通常就直接在 website 文件所在的目录下,建立 1 个 upload 子目录,用于保存用户上传的图片文件
随着 upload 目录中文件越来越多,所在分区如果出现容量不足,则很难扩容。只能停机后更换更大容量的存储设备,再将旧数据导入;
在部署新版本(部署新版本前通过需要备份)和日常备份 website 文件的时候,需要同时操作 upload 目录中的文件,如果考虑到访问量上升,后边部署由多台 Web 服务器组成的负载均衡集群,集群节点之间如果做好文件实时同步将是个难题。
集群时代的图片服务器架构(实时同步)
一个传统的 Web 服务端站点下面,新建一个名为 upload 的虚拟目录,由于虚拟目录的灵活性,能在一定程度上取代物理目录,并兼容原有的图片上传和访问方式。
优点:配置更加灵活,也能兼容老版本的上传和访问方式。因为虚拟目录,可以指向本地任意盘符下的任意目录。这样一来,还可以通过接入外置存储,来进行单机的容量扩展。
缺点:部署成由多台 Web 服务器组成的集群,各个 Web 服务器(集群节点)之间(虚拟目录下的)需要实时的去同步文件,由于同步效率和实时性的限制,很难保证某一时刻各节点上文件是完全一致的。即时通讯聊天软件app开发可以加蔚可云的v:weikeyun24咨询
整个 Web 服务器架构已经具备 “可扩展、高可用” 了,主要问题和瓶颈都集中在多台服务器之间的文件同步上。
上述架构中只能在这几台 Web 服务器上互相 “增量同步”,这样一来,就不支持文件的 “删除、更新” 操作的同步了。
早期的想法是,在应用程序层面做控制,当用户请求在 web1 服务器进行上传写入的同时,也同步去调用其它 web 服务器上的上传接口,这显然是得不偿失的。所以我们选择使用 Rsync 类的软件来做定时文件同步的,从而省去了 “重复造轮子” 的成本,也降低了风险性。
同步操作里面,一般有比较经典的两种模型,即推拉模型:所谓 “拉”,就是指轮询地去获取更新,所谓推,就是发生更改后主动的 “推” 给其它机器。当然,也可以采用加高级的事件通知机制来完成此类动作。
在高并发写入的场景中,同步都会出现效率和实时性问题,而且大量文件同步也是很消耗系统和带宽资源的(跨网段则更明显)。
沿用虚拟目录的方式,通过 UNC(网络路径)的方式实现共享存储(将 upload 虚拟目录指向 UNC)。
支持 UNC 所在 server 上配置独立域名指向,并配置轻量级的 web 服务器,来实现独立图片服务器。
优点:通过 UNC(网络路径)的方式来进行读写操作,可以避免多服务器之间同步相关的问题。相对来讲很灵活,也支持扩容 / 扩展。支持配置成独立图片服务器和域名访问,也完整兼容旧版本的访问规则。
缺点:但是 UNC 配置有些繁琐,而且会造成一定的(读写和安全)性能损失。可能会出现 “单点故障”。如果存储级别没有 raid 或者更高级的灾备措施,还会造成数据丢失。
在早期的很多基于 Linux 开源架构的网站中,如果不想同步图片,可能会利用 NFS 来实现。事实证明,NFS 在高并发读写和海量存储方面,效率上存在一定问题,并非最佳的选择,所以大部分互联网公司都不会使用 NFS 来实现此类应用。当然,也可以通过 Windows 自带的 DFS 来实现,缺点是 “配置复杂,效率未知,而且缺乏资料大量的实际案例”。另外,也有一些公司采用 FTP 或 Samba 来实现。
上面提到的几种架构,在上传 / 下载操作时,都经过了 Web 服务器(虽然共享存储的这种架构,也可以配置独立域名和站点来提供图片访问,但上传写入仍然得经过 Web 服务器上的应用程序来处理),这对 Web 服务器来讲无疑是造成巨大的压力。所以,更建议使用独立的图片服务器和独立的域名,来提供用户图片的上传和访问。