做一款互联网产品,人们往往立马就想到了海量用户、海量数据、高并发、高性能。所以起初做架构设计时就把性能提到了一个不得不做的地位。我个人是很反对这种“未雨绸缪”的方式的,因为对于一个新应用来说获取一个互联网用户的成本并不小,而且“海量”不是短期内就会面临的。所以请建议您最好先在基于投入产出比的考量下对​快速实现​ OR ​性能​重要程度做出权衡后再做考虑,最好先实现应用再做优化,过早优化是万恶之源这句话不是吓唬小孩子的。当然,本文讲的就是性能的考量,所以文章以下的讲解是在你已经决定要重点考虑性能的基础上。


性能无非就是为了通过缩短响应时间来获得良好的用户体验,通常我们会说起​2/5/10法则​:用户响应在2秒之内是很好的用户体验;用户响应在2-5秒之间是一般的用户体验,用户可以接受;但是用户响应在5-10秒之间是很糟糕的用户体验,已经接近了用户可接受的极限。所以我们为了减小用户响应时间必须要分析出可能出现的性能瓶颈在哪里。

构建高性能服务的考量_带宽

如图我们可以很清晰的看出用户在等待的过程中发生了什么:

  • 数据在网络上传输的时间;
  • 后台服务器处理请求并生成回应的时间;
  • 客户端处理回复并进行UI呈现的时间;

因为我们今天讲的是构建高性能服务,所以3我们暂时忽略。所以​响应时间 = 发送时间 + 传播时间 + 处理时间​。有些人要问了,发送时间是个什么东东,我们来分析下一次网络I/O的过程:

  1. 将要发送的数据写入进程的数据缓冲区;
  2. 调用系统API,这里涉及到用户态到内核态的转化,将数据存入系统内核缓冲区;
  3. 数据从内核缓冲区进入网卡;
  4. 数据从网卡传输到网络线路;
  5. 数据在线路中转换成相应的信号通过介质进行传输;

所以​发送时间 = 数据量/带宽​,带宽就是数据的发送速度,就是通常我们所说的Mb/s。那么传播时间又与什么有关呢?很容易想到的就是传输距离和传输速度,传输距离就是我们现实中的从北京到上海的距离(铺设网线的距离)。传输速度指的是信号的传输速度,通常接近于光速,我们将其约等于2x10^8m/s。所以​传播时间 = 传输距离/传输速度​。

现在我们得出了​响应时间 = 数据量/带宽 + 传输距离/传输速度 + 处理时间​。到底是哪一个步骤最大的影响了我们的用户响应呢?我们举个例子,假如客户在兰州,网络出口带宽为4Mb/s(实际运营商提供的4Mb的网络上行带宽远远低于4);服务器在北京,网络出口带宽为100Mb/s;兰州距离北京约为2000km;发送回应均为10kB(0.08Mb)数据。

  • 客户端发送时间 = 0.08/4 = 0.02s
  • 服务端发送时间 = 0.08/100 = 0.0008s
  • 传播时间 = 2x10^6/2x10^8=0.01s
  • 那么响应时间 = (0.02+0.0008) + 2x0.01 + 处理时间;

除去处理时间发送时间+传播时间才为0.04秒,仿佛可以看出影响我们服务性能的仿佛是在处理时间上。其实不然,这里面哪一项都不能被完全忽略。比如刚才我们举得就是个很极端的例子,客户端上行带宽不低,而且服务端只给这一个用户提供服务,所以两端的发送时间都很小;在传输上我们忽略了信号的衰减,各级路由器的转发,甚至不同运营商的互联互通问题。但是这两个问题通常不是我们程序开发者能解决的,这需要科学合理的IDC的支持,而且这个成本是企业非常关注的。

所以我们还是把优化重点转移到最后一项​服务器的处理时间​,这里才是考验我们架构师,研发工程师,DBA能力的地方。如何实现服务灵活的扩展,部署;如何设计服务的并发策略;选择怎样的I/O处理模型;如何降低业务逻辑复杂度;如何处理负载;如何优化数据库......我们还有很长的路要走。

推荐书籍​​《构建高性能Web站点》​​,感谢作者 郭欣给大家提供了这么一本很优秀的国产书籍。

开源项目github—​​《 高性能TCP网络服务器程序》​​,​​《 基于TCP协议的远程过程调用框架客户端实现》​​,​​《 解耦网络接入层的一个简单微服务框架示例》​​。