我们如何微调Go应用程序的性能

在开始本文之前,我想宣布,诚实蜂开源了我们的golang工人库库jobq ,这是一个非常易于使用的库,可以节省您维护goroutine和频道使用率的时间,请随时发表评论,报告问题并有助于使其变得更好🙂

响应时间增加

在诚实应用程序的使用中,重要的部分之一是地址搜索,因为这是使用我们的服务的切入点。 为了提供更多的灵活性和便利性,我们构建了一个名为“ Atlas”的服务,使其成为具有邮政编码搜索和Google Maps api调用的委派服务器。

最近,我们发现在根据的Google Place Autocomplete策略修改了一些代码以使用session_token之后,响应时间增加了100毫秒左右。

然后,基于通常的行为,第一个响应是检查我们在代码修改上做错了什么,并且可疑点肯定在session_token添加上,因为它是基于对Atlas的每个api调用生成的,并且令牌本身是一个通过Random创建的UUID,在类似Unix的系统上,Random Reader从/ dev / urandom中读取并执行I / O操作。

那是根本原因吗?

解决性能问题总是像犯罪现场调查一样,您总是需要进行更多挖掘,我们发现它实际上不是通过UUID生成引起的,因为它仅占用了额外的300纳秒的时间,并且占用的内存很少。

根据上面的异常GC暂停图,我们可以确定这是由于内存卡住了更长的时间,并且原来的GC循环无法再处理它了,这在newRelic图(黄色部分)下面非常明显。

然后我们去检查AWS弹性缓存,实际上,由于缺乏物理内存,Swap的使用率提高到了近1.5GB,这是因为缺少物理内存,因此系统决定使用Swap进行覆盖。

恢复

我们决定将内存大小从cache.t2.small增加到cache.m1.medium ,并将GOGC百分比从100调整为400,因为在这段时间内,诚实蜂还启用了使用基于文本的内容和JP进行SG搜索的功能邮政编码搜索提高了准确性,这也增加了流量(吞吐量)。

GOGC变量设置初始垃圾回收目标百分比。 当新分配的数据与上一个收集之后剩余的实时数据之比达到此百分比时,将触发收集。 默认值为GOGC = 100。 设置GOGC = off将完全禁用垃圾收集器。 运行时/调试包的SetGCPercent函数允许在运行时更改此百分比。 请参阅https://golang.org/pkg/runtime/debug/#SetGCPercent。

有效!! SLA也恢复正常。

故事结束了吗?

不,因为我们仍然可以观察到Web外部(Google Maps api)的长时间延迟,因此在代码库中搜索之后,以前的工程师使用for循环调用google api并完成完整结果,这意味着其中一项搜索需要调用1个自动完成请求,并根据预测从Geocoding api(如A + B + C)中获取详细的经/纬度和邮政编码。

解决它实际上很简单,这就是使并发可以在搜索结果收集中发生,这是jobq进入的时间。

我们没有在jobq调度程序上使用动态调整的原因是因为该作业还会触发I / O(postgres和redis),自动增加可能导致fd用尽问题并导致恐慌。

通过这种方法,我们成功地将A + B + C时间减少到更平坦的响应时间(取决于A或B或C的延迟),并节省了大约1/3的响应延迟时间。

结论

监视性能既有趣又困难,但是一旦解决了,您将在本周的经验中学到很多东西。