Wolfram 云端需要变得更加完美
Wolfram Cloud正式版马上就要上线了!(耶!),现在我的大部分时间是在进行一些完善工作,尽可能做到完美!(顺便提一下, 正式的云端将会变得更加完美! )大多数时候我主要在考虑它的顶层功能与策略。我倾向于从各个层面考虑问题,但作为CEO,我最终要对所有事情负责。而就在三月初,由于偶然的原因我对一件事物进行了深入的研究。
事情是这样的。作为一个正式的产品系统,Wolfram Cloud 被许多人用来处理各种重要事项,例如公司各项业务等等。因此Wolfram Cloud的处理速度应该越快越好。我们的各项指标显示其标准速度是很快的,但我在使用Wolfram Cloud的过程中却出现了一些意外情况:Wolfram Cloud有时运行速度很快,但有时却慢了起来。
我们有非常出色的软件工程师来排查和解决问题,但几个月过后问题还没有解决。那时我们刚发布了Wolfram Data Drop,所以我想,我为什么不自己做一些测试呢?我可以通过我们新发布的Wolfram Data Drop来搜集一些数据啊!
Wolfram语言很棒的一点就是它非常适合很忙的人:即时你只有写几行代码的时间,你也可以完成整件事情。在这个例子中,我只需要运行3行代码就找到了问题所在。首先,我通过一个很小的Wolfram语言程序在Wolfram Cloud中部署了一个Web API:
然后我调用这个API50次,测量每次调用花费的时间(%表示与前一次相比)
然后我绘制了时间序列图
然后一些不可思议的事情发生了。有时候调用一次API的时间大约为220ms,但通常是900ms甚至1800ms。最不可思议的是这些调用时间似乎是可以被量化的!
我们可以很清楚地看到,直方图左边的调用速度都很快,接下来的调用速度变缓,出现了一个用时高峰,然后调用速度变得十分缓慢, 太奇怪了!我在想这种现象是不是持续发生的。所以我设置了一个阶段性任务,每几分钟对API进行多次调用,然后把调用时间输入Wolfram Data Drop。这个过程持续了一个晚上,第二天早上我来查询结果,以下是我看到的:
这更奇怪了!为什么会出现这么大的变动?我能理解集群中某个节点可能会逐渐变慢,但是为什么怎么会出现这种反复的情况呢?
我第一个想到的是可能是网络问题,因为我是从1000多英里以外的服务器调用API。所以我去查看了网速情况。但除了有个别时候出现了峰值的情况,其他时间的网速都非常稳定。
服务器内部出现问题了
这么说,一定是服务器本身出问题了。Wolfram Cloud中引进了许多新技术,但是大多数都是纯粹的Wolfram语言代码,因此检测起来很容易。但是在Wolfram语言层面以下还有一个通用的现代服务器基础设施。这跟WolframAlpha 的服务器设施,以及Web Mathematica10年前就开始使用的服务器设施大致相同。但是作为一个对计算要求更高的系统,Wolfram Cloud 的服务器设置有一些细微的差别。
我一开始怀疑就是这些细微的差别导致了网站服务器层的问题。我希望我们最终能够拥有专门的Wolfram语言基础设施,但是现在我们用的是以Java为基础的服务器系统 Tomcat。一开始我以为可能是Java垃圾收集导致了Wolfram Cloud速度变慢。代码分析显示了Tomcat中垃圾回收机制缺失会有产生问题,但是这种现象很少,而且只用了几毫秒而不是几百毫秒。所以这不是导致速度变慢的真正原因。
到现在为止,我已经沉迷在这个问题中,非常想找出原因所在。我已经很久没有像这样专注调试某个系统故障了。这种感觉就是在做某种科学实验一样。而就像在科学实验中,简化研究对象总是很重要,所以我决定要简化我的研究对象。我云切断了大部分的网络:从内部集群中调用API。然后我切断了负载均衡器,通过把我的请求锁定在一个节点上使所有的请求传输到某个特定的节点(外部用户无法这么做除非他们有Private Cloud)。但是速度慢的问题依然存在。
所以我开始搜集更详细的数据。第一步是记录API 返回执行Wolfram语言代码开始与结束的绝对时间,然后将前者进行对比,以下是对比图:
蓝色线条表示原始花费时间,黄色线条表示执行Wolfram语言代码开始与结束的绝对时间。我在整个系统表现很差的时候搜集了这些数据。我发现多数速度非常慢的情况出现在前者的时候.
这又是一个很奇怪的现象。看起来速度缓慢跟Wolfram语言代码运行的绝对时间(根据结束与开始时间之差)并没有很大的关系。相反,更像是有某种外部因素时不时地扰乱系统。
一个令人困惑的现象是集群中的每一个节点都包含8个内核,每一个内核都运行一个不一样的Wolfram引擎实例。Wolfram引擎很友好、稳定,因此每一个实例两次运行的间隔时间长达几小时甚至几天时间。但我想,有没有可能是有一些实例在运行过程中产生了一些问题呢?所以我通过测试API查看Process IDs和Process Times,然后我绘制了运行时间和API调用时间的分布图.
图中可以看到新启动的进程 调用API要快一点,但是区别并不是非常明显。