Engineering

Serverless Computing first steps

No items found.
This is a translated and updated version of the article published a few years ago, if you prefer you can read the outdated version in Portuguese đŸ‡§đŸ‡· here.

The term Serverless became quite known in the past few years thanks to the popularisation of the use of AWS Lambda, Google Cloud Functions, Azure Cloud Functions and others. The idea behind Serverless computing is the consolidation of the term FaaS (Function as a Service), that exists since 2014 so that developers can create any kind of application without the need to configure, maintain and escalate servers.

The most popular tool to work with Serverless using Node.js is Serverless Framework, because of the long list of providers (AWS, Azure, Tencent, Google, Cloudflare and others) and the huge documentation. This is the tool we’ll use in this article.

There’s some important things to keep in mind before we start:

  • Although the term is “Serverless”, it doesn’t mean that there are no servers behind it, it means that us as developers won’t have to worry about server management, scaling options, optimise availability and more. For example, new instances spin up automatically if you need, without the need to manually provision them.
  • Serverless functions are stateless, which means that each request is independent, it doesn’t have any relation with previous or future requests.
  • The server gets warmed up by a request called cold start and it'll stay alive awaiting another request. If another request is not received in the specified time, the server shuts down. But the cool thing is that, since the server is already warmed up, when another request arrives it can run instantly.

Let’s get our hands dirty then. I’ll show you the very first steps for creating a Serverless function for a prize draw.

Some people are participating in a prize draw to win a trip to the Maldivas and we need to make a service that will receive the list of people participating and randomly choose a winner.

If we were writing this function without using Serverless Framework, this is how we’d do it:

function getRandomUser(users) {
  const randomIndex = Math.floor(Math.random() * users.length)

  return users[randomIndex]
}
module.exports = getRandomUser

When we are dealing with Serverless Framework we have to be aware of some things first:

The function, when called, receives three parameters: Event, Context and Callback.

Event (Object)

When we do a HTTP request using Node we get the Request object containing a lot of request information, such as headers and body, but when it comes to the Event object the logic is the same, we receive all the request information through it.

Context (Object)

The Context object contains the metadata of the function call. In our case, using AWS Lambda, our context must contain an AWS Request Id, the name of the function, the name of the group log, memory limit, remaining time until the end of the execution and more.

We’ll talk about the Callback parameter later.

So, our function now should look like this:

function getRandomUser(event) {
    const users = event.body.users;
    const randomIndex = Math.floor(Math.random() * users.length);
    
    return users[randomIndex];
}
module.exports.handler = getRandomUser;

To get the users array we only need to access it through event.body.users. Now you probably have some questions: “but where is this array coming from? How do I pass it to the function? How do I even test it?”

Well, calm down, it’s pretty simple 😊

Testing a Serverless function

First of all, to make our lives easy let’s create a file called sample-event.js containing an array of all the users participating in the prize draw. Then create a folder called functions and a file called getRandomUser.js inside it, then paste our function's code in it.

Installing and configuring Serverless Framework

Now we’re going to install the Serverless Framework using the command npm i -g serverless


Usually you’ll need to install it locally on your project to be able to deploy your functions through a CI, but in our case we’ll only need to use the CLI commands, that’s why we’re installing it globally.

If everything goes well you should get the list of all the available commands by running serverless — help.

Now let’s configure our Serverless application. Create a serverless.yml file and we'll give our application and function a name:

service: serverlessFirstSteps 
provider:
  name: aws
  runtime: nodejs8.10
  functions:
    getRandomUser:
      handler: functions/getRandomUser.handler

Here's what is happening:

  • service: The name of the service.
  • provider: Information about the provider you choose (here we are using AWS but remember that they offer some other options if you prefer).
  • runtime: Node version (nodejs10.x, nodejs12.x, nodejs14.x).
  • functions: All the functions set up.
  • getRandomUser: Our function’s name. It can be literally anything you want.
  • handler: The path to our function. This might be confusing at first, but here’s some more examples to make it clearer.
    If our file was called app.js and our function was exported like module.exports.getRandomUser = getRandomUser , our handler would look like functions/app.getRandomUser.
    If our file was called drawService.js and our function was exported like module.exports.getDrawWinner = getRandomUser, our handler would look like functions/app.getDrawWinner.

Now we can test our function locally, and to do this we run serverless invoke local --function getRandomUser --path sample-event.js, the function flag receives the name of the function and the path flag receives the path to our sample array that will be passed to the function within the event parameter.

After running you should have the first winner of our prize draw.

Now let’s make things more interesting, shall we?

Our function as it is can only be invoked manually and that’s not useful at all, right? One of the many advantages of using Serverless Framework is that we can trigger our function from a HTTP call, or maybe a cron job, or even Alexa. Amazing, right?
What about turning the function into an endpoint that we can call every time we have a new prize draw?

Turn the sample-event.js file into a json file

{
  "users": [
    {
      "name": "Olivia",
      "lastname": "Medeiros",
      "email": "olivia@outlook.com"
    },
    {
      "name": "Madison",
      "lastname": "da Silva",
      "email": "madison@uol.com"
    },
    {
      "name": "Sabrina",
      "lastname": "Souza",
      "email": "sabrina@hotmail.com"
    },
    {
      "name": "CauĂŁ",
      "lastname": "Junior",
      "email": "caua@gmail.com"
    },
    {
      "name": "Lucas",
      "lastname": "Lopes",
      "email": "lucas@hotmail.com"
    },
    {
      "name": "Maria",
      "lastname": "Rodrigues",
      "email": "maria@gmail.com"
    }
  ]
}

We’ll modify our configuration a little.

service: serverlessFirstSteps 
provider: 
  name: aws 
  runtime: nodejs8.10 
functions: 
  getRandomUser: 
    handler: functions/getRandomUser.handler
    events:
      - http:
          path: api/random-user
          method: GET
plugins:
  - serverless-offline
  • events: Indicates that we’re gonna use some kind of event to trigger the function. This starts the events configuration.
  • http: Here we’re specifying that the event we’re using to trigger the function is a HTTP request.
  • path: the path we want to use in our endpoint.
  • method: The HTTP method.
  • plugins: The list of plugins you’re using. You can find the list of available plugins here.

Now we need to make some changes in our code as well.

function getRandomUser(event, _context, callback) {
  const { users } = JSON.parse(event.body)
  const randomIndex = Math.floor(Math.random() * users.length)

  return callback(null, {
    statusCode: 200,
    body: JSON.stringify(users[randomIndex]),
  })
}
module.exports.handler = getRandomUser

Remember the third parameter? We need it now. The Callback parameter, as the name says, is a callback function that you’ll call when you want the execution to finish and return something to the client.
The first parameter this function receives is an Error object, which in our case is null. The second parameter is the response, it must contain the status code, but the body can be empty.

Since the function is not deployed yet, we’ll need a plugin called serverless-offline to be able to call it locally. It can be installed by running yarn add -D serverless-offline .

Run serverless offline , wait for the output and you should see this:

Server ready: http://localhost:3000 🚀

Open Postman or any other API Client of your preference and do a POST request passing the content of the sample as the body.

The result of this request should be an object with one of our users, for example:

Nice, right? Now to the last part of this tutorial: deploying our function. If you haven’t set your AWS credentials in your .bashrc or .zshrc, now it's time to do so. After declaring your credentials, simply run serverless deploy --stage production, wait for the build/deploy to finish and you have a fully deployed function. At the end of the building the framework gives you an API Gateway url that you can use to make a request to the endpoint we created.
Just for comparison, if we were doing this same API without using Serverless Framework, we would have to create an EC2 instance manually and worry about keeping the server up and monitoring it to make sure it's up 24/7.

Now I recommend you to start exploring Serverless possibilities — as I said before, it can be triggered by a lot of different events which makes it an incredibly powerful tool. Here’s the Serverless Framework and AWS Lambda documentation to help you through your exploration. Have fun!

Serverless Computing first steps
was originally published in YLD Blog on Medium.
Share this article: