编者按:本文由jojo.zhou在众成翻译平台上翻译。
在我们谈及到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
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属性启用它。
constrequest = 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 举报,一经查实,本站将立刻删除。