Repustate 向世界各地的企业和组织提供文本分析服务。随着公司的发展,他们每天处理的文本段数量从 5 亿增加到 10 亿,其中包括 Tweet、新闻文章、博客评论、用户反馈等。大规模的文本分析非常困难,因为很少会出现两段文本完全相同的情况,所以无法利用缓存来提高效率。不过,它可以将大段的文本分成多个句子,然后并发分析每个句子。近日,Repustate 官方博客发表了一篇博文,介绍其API 的演进过程。
Repustate API 的第一个版本是用 Django 编写的。他们构建了一个原型,并以此为基础推出了他们的服务。但每个 Django 请求 / 响应周期的开销太大。随着 API 访问量增加,可靠性问题凸显,使用 Amazon 服务的成本也大大增加。于是,他们开始寻找一种 Python 代替方案,并选择了 Flask 。Flask 几乎是现成的 API,而且是轻量级的。不过,他们稍后又发现了 Falcon 。他们非常喜欢这个框架,因为它使用 Cython 进行了优化,速度比 Django 要快许多,而且它还遵循简洁 REST 原则。事实证明,Falcon 是一个很好的补救方案。Repustate 的平均响应时间缩短了,故障和支持问题的数量也降下来了。
但即便如此,Repustate 的性能仍然不能满足日益增长的需求。尤其是并发,一直是 Python 的痛处。而且,他们用的是 Python 2.7,还没有使用 Python 3 中的 asyncio 包。但实际上,即使用了,也还是要担心 GIL 的问题。并且,Falcon 无法实现自托管部署。Python 无法像 Java 或 C 那样打包,然后分发。而他们的许多客户需要在自己的网络中运行 Repustate,他们只能为这些客户提供一个部署了整个技术栈的虚拟应用。该虚拟应用既可以用于 VMware,也可以用于 Virtual Box。这是个可行的方案,但很笨重,而且更新和支持困难。所以,他们希望能够仅仅提供一个可以安装的二进制文件。
之所以选择 Go,是因为 Go 满足了他们所有的要求:
- 比 Python 快
- 可以编译成单个的二进制文件
- 可以部署到任何操作系统
- 容易实现并发
而且,Go 测试套件的布局看上去比他们的 nose 测试要简单。测试函数头很容易迁移。例如,将def test_my_function():
转换成func TestMyFunction(t *testing.T) {
,通过简单的替换就可以完成。此外,go routines 和 channels 非常易于使用,使得并发文本分析很容易实现。
整个迁移过程耗时 3 个月,感兴趣的读者可以查看他们的迁移过程。下面是他们的迁移成果:
- API 平均响应时间由 100ms 降至 10ms;
- 所需 EC2 实例的数量减少了 85%;
- 由于 Go 可以编译成一个单独的二进制文件,而 Go 1.5 让交叉编译变得很容易,所以他们现在能够提供一个 Repustate 自托管版本;
- 由于 Python 和 Go 相似,所以他们能够快速重建单元测试。
另外,由于重新过了一遍 Python 代码,他们还做了许多与性能无关的改进。因此,该文指出:
如果时间允许,回过头来看看旧有的代码总是好的。你也许会惊讶,它怎么会那么差。
感谢魏星对本文的审校。
给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ , @丁晓昀),微信(微信号: InfoQChina )关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入 InfoQ 读者交流群)。
评论