在开发和架构设计过程中,我们往往会被要求构建低延迟的应用,快速的响应各类请求对于优化用户体验来说非常重要。而设计低延迟应用时需要考虑很多因素,也正是这些因素将其与其它应用区分开来,它们包括:要产生更少的垃圾,转换更少次数的数据,让应用需要的数据随时可获取等。本文从这几个方面,介绍低延迟应用与普通应用之间的差别。
简单性是关键
如果我们想让一样东西执行得更快,最好的方式是让它做更少的工作。也就是说,要产生更少的垃圾,转换更少次数的数据,让应用需要的数据随时可获取。
如果你想获得稳定的性能,简单性尤其重要。如果你期待 99% 或者 99.9%的准确率,那么如果你看到系统出错,此时肯定是绝大多数事情都在变糟。系统越复杂,事情就会变得越糟糕。如果吞吐量也对你很重要,你会发现一个缓慢的输出会对结果产生很不好的影响,你有必要开始担心 99.99% 或更高的准确率,因为在系统再次处于正常运行状态之前,即使一个非常不常见的延迟也会影响许多请求或事件,何况很多时候,数百或数千个延迟也并不少见。
不要考虑容易添加,而要考虑容易移除
你不需要考虑太多如何方便地添加代码的事情,而是要考虑怎么轻松地剔除那些不需要做的事情。许多框架在设计的时候就会考虑让其能够轻松上手,也很容易添加功能,这样如果你需要框架少做一些事情,那么它就可以少做一些事情。
解决这一点的最好方法是使用非常轻薄的库和框架(在调用堆栈和数据变换的方面),如果不需要甚至可以做得更少。
你想要一个清晰简单的解决方案,但你也想有选项可以替换或删除你不需要的任何功能。
转换更少次数的数据
我常常对代码的错综复杂感到惊讶。它经常像揉面或揉数据一样被执行。相同的数据被转换一次又一次,然后还会再返回来转换为另一种形式,最后与某些自定义数据放入一种数据结构中,被用来构建另一种数据结构。所有这些复杂过程都减慢了应用程序的运行速率,并掩盖了应用程序实际做的事情。
你需要设计自己的应用程序,这样你可以看到数据从一端到另一端发生了什么,以致你可以删除你实际上不需要的一些步骤(并且可能是错误的来源)。
我见过一个日期的例子,要将一个 64 位长整数转换成一个日期对象,然后再转换为一个 MM / DD / YYYY 的字符串,再转换为一个 yyyy / MM / DD 的字符串,再转换为日期类型,并最终转换回 64 位长整形。
我也见过另一个例子,要将 64 位 double 型转换为一个 double 型对象,转换为字符串类型后又解析为 double 型,进行一些不正确的或复杂的四舍五入,最后转化为了最初的 64 位 double 型。
这听起来很傻,但是有些框架经常会这样做。每个库中每种层次的部分由不同的人写入,数据在每个库所使用的模型之间转换。
计算机科学中的所有问题都可以从抽象层面来解决。
代码的可读性
很多代码是以一种自然语言的风格,在高层次上对应用程序进行描述。即使我不懂编程,我也知道代码要做的事情。这工作就像魔术。但问题是,代码虽然在高层次上编写,但是执行的时候并不是像你想象的那样。虽然功能性问题可以通过好的测试被发现。当你的设计掩盖了计算机实际执行的有关细节的时候,虽然代码正确执行,但是该如何判断它执行的很差呢?有些代码在大部分情况下执行得很好,只在很少的时候表现不好,此时更难检测。即使性能分析工具也帮不了太多。
低延迟代码的优越性是它能够轻易地读出你让计算机需要实现的事情。这个操作是 O(1),O(log N) 或者 O(N)?这个操作是线程安全的吗?如果我不需要让它是线程安全的,是不是不会这么容易?
这种低层次的代码是有用的,但你仍然需要从高层次上理解代码要做的工作。总存在一部分代码告诉你组件是用来干什么的。这种高层次的组件调用往下,以致你可以看到它是怎么工作的。反过来又可以看到代码在低层次上工作的细节。
业务和基础架构代码的分离
如果应用程序没有做自己应该做的事情,你应该改变你的业务逻辑来解决它。如果应用程序不以这种方式执行,你应该改变你的基础架构,使得你的应用程序仍然做它需要做的事情。
几个不错的案例
Aeron( https://github.com/real-logic/Aeron )
Chronicle( http://chronicle.software/hft-products/ )
到底有多少差异?
使用低延迟技术能够显著提高一个应用的典型性能,也能增加它的吞吐量。在一致性条件下,能够减少 99%的延迟。
设计已经尽可能快了吗?
对于我们正在开发的项目,这并不是最关键的优点。它不仅仅是生产力。主要的优点是开发最简单的解决方案,来解决为提高性能所需要解决的问题,通过更少的努力让其变得更快,只有当它已被确定是必须的才执行。
简单性也能提高可维护性
我们使用的拇指规则是,一个成功的系统在维护上的开销是构建上的开销的三倍。系统的简单性和透明性有助于最大限度地减少你的长期成本,因为其能够帮助以更小的风险,更短的时间运行一个应用。
既然简单性是如此重要,为什么不是每个人都这样做呢?
构建一个大的、复杂的系统很容易,你只要不断地增加功能。使系统尽量简单是非常困难又需要经验的。为了在开发的时候尽量避免添加不需要的东西,你经常需要多年开发相同类型解决方案的经验。
查看英文原文: How Do Low Latency Applications Differ From Regular Applications?
评论