近日,开源服务软件Hasura在官博发文称,随着用户数的增加,软件规模化的性能开始成为一个问题,于是他们用Go重写了一个Node.js微服务,结果显示,内存消耗减少至一半而服务请求数量却增加了5倍。

为什么会选择Go?

在可扩展需求变的愈加急切的情况之下,Hasura团队决定用Go重写服务。选择Go的原因有很多,其中包括但不止于:

重写服务

看似简单的事情,可做起来并不容易。事实上,重写工作并不顺利,尤其是编写这样的微服务。该服务非常方便有用,但并不执行过于复杂的任务,Hasura-storage的创新和实用性来自于连接用户喜爱的两个伟大的服务:S3和Hasura,而不是做任何异想天开的事情。

重写完成后的性能表现

任何重写工作都避免不了进行基准测试,他们也一样。基于k6设计了以下测试环境:
当测试开始时,它在最初的10秒内将工作者的数量从1提升到目标数,然后再运行60秒才结束。

工作人员尽可能快地查询服务,我们运行以下测试。

  • download_small_file (100 workers) - 下载一个100KB的文件
  • download_medium_file (100 workers) - 下载一个5MB的文件
  • download_large_file (50 workers) - 下载一个45MB的文件
  • download_image (100 workers) - 下载一个5.3MB的图片
  • download_image_manipulated (10 workers) - 下载相同的图片,但要调整图片的大小,并即时应用一些模糊的效果
  • CPU被限制在整个系统的10%
  • 内存没有限制

在看到结论之前,这里想澄清一下,你将要看到的数字不应该从表面上看,用于基准测试的系统的CPU容量相当有限,所以想给两个服务施加些压力,看看它们在压力下的表现,所以,大家感兴趣的不是原始数字,而是两个版本之间的差异。

请求数

请求数是衡量重写是否有意义的重要指标:

在这里插入图片描述如图所示,在各种情况下,所提供的请求数量都有大幅提高,特别是对于较小的文件,有5倍的提升。

内存消耗

内存是一种有限的资源,如果一个系统达到了它的极限,就不容易对它进行节流。传统的系统依靠交换磁盘,但对整体性能影响巨大。现代系统依靠的是在达到阈值时重启服务。正是由于这个原因,不同情况下的内存使用峰值是很重要的,如果你达到一定的数值,你的服务就会被重新启动,如果服务被重新启动,它就不能为请求提供服务。下面可以看到上述不同场景下的峰值使用情况。

在这里插入图片描述如图所示,该项指标中多种情况下都得到了较大的提升,尤其是在下载大文件时。

响应时间

关于响应时间这个指标,主要看两个方面,最小响应时间,以及在95%的页面之下,大多数用户端的响应时长最多是多少(包括系统有压力时)。

下面先看一下最小响应时间。
在这里插入图片描述
在download_small_file案例中很难看出来有什么变化,但将该场景的响应时间从Node.js案例的29ms提高到Go案例的7ms。除了download_image_manipulated,在其他场景中看到了4倍的改进。

现在来看看95%的页面响应情况。

在这里插入图片描述
在该测试案例下面,你也能看到大多数情况之下都有4倍的改进,但在download_image_manipulated和download_large_file这两种情况下看到了实质性的改进,但没有像其他情况那样戏剧性。这是有道理的,因为下载大文件是由I/O NET约束的,而处理图像是由CPU约束的,即使如此,很高兴能看到这一重大改进。

将服务部署到生产中

在服务被重写和测试后,Hasura团队将服务部署到生产中。当它被部署后,效果非常显著。下面是在集群中的一个节点的内存使用情况。

在这里插入图片描述
正如你所看到的,新服务减少了近40%的内存占用,这一重大改进可以为更多的用户和流量提供服务,且不会增加基础设施费用。

结论

经测试及实际生产部署得知,重写后的服务顺利完成了当初定下的性能提升目标,利用更少的资源提供更多的请求与服务,并且也改善了用户的响应时长。

参考链接:

Logo

20年前,《新程序员》创刊时,我们的心愿是全面关注程序员成长,中国将拥有新一代世界级的程序员。20年后的今天,我们有了新的使命:助力中国IT技术人成长,成就一亿技术人!

更多推荐