微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用Node.js理解和测量HTTP时序

编者按:本文由jojo.zhou在众成翻译平台上翻译。

理解和测量HTTP时序帮助我们去发现客户端与服务器服务器与服务器之间通信的性能瓶颈。本文阐述了在一次HTTP请求中的时序,并展示了如何在Node.js中进行测量。

在我们谈及到HTTP时序之前,让我们看一下基本的概念:

  • IP(Internet Protocol) : IP是网络层的协议,处理网络地址和路由。IP的责任是根据数据包的头部信息,通过一个或更多的IP网络,将源主机的包传送到目的主机,它还定义了用于封装分发数据的包结构。

  • DNS(Domain Name Servers) : DNS是一种分层分散式的命名系统。用于将类似于risingstack.com的人类可读的域名解析为机器可读的IP地址。

  • TCP(Transmission Control Protocol):TCP标准定义了在应用交换数据时,如何去建立和保持网络会话。TCP为运行在IP网络请求的应用程序提供了可靠、有序、和错误检查的八位字节流。HTTP的客户端通过建立TCP连接来发起请求。

  • SSL/TLS(Transport Layer Security):TLS是一种通过计算机网络提供通信安全的加密协议。SSL(Secure Sockets Layer)是TLS的不推荐使用的前身。 TLS和SSL都使用证书建立安全连接。 SSL证书不依赖于加密协议(如TLS),证书包含密钥对:公钥和私钥。这些密钥一起工作,建立一个加密的连接。

现在,让我们看一下一次普通的HTTP请求时间轴

时间段的解释:

  • DNS Lookup: DNS的查询时间。DNS查询解决了域名到IP的解析。每一个新的域名需要一个完整的往返来完成域名的查询。当目的地已经在IP地址时,DNS的查询便结束了。

  • TCP Connection: TCP连接源主机和目的主机的时间。连接必须正确地建立在多次握手过程中。TCP的连接被操作系统所管理,如果在TCP之下的连接无法被连接,操作系统范围内的TCP连接超时将超出我们应用范围内的超时配置。

  • TLS handshake:完成一次TLS的握手时间。在握手过程中,端点交换认证和密钥来建立和恢复安全的会话。没有HTTPS的请求就没有TLS握手。

  • Time to First Byte(TTFB): 初始响应的时间。这个时间除了等待服务器处理请求和返回响应的时间之外,还可以捕获往返服务器的延迟。

  • Content Transfer: 接受数据的时间。它的长度取决于返回数据的大小和可用的网络带宽。

如何借助HTTP时序发现性能瓶颈?

举个例子:如果你的DNS查询比你期望的时间更长,这个问题可能是因为你的DNS供应商或者DNS缓存设置引起的。

Time to First Byte比预期更长时,应该检查端点之间的延迟,还有当前服务器的负载

Content Transfer过慢可能是由于返回的数据太大不够高效(无用的JSON属性值等)或者过慢的网络连接等。

使用Node.js测量HTTP的请求时序

使用Node.js测量HTTP的时序,我们需要订阅一个特定的HTTP请求、响应和socket事件。这里有一个只关注时序的简短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.'end', () => {

      timings.endAt = process.hrtime()

    })

  })

  req.'socket', (socket) => {

    socket.'lookup', () => {

      timings.dnsLookupAt = process.hrtime()

    })

    socket.'connect', () => {

      timings.tcpConnectionAt = process.'secureConnect', () => {

      timings.tlsHandshakeAt = process.hrtime()

    })

  })

DNS Lookup(DNS查询) 只在有域名的情况才有:

// There is no DNS lookup with IP address

const dnsLookup = dnsLookupAt !== undefined ?

  getDuration(startAt, dnsLookupAt) : undefined

TCP Connection(TCP连接)当host被解析后会立刻建立连接:

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

TLS handshake (SSL) 只发生在HTTPS的请求协议中:

// There is no TLS handshake without https

const tlsHandshake = tlsHandshakeAt !== undefined ?

      getDuration(tcpConnectionAt, tlsHandshakeAt) : undefined

我们等待服务器去发送 First Byte(第一个字节):

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

Content Transfer(内容传送) 开始于第一个字节流:

const contentTransfer = getDuration(firstByteAt, endAt)

Total Duration(总共持续时长) 由开始到最后的计算:

const total = 在GitHub上查看完整的代码example

使用工具测量时序

现在我们已经知道了Node去测量HTTP时序,让我们看一下现有的能帮助你理解HTTP请求的工具。

request 模块

流行的request模块具有内置的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时序。

Jaeger中使用opentracing-auto测量HTTP时序。

总结

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


奇舞周刊

——————————————————

领略前端技术 阅读奇舞周刊


长按二维码,关注奇舞周刊

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐