Gunnar Assmy - Fotolia

Tip

AWS WebSocket support ushers in real-time serverless features

The WebSockets vs. HTTP debate has changed for AWS users. With WebSocket support for Amazon API Gateway, users can build serverless applications that can communicate instantaneously.

Serverless application developers who seek stateful connections that serve up real-time information can rely on AWS' native support of WebSocket APIs in Amazon API Gateway.

As the name implies, WebSocket APIs connect much like a socket on a network, and the user can send and receive content asynchronously. WebSockets enable Amazon API Gateway to run serverless applications that need real-time chat messaging, real-time push notifications to clients and other features.

Before AWS users had native WebSocket support, they could not build serverless applications that required real-time communications. Developers had to design applications to either run on a third-party HTTP server, such as Nginx, or perform real-time displays via hacked-together AWS IoT services. With native AWS support for WebSocket APIs, developers can simply configure API Gateway to know which Lambda function to call and when.

With the boost of Amazon's WebSockets support, AWS developers need to understand how a WebSocket API connection differs from HTTP, the best AWS WebSocket use cases and ones to avoid, and how to set up WebSocket APIs for real-time communications.

WebSockets vs. HTTP connections

Unlike HTTP endpoints, WebSockets are stateful. WebSocket APIs form persistent connections; traditional HTTP connections drop a connection to the browser after returning content. WebSocket APIs don't require repeated connection logic, and the client and server both have much less overhead once connected than they do with HTTP connections.

HTTP polling is a technique that lets an application retrieve information based on a client pulling data. By contrast, WebSocket APIs enable the server to push content in real time to the browser. WebSockets also bypass the issue of connections timing out after 30 seconds, since they can send back data asynchronously any time after the client is connected.

When AWS WebSockets don't fit

Consider WebSockets for always-on devices, but beware that the technology can cause problems for systems that don't need an always-connected client.

WebSockets are great for applications that rely on real-time data, such as a chat feature that users expect to update immediately, no matter how many new entries occur. They also suit applications that rely on data-intensive workflows where the client is most frequently on a stable connection. Chat applications, analytics applications and big data analysis applications do not rely on a typical request/response resource but instead can operate much more asynchronously.

These AWS WebSocket interactions are not, however, designed to fit the needs of blogs, basic e-commerce sites or other applications that mostly serve up semistatic information.

WebSockets are a great addition to single-page application capabilities on AWS, but the cloud provider cannot serve up a WebSocket API application entirely on its own. Instead, the technology is a way to provide an API for a client application served up from a static content delivery network, relying on such services as S3 or CloudFront.

Get started with AWS WebSockets on API Gateway

Developers should think of Amazon API Gateway with WebSockets more like an Alexa skill than an HTTP endpoint. AWS WebSocket support enables developers to set up conceptual routes -- similar to Alexa intents -- that match specific inputs, as well as a default route that the WebSocket executes when no other pattern matches.

Typically, WebSockets are structured as a JSON data string request that's given an action, as well as other data to pass along to the serverless Lambda function. For example, if a developer needed to list all users with an email containing support, the application could use:

{ "action": "ListUsers", "data": { "email": "support" } }

Developers can use any basic message pattern here but should pick something standard, like action, to make things easily understood by anyone else who works with the code. Developers can specify the route selection expression when they create an API Gateway with a WebSocket API. In this case, it's the standard $request.body.action.

AWS WebSockets' default routes

All API Gateway WebSocket connections have three default routes, which all start with a dollar sign ($):

  1. $connect is triggered when a new client connects.
  2. $disconnect is triggered when a Websocket client disconnects.
  3. $default is triggered as a fallback, whenever no more specific action route is mapped.

Developers should always implement the $default handler. For most applications, the setup can be as simple as indicating that the command wasn't understood, so the client that connects doesn't wait for a response that will never come. Since WebSocket requests are asynchronous in nature, a client could send multiple requests before it gets a response, so the developer must set up a way to let the client know if one request is never going to receive a response.

Add request IDs

There is also no direct request/response relationship with asynchronous WebSocket requests. As clients can submit several requests at once, set WebSockets with request IDs so the client can match each response with the request that submitted it. For example, a request to search for stories with API Gateway in them might look like this:

{
    "request_id": 1,
    "action": "SearchStories",
    "query": "API Gateway"
}

The response should include all the relevant information the client needs to know:

{
    "request_id": 1,
    "action": "SearchStories",
    "query": "API Gateway",
    "results": [
         {
             "$type": "Story",
             "id": "2019-02-12-01",
             "title": "API Gateway Websockets"
         },
         {
             "$type": "Story",
             "id": "2019-02-12-02",
             "title": "API Gateway with Lambda functions"
         },
         …
    ]
}

Alternatively, set up the WebSocket API to stream results as they're found, so multiple results return, each on its own object:

{
    "request_id": 1,
    "result": {
         "$type": "Story",
         "id": "2019-02-12-01",
         "title": "API Gateway Websockets"
    }
}
{
    "request_id": 1,
    "result": {
         "$type": "Story",
         "id": "2019-02-12-02",
         "title": "API Gateway with Lambda functions"
    }
}

The client can start to display results more quickly when they stream, since the system doesn't require retrieval of all of the results before a response comes back.

How WebSockets push results to a client

When it comes to WebSockets vs. HTTP, WebSockets' greatest advantage is that back-end servers can push content out to clients when the servers have it, instead of requiring a client to poll for new results for a particular request.

For example, a user may want statistics on an email campaign. WebSockets can stream results live to the user's browser as customers open the email messages, instead of the user hitting refresh -- or getting an automatic refresh interval -- to see updated statistics. Applications accomplish this livestream with WebSockets on AWS via a publish and subscribe (PUB/SUB) approach.

To set up PUB/SUB, have the client subscribe to a particular request, such as monitoring an email campaign:

{ "action": "subscribe", "id": "stats/email-campaign/1" }

The back-end function should then register the connection handler from the WebSocket connection, commonly stored in a DynamoDB database or similar service. When the application receives a new event, such as when an email recipient clicks or opens an email, the back-end component checks the appropriate DynamoDB table and pushes the information out to all connection IDs that are subscribed to that particular topic ID.

This PUB/SUB interaction is similar to how Amazon Simple Notification Service operates, but as of now, it's not possible to register a connection ID directly with SNS to publish messages via AWS WebSockets. However, integration with Amazon SNS seems like a logical next step for API Gateway and WebSockets.

Dig Deeper on AWS cloud development