使用Node.js了解和测量HTTP花费的时间

了解和测量HTTP时间有助于咱们发现客户端到服务器服务器到服务器之间的通讯性能瓶颈。 本文介绍了HTTP请求中的时间开销,并展现了如何在Node.js中进行测量。node

在咱们开始了解HTTP时间开销以前,让咱们来看一些基本的概念:git

  • IP(互联网协议):IP是网络层协议,涉及网络寻址和路由。 IP负责根据一个或多个IP网络上的数据包头将数据包从源主机传送到目标主机。 它还定义了封装要传递的数据的数据包结构。
  • DNS(域名服务器):DNS是一种分层分散式命名系统,用于将诸如risingstack.com的人类可读主机名解析为机器可读的IP地址。
  • TCP(传输控制协议):TCP标准定义了如何在应用程序之间创建和维护网络对话以交换数据。 TCP在经过IP网络通讯的主机上运行的应用程序之间提供可靠,有序和错误检查的八位字节流。 HTTP客户端经过创建TCP链接来发起请求。
  • SSL / TLS(传输层安全性):TLS是一种经过计算机网络提供通讯安全性的加密协议。 SSL(安全套接字层)是TLS的不推荐使用的前身。 TLS和SSL都使用证书创建安全链接。 SSL证书不依赖于加密协议(如TLS),证书包含密钥对:公钥和私钥。 这些密钥一块儿工做,创建一个加密的链接。

如今咱们来看一下一般HTTP请求的时间表:

clipboard.png

  • DNS查找:执行DNS查找所花费的时间。 DNS查找将域名解析为IP地址。 每一个新的域须要一个完整的往返行程来进行DNS查找。 当目的地已是IP地址时,没有DNS查找。
  • TCP链接:在源主机和目标主机之间创建TCP链接所需的时间。 必须在多步握手过程当中正确创建链接。 TCP链接由操做系统管理,若是基础TCP链接没法创建,则OS范围的TCP链接超时将会进入咱们应用程序中的超时配置。
  • TLS握手:完成TLS握手的时间。 在握手过程当中,端点交换认证和密钥以创建或恢复安全会话。 没有HTTPS请求的不须要TLS握手。
  • 第一个字节的时间(TTFB):等待初始响应的时间。 此时间除了等待服务器处理请求和传递响应所花费的时间以外,还能够捕获往返服务器的延迟。
  • 内容传输:接收响应数据所花费的时间。 响应数据的大小和可用的网络带宽决定其持续时间。

如何经过HTTP时间开销帮助发现性能瓶颈?

例如,若是您的DNS查询所花费的时间比预期的要长,那么问题多是您的DNS提供商或DNS缓存设置。github

缓慢的内容传输多是由效率低下的反应机构引发的,例如发回太多的数据(未使用的JSON属性等)或缓慢的链接。缓存

测量Node.js中的HTTP时间开销

为了测量Node.js中的HTTP时间开销,咱们须要订阅特定的请求,响应和套接字事件。 这是一个简短的代码片断,展现了如何在Node.js中执行此操做,此示例仅关注时序:安全

const timings = {
    // use process.hrtime() as it's not a subject of clock drift
    startAt: process.hrtime(),
    dnsLookupAt: undefined,
    tcpConnectionAt: undefined,
    tlsHandshakeAt: undefined,
    firstByteAt: undefined,
    endAt: undefined
  }

  const req = http.request({ ... }, (res) => {
    res.once('readable', () => {
      timings.firstByteAt = process.hrtime()
    })
    res.on('data', (chunk) => { responseBody += chunk })
    res.on('end', () => {
      timings.endAt = process.hrtime()
    })
  })
  req.on('socket', (socket) => {
    socket.on('lookup', () => {
      timings.dnsLookupAt = process.hrtime()
    })
    socket.on('connect', () => {
      timings.tcpConnectionAt = process.hrtime()
    })
    socket.on('secureConnect', () => {
      timings.tlsHandshakeAt = process.hrtime()
    })
  })

DNS查找只会发生在有域名的时候:服务器

/ There is no DNS lookup with IP address
const dnsLookup = dnsLookupAt !== undefined ?  
  getDuration(startAt, dnsLookupAt) : undefined

TCP链接在主机解析后当即发生:网络

const tcpConnection = getDuration((dnsLookupAt || startAt), tcpConnectionAt)

TLS握手(SSL)只能使用https协议:socket

// There is no TLS handshake without https    
const tlsHandshake = tlsHandshakeAt !== undefined ?  
      getDuration(tcpConnectionAt, tlsHandshakeAt) : undefined

咱们等待服务器开始发送第一个字节tcp

const firstByte = getDuration((tlsHandshakeAt || tcpConnectionAt), firstByteAt)

总持续时间从开始和结束日期计算:分布式

const total = getDuration(startAt, endAt)

看到整个例子,看看咱们的https://github.com/RisingStac...仓库。

测量时间的工具

如今咱们知道如何使用Node测量HTTP时间,咱们来讨论可用于了解HTTP请求的现有工具。

request module

著名的request module具备测量HTTP定时的内置方法。 您可使用time属性启用它。

const request = require('request')

request({  
  uri: 'https://risingstack.com',
  method: 'GET',
  time: true
}, (err, resp) => {
  console.log(err || resp.timings)
})

分布式跟踪

可使用分布式跟踪工具收集HTTP定时,并在时间轴上可视化它们。 这样,您能够全面了解后台发生的状况,以及构建分布式系统的实际成本是多少。

RisingStack的opentracing-auto库具备内置的标志,可经过OpenTracing收集全部HTTP时间。

clipboard.png

在Jaeger中使用opentracing-auto的HTTP请求时序。

总结

使用Node.js测量HTTP时间能够帮助您发现性能瓶颈。 Node生态系统提供了很好的工具来从应用程序中提取这些指标。

关注个人公众号,更多优质文章定时推送

clipboard.png

翻译自Understanding & Measuring HTTP Timings with Node.js

相关文章
相关标签/搜索