微信你的kindle V2.0

这次改版的主要目的是让不读成为一个稳定能长期运行的服务,去掉第一版中一些试验性的功能。

主要的改动:

  1. 主数据库从ElasticSearch换成Slick+H2。
  2. 微信机器人模块完全独立出来,通过Rest API和主数据库交互。

原有构架中,每个模块(微信机器人,蜘蛛,邮件)都在同一个Akka Cluster中,并自带一个ElasticSearch数据库本地实例,数据的读写操作都针对这个本地数据库,数据同步交由Elastic集群完成,完全无需关注其他模块的存在。 这个方案的最大优势是可扩展性,能够非常方便的增加模块实例,提高整个系统的吞吐。但缺点也很明显:对于Neveread这样一个小系统,这一套东西太overkill了,并且ElasticSearch数据库的管理能力较弱,不便于引入复杂一点的数据操作。改版后,neveread的服务器从阿里云1G内存迁移到了DigitalOcean 512M内存的VM,并通过了相同强度的压力测试。

细节改动:

  1. 去掉了自动好友验证功能。
  2. 去掉了邮箱全文投递功能。(update:已反合全文投递功能,发送文本或HTML内容到「不读」为你分配的@kindle.pm邮箱即可)
  3. 引入基于用户的优先级投递功能。
  4. 增加微信机器人的功能。如:替用户投递文章,绑定邮箱,自动抓取关注的订阅号新发布的文章。

和第一版一样,这次升级也是一次新技术的学习过程,其中有很多有意思的事情,如函数式数据库操作(FRM)库Slick的引入。重新设计了微信机器人消息收发模块,通过无状态的Actor消除缓存需求。大量使用Future,让整个系统全异步执行。这里先说说基于用户的优先级投递功能。

优先级投递功能

为了更加友好的使用微信机器人:),系统中人为的把每条微信消息的发送间隔增加的1秒以上,这样消息发送模块很容易成为整个系统的瓶颈,导致无法及时处理用户消息。因此需要引入优先级来保证服务质量。

第一版中,每种消息类型有一个优先级,如绑定消息的优先级比其他消息要高,改版后优先级会同时由消息类型优先级和动态调整的用户优先级共同决定。

优先级投递功能主要解决的问题是:

  1. 优先级高的用户的消息优先投递。
  2. 优先级高的消息类型的消息优先投递。
  3. 确保优先级低的用户的消息也有机会投递。
  4. 大量发送消息的用户优先级迅速降低,防止恶意使用。

具体算法:

每个用户都有一个优先级基数。用户每发送一条消息,该基数都会自动减1,每条消息的优先级由该基数和消息类型优先级共同构成,并被放入一个优先级队列中,按序投递。如果队列中消息数量超过一定阀值,最低优先级的消息会被直接丢弃。用户优先级基数会定时重置。

实现的效果:

假设A用户优先级为60,B用户优先级为50,普通消息优先级为0,命令消息优先级为10.

满负荷情况下,A发送10条普通消息后,B发送的普通消息才会被投递,但如果B发送的是命令消息,该消息也会被立刻投递。A如果继续按照2 msg/sec的速度发送消息,而B按照 1 msg/sec的消息发送消息,则后续B的消息都会被优先投递,直到下一次优先级基数重置。

目前系统设置中,新注册的用户优先级基数默认为50,而上一个版本中已绑定的用户按60优先级基数导入到新版本中。

发送「设置」微信消息给文字鲨看看你的优先级吧!

附:

v2ex讨论链接

Slick文档FRM VS ORM (建议发送到kindle上细读:)

微信你的Kindle:记录我的第一个Web项目

不读:构建你万年图书馆

欢迎关注「不读」的公众号

公众号