Skip to main content

When performing client to server or server to server communication, many web developers usually try to find performance bottlenecks. This issue can cause a big disappointment for your client. Therefore, it should be finished quickly before it fails your client. In this article, we will discuss on how timings are happened in an HTTP request and understand how to measure them in Node.js. Take a look at the information below.

There are some basic concepts that you have to know before we talk about HTTP timings.

  • IP (Internet Protocol): IP is a network-layer protocol, dealing with network addressing and routing. You can deliver packets from the source host to the destination host based on the packet headers across one or more IP networks. It also defines packet structures that encapsulate the data to be delivered.
  • DNS (Domain Name Servers): To resolve human-readable hostnames like risingstack.com into machine-readable IP addresses, developers use DNS. It is a hierarchical decentralized naming system.
  • TCP (Transmission Control Protocol): Basically, the TCP standard describes how to establish and maintain a network conversation between applications to exchange data. Between applications running on hosts communicating over an IP network, TCP provides reliable, ordered, and error-checked delivery of a stream of octets. An HTTP client initiates a request by establishing a TCP connection.
  • SSL/TLS (Transport Layer Security): TLS is known as a cryptographic protocol that offers communications security over a computer network. While SSL (Secure Sockets Layer) is a deprecated predecessor to TLS. In order to establish a secure connection, both TLS and SSL use certificates. A certificate contains a key pair, such as a public and a private key; therefore SSL certificates are not dependent on cryptographic protocols like TLS.

How Do HTTP Timings Help Us Discover Bottlenecks?

You will notice that something wrong happens when DNS Lookup takes longer time than you expected. Commonly, the problem is in DVS provider or with your DNS caching settings.

You should check out the latency between the endpoints when you see longer Time to First Byte. You should bear in mind that you  always have to check out the current load of the server.

There are two reasons that cause slow content transfer, such as inefficient response body like sending back too much data (unused JSON properties, etc.) or by slow connections as well.

Measuring HTTP Timings in Node.js

We need to subscribe to a specific request, response and socket events to measure HTTP timings in Node.js. In order to know how a short code snippet works in Node.js, you can take a look on the example below which focuses only to the timings:

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 Lookup only happens with domain names:

// There is no DNS lookup with IP address

const dnsLookup = dnsLookupAt !== undefined ?

  getDuration(startAt, dnsLookupAt) : undefined

 

TCP Connection happens immediately after the host is resolved:

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

 

TLS handshake (SSL) happens only with https protocol:

// There is no TLS handshake without https   

const tlsHandshake = tlsHandshakeAt !== undefined ?

      getDuration(tcpConnectionAt, tlsHandshakeAt) : undefined

We wait for the server to start sending First Byte:

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

 

Content Transfer starts with the first byte:

const contentTransfer = getDuration(firstByteAt, endAt)

Total Duration is calculated from start and end dates:

const total = getDuration(startAt, endAt)

 

Tools to Measure Timings

After knowing how to measure HTTP timings with Node, let’s talk about existing tools that you can use to understand your HTTP requests.

Request module

In popular request module, you can discover a built-in method to measure HTTP timings. Use time property to enable it.

const request = require(‘request’)

 request({

  uri: ‘https://risingstack.com’,

  method: ‘GET’,

  time: true

}, (err, resp) => {

  console.log(err || resp.timings)

})

 

Distributed Tracing

You can also collect HTTP timings with distributed tracing tools and visualize them on a timeline. Therefore, you can know what’s happening in the background and how much is the real cost of building distributed systems. RisingStack’s opentracing-auto library has a built-in flag to collect all the HTTP timings with OpenTracing.

 

That’s what you need to know about using Node.js to understand and measure HTTP Timings. HTTP Timings need to be measured in order to discover performance bottleneck location. With Node ecosystem, you can extract these metrics from your application.