Look Ma, No Servers !!
In this blog we discuss about our experience of building a simple game using serverless components.
We at MORE participated in an event for AWS and decided to let our visitors play a small game at our booth, a simple memory game. The game went as follows:
1. The player was initially shown 8 pairs of cards in a 4 X 4 grid.
2. After the player got a chance to see them, the cards were all turned face down.
3. The player then had to select a card and in the next click select the same card from the remaining ones, to match them as a pair.
4. Each player was given a limit of 2 minutes to complete the game.
5. The player — with a strong memory — that could complete the game in the smallest amount of time was the winner.
The idea of the game was simple, and we wanted to keep the architecture also simple. We decided to go serverless for this simple game.
So, what is serverless? How can a service really be serverless? Serverless in reality does use servers and other infrastructure underneath, however — and this is what makes it wonderful — you don’t have to worry about infrastructure provisioning or configuration or scaling. This is how AWS defines serverless –
“Serverless Computing eliminates infrastructure management tasks such as server or cluster provisioning, patching, operating system maintenance, and capacity provisioning. You can build them for nearly any type of application or backend service, and everything required to run and scale your application with high availability is handled for you.”
So how did we actually go “serverless” and what are the various components we used?
The architecture looks like this:
The AWS services we used were
1. AWS S3 to host static frontend files
2. AWS API gateway for the UI to make calls to the Lamba Functions
3. AWS lambda functions that holds the business logic
4. AWS DynamoDB that holds user’s game scores and other details.
Let us look at the components in detail.
AWS S3 — S3 is Amazon’s Simple Storage Service that provides object-based storage. In S3 users can create “buckets” and upload files into these buckets. It is possible to control who has access to which files as well as life cycle of files within these buckets. Please note, this is again a serverless service. While you are working with objects, you are not worried about configuring disk space, monitoring available storage space etc. A classic example of a serverless service.
S3 can also be used to host a static website. The requirement in this case is that the name of the bucket match the domain name in addition to making a few DNS settings with the domain name provider.
For our game, the UI was developed in angular.js and after compiling, the files were uploaded to a bucket. The bucket name mapped to the URL we were using for the game. The moment players hit the URL for our game, the files were being rendered from the corresponding S3 bucket. The “cards” which actually where images of AWS service logos, were also stored in another S3 bucket. On start of the game, the UI requested the “backend” to provide a randomized list of cards to be displayed.
The matching logic was handled in the UI and in the end, the UI sent a request to the “backend” to store user and user score details.
AWS Lamba functions — AWS Lambda is the crux of our solution. With Lambda, you can run code for virtually any type of application or backend service — all with zero administration. Just upload your code and Lambda takes care of everything required to run and scale your code with high availability. Under the hood of course, AWS does a lot of work in making the required hardware available, monitoring the use of the lambda functions and scaling hardware as needed. In a non-lambda world, we would have had to manage all this ourselves — set up load balancers, set up auto-scaling VM groups etc. However with lambda functions, this becomes redundant. The other most important benefit of lambda is that you pay only for the time your request is being processed. This is another major advantage over managing infrastructure yourself.
So now, you have written your business logic, uploaded your code , but how and when will this code get invoked? What is needed is a trigger for function execution.
Some of the triggers that can invoke a lambda function are:
1. An HTTP URL
2. An event triggered by uploading a file to S3
3. An event from a kinesis stream
In addition to the above, there are a host of services in AWS that integrate seamlessly with AWS Lambda functions.
For our game, we chose an HTTP URL as a trigger. The mapping of the URL with the Lambda function was done using AWS API gateway. Amazon API Gateway is a fully managed service that makes it easy for developers to create, publish, maintain, monitor, and secure APIs at any scale. The API gateway is a powerful service that lets you create multiple versions of an API. It has integrations with AWS Cognito and AWS identity and access management policies to manage authorization. Integration with Cloud Trail provides monitoring and logging as well.
The AWS API Gateway helped us publish the backend logic running as a lambda function as a secure API.
The last bit of the solution consists of AWS dynamodb. DynamoDB is a NoSQL database as a service. Unlike some of the other NoSQL databases, DynamoDB does not need you to manage shards, nodes and other configuration. Amazon DynamoDB is a key-value and document database that delivers single-digit millisecond performance at any scale. It’s a fully managed, multi-region, multi-master database with built-in security, backup and restore, and in-memory caching for internet-scale applications. All the player data and scores were stored in DynamoDB from the lambda function.
One of the major questions when we decided to go serverless was how do we debug? How do we access log files? Cloud Trail integrates with all these services , collects logs from them and you can see them on the web based console.
So, to summarize the flow is as follows
1. When the user invokes the URL, the request is served from S3.
2. When the user performs any action, the request is sent to API Gateway.
3. The API gateway then invokes the corresponding lambda function
4. The lambda function then stores the user data in DynamoDB.
The deployment process was fairly simple. Once the UI code was ready and compiled, it was pushed to the corresponding S3 bucket. The java code was deployed as Lambda functions and the API was configured in the API gateway to invoke the lambda functions. The API gateway was assigned the necessary roles to invoke the lambda function.
That’s it! The game was on.
The entire game end to end was built in a very short time. Deployment did not need any installation or configuration and while the event was on, we never had to worry about the game being very popular and not scaling. Server-less truly makes development and deployment smooth.