Learn And Life.

关于一个接口的设计

对最近的工作做一个总结和反思,最近在处理消息分片的工作,先介绍下应用的场景:
我们在做一个直播的产品,直播中会存在很多消息,这样就需要对消息进行处理,然后回放的时候,会用到这些存储的文件,我们目前使用的第三方的聊天室系统,需要对第三方的消息同步到我们的系统存储起来,一方面便于查询问题,因为消息内容中除了第三方的自定义的协议之外,也会涉及到我们业务数据的上报;另外一方面,不需要依赖第三方服务,对自己的数据管控。在改版之前,第三方会在直播结束,会回调我们的接口,进行消息的同步,写入异步队列,实现串行处理,之前每个直播消息,会生成独立的一个文件,放到云存储s3,由于消息文件过大,导致有些回播在下载消息文件的过程中,加载时间太慢,甚至导致客户端app直接崩溃,为此,之前有人改过一版,只是对于消息过于大的文件,进行了不处理,也就是完全的抛弃掉,回播不会存在聊天消息,这种处理太过于武断,没有从根本上解决问题

在处理这个问题的过程中,遇到了一些问题
之前的处理方式:
将消息文件从redis落地,将消息文件存放于磁盘,然后用shell脚本实现同步到s3

方案一
我没有修改既有的这种方式,甚至没有对这种方式产生任何的质疑, 于是做了如下的设计

1.新增接口,提供消息分片的文件列表,需要服务端存储某个视频的消息分片的文件的列表
2.仍然使用既有使用shell脚本同步消息文件的方案

这样的设计有什么问题呢?
1.浪费了存储空间,这些消息文件是静态的文件,生成之后就不会变,所以并不需要把消息分片文件列表存放于redis中
2.消息文件的同步,将消息文件存放于本地磁盘,然后使用shell脚本同步,而且同步进程使用的单进程,实践证明,这种方式并不是最好的,由于产生的文件的数量比较多,导致消费脚本处理不过来,产生消息文件的积压

方案二
1.做好对旧版本的兼容,对接口进行修改,提供消息文件的索引文件,索引文件是消息分片文件上传到s3之后的文件列表
2.不基于shell脚本处理,基于s3提供的sdk,完全使用同步的方式进行处理,即不将redis中的消息内容落地处理,不生成消息文件
3.动态生成消息分片文件的时候,同时生成消息索引文件,并同步到s3

索引文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
[
{
timestamp: "1481188775520",
url: "http://test.s3.amazonaws.com/cheetahlive/15/33/14811887487207113059/14811887487207113059_0.json"
}
{
timestamp: "1481188775520",
url: "http://test.s3.amazonaws.com/cheetahlive/15/33/14811887487207113059/14811887487207113059_1.json"
}
...
]

这样,既解决了服务端的存储问题,不用再存储消息分片文件了,直接客户端通过接口请求,拿到消息索引文件,通过解析消息索引文件,得到所需要的消息索引文件列表,同时解决了消息文件存放于存盘,产生的消费能力跟不上导致的文件积压的问题,如果文件比较多,还可以对回调任务处理脚本使用多进程的方式,不用考虑到是否会产生多个进程同时消费一个消息文件的问题,完美支持多进程,这样设计似乎完美了吧?

真的完美么?

方案三
在方案二的基础上做了以下的修改
方案二会产生什么问题呢?
1.客户端要下载消息文件,需要先请求索引文件接口,下载并解析索引文件,获取消息分片文件列表,客户端同学会说,你的接口太难用了得改啊
2.流量问题,移动端应用,最需要考虑的问题之一,就是能省流量
如何更友好的处理这些问题呢?
1.简化接口,还是使用索引列表的方式返回,但是处理方式跟方案一不同的地方是,服务端请求索引文件,解析并通过接口返回
2.生成的消息文件使用gz压缩,当然这个压缩需要s3支持,开启s3的gz压缩模式,减少消息的传输

到此,也算是比较完美的了,不知道还没有比较好的方案来处理这个问题?希望能得到大家的交流!

总结:
1.在接口升级的过程中需要考虑到客户端新老版本的兼容性
2.对于同步处理还是异步处理的选择,根据特定的业务场景进行选择,考虑有没有必要使用异步处理,不是所有场景都适合使用异步处理的方式
3.文件存储,考虑磁盘的使用文件,目录划分
4.消费模型,必须需要考虑生产者和消息者之间能力匹配问题,不然会产生积压
5.对于数据的处理方式和存储方式,不是所有的数据都需要使用内存或者数据库存储,可以使用云存储,结合cdn技术,更好的管理静态文件
6.对于考虑一个方案的时候,需要做更多的可能性测试,通过测试来选取最佳方案
7.在思考方案的时候,需要从头到尾的考虑整个的数据的处理过程,可能是一个回路,只是变更一种数据获取方式,所以考虑的时候,尽可能的考虑每一个数据上处理的环节

人因为梦想而伟大,产品因为一个更好的技术方案而解放我们,多思考细节的东西,才能挖掘别人看不到的东西,一切变化,都因为在变!!