1
Introduction to serverless with Claudia

This chapter covers

  • What serverless is
  • The core concepts of serverless
  • The difference between serverless and hosted web applications
  • How Claudia fits
  • Why use serverless

Serverless is a method of deploying and running applications on cloud infrastructure, on a pay-per-use basis and without renting or buying servers. Instead of you, the serverless platform provider is responsible for capacity planning, scaling, balancing, and monitoring; the provider is also able to treat your applications as functions.

Wait, no servers? Seems like a new buzzword, a hipster cloud trend promising to revolutionize your life for the better.

This book explains what serverless is, what problems it solves, and where it does or doesn’t fit into your application development process, without fanboyishly showing off and selling serverless like some trendy cloud cult that everyone needs to follow. It does so with a pragmatic approach, explaining the concepts by teaching you how to build reliable and scalable serverless applications with Node.js and Claudia.js, while saving time and resources.

This chapter focuses on the concepts of serverless: what it is, why it matters, and how it compares to server-hosted web application development. Your main goal for this chapter is to gain a good understanding of basic serverless concepts and build a good foundation.

1.1 Servers and washing machines

To understand serverless, consider for a moment washing machines. A clothes-cleaning appliance might sound like a crazy place to start, but owning a server nowadays is similar to owning a washing machine. Everybody needs clean clothes, and the most logical solution seems to be buying a washing machine. But most of the time the washing machine is plugged in, doing nothing. At best, it’s used 5 to 15 hours per week. The same goes with servers. Most of the time, your average application server is just waiting to receive a request, doing nothing.

Interestingly, servers and washing machines have many common issues. They both have a maximum weight or volume they can process. Owning a small server is similar to owning a small washing machine; if you accumulate a big pile of laundry, the machine can’t process all of it at once. You can buy a bigger one that can take up to 20 pounds of clothes, but then you’ll find yourself in a situation where you want to clean just one shirt, and running a 20-pound machine for a single shirt seems wasteful. Also, setting up all your applications to run safely together on one server is tricky, and sometimes impossible. A correct setup for one app can completely mess up another one with a different setting. Similarly, with washing machines you have to separate clothes by color, and then choose the proper program, detergent, and softener combinations. If you don’t handle setup properly, the machine can ruin your clothing.

These issues, along with the problem that not everyone is able to own a washing machine, led to the rise of laundromats or launderettes—coin laundry machines that you rent for the time needed to wash your clothes. For servers, the same need has led many companies to start providing server rental services, either locally or in the cloud. You can rent a server, and the server provider takes care of the storage, power, and basic setup. But both laundromats and rental servers are just partial solutions.

For rentals of washing machines and servers, you still need to know how to combine your clothes or applications and set up the machines, choosing appropriate detergents or environments. You also still have to balance the number of machines and their size limitations, planning how many you will need.

In the world of dirty laundry, in the second half of the twentieth century, a new trend of “fluff and fold” services started. You can bring these services a single piece or a bag of clothes, and they will clean, dry, and fold your laundry for you. Some even deliver to your address. They usually charge by the piece, so you don’t need to wait to gather a specifically sized batch to clean, and you don’t have to worry about washing machines, detergents, and cleaning programs at all.

Compared to the clothes cleaning industry, the software industry is still in the era of self-service laundromats, as many of us still rent servers or use Platform as a Service (PaaS) providers. We are still estimating the number of potential requests (quantity of clothes) that we’re going to handle and reserving enough servers to (we hope) deal with the load, often wasting our money on servers that either are not operating at full capacity or are overloaded and unable to process all our customer requests.

1.2 The core concepts

So how does serverless change that? The name, implying having no server at all, doesn’t seem to be a logical solution. Go back to the definition:

Contrary to its name, serverless does not exclude the existence of servers; software requires hardware to run. Serverless just removes the need for companies, organizations, or developers to physically rent or buy a server.

You are probably wondering why serverless is so named. The answer lies in the serverless abstraction of the server concept. Rather than renting a server for your application, setting up the environment, and deploying it, you upload your application to your serverless provider, which takes care of assigning servers, storage, application handling, setup, and execution.

More precisely, the provider stores your application inside a certain container. The container represents an isolated environment that contains everything your application needs to run. You can think of the container as being a pot for houseplants. The plant pot contains earth filled with all the minerals your plant needs to live.

Like the plant pot, the container allows the serverless provider to safely move and store your application, and to execute it and make copies of it depending on your needs. But the main benefit of serverless is that you don’t do any server configuration, balancing, scaling—basically, any kind of server management. The serverless provider manages all of that for you while also guaranteeing that if a large number of calls to your application occur at the same time, it will clone enough containers to handle all the calls, and each clone will be an exact copy of the first. If necessary, the provider will create thousands of clones. The serverless provider decides to replicate a container only when the number of requests to your application becomes so big that the current container can’t handle all incoming requests.

Unless there is a request (a call) to your application, not a single instance of your application is running, so it isn’t wasting space, server time, or energy. The serverless provider is responsible for all the operational details, such as knowing where your application is stored, how and where to replicate it, when to load new containers, and when to reduce the number of replicated containers to unload the unused servers.

From the washing machine perspective, the process is like calling a fluff and fold cleaning service; the delivery guy appears at your door to pick up your dirty laundry, and the service cleans and then returns the laundry to you. No matter how much clothing you have and no matter what kinds (wool, cotton, leather, and so on), the cleaning company is responsible for all the processes of separation, detergent choice, and program selection.

1.3 How does serverless work?

As previously described, serverless providers supply an isolated compute container for your application. The compute container is event-driven, so it’s activated only when a certain event triggers.

Events are specific external actions that behave exactly like physical triggers. Take your home lights as an example: the events that turn them on can differ. A classic light switch is invoked by pressure; a motion sensor is tied to motion detection; a daylight sensor turns your lights on when the sun goes down. But containers are not limited to listening to the specified events and invoking your contained functions; they also provide a way for your functions to create events themselves, or, more precisely, to emit them. In a more technical manner, with serverless, your function containers are both event listeners and event emitters.

Finally, serverless providers offer various triggers that can run your functions. The list of triggers depends on the provider and implementation, but some of the most common triggers are HTTP requests, file uploads to file storage, database updates, and Internet of Things (IoT) events. There are many more.

1.4 Serverless in practice

The whole serverless landscape contains lots of moving parts, so we introduce it gently. We build an example application and bring in one piece at a time, so you can see how it fits. As you slowly pick up each new concept, you’ll expand your example application.

This book takes a greenfield approach to its example application (it will be built from scratch), and it handles the problems of a small company—more precisely, a pizzeria. The pizzeria is managed by your fictional Aunt Maria. During the course of the book, Aunt Maria will face a lot of real-world problems, and your goal will be to help her while grasping serverless concepts along the way. Serverless, like every new technology, introduces a lot of new concepts that can be difficult to handle all at once.

1.4.1 Aunt Maria’s serverless pizzeria

Aunt Maria is a strong-willed person. For more than three decades, she has been managing her pizzeria, which was the place where many generations of people from the neighborhood spent time with their families, laughed together, and even went on romantic dates. But recently, her pizzeria has seen some rough times. She’s told you that she’s seeing fewer and fewer customers. Many of her customers now prefer ordering online via websites or their phones rather than visiting in person. Some new companies have started stealing her customers. The new Chess’s pizzeria, for example, has a mobile app with pizza previews and online ordering, and also a chatbot for ordering via various messenger applications. Your aunt’s customers like her pizzeria, but most want to order from their homes, so her three-decades-old business has started to wane.

The pizzeria already has a website, but it needs a back-end application to process and store information on pizzas and orders.

1.4.2 A common approach

Given Aunt Maria’s limited resources, the easiest solution is to build a small API with a popular Node.js framework, such as Express.js or Hapi, and set up a pizza database in the same instance (most likely MongoDB, MySQL, or PostgreSQL).

A typical API would have its code structured in a few layers resembling a three-tier architecture, meaning that the code is split into presentational, business, and data tiers or layers.

The typical three-tier application design would be similar to figure 1.1, with separate routes for pizzas, orders, and users. It would also have routes for webhooks for both chatbots and a payment processor. All the routes would trigger some handler functions in the business layer, and the processed data would be sent to the data layer—database and file and image storage.

01-01-9781917294723.eps

Figure 1.1 The typical three-tier design for the Pizza API

This approach fits perfectly for any given small application. It would work fine for your Pizza API, at least until online pizza orders grow to a certain level. Then you would need to scale your infrastructure.

But to be able to scale a monolithic application, it’s necessary to detach the data layer (because you don’t want to replicate your database, for the sake of data consistency). After that, your application would look like the one shown in figure 1.2. But you’d still have one conglomerate of an application with all its API routes and the business logic for everything. Your application could be replicated if you had too many users, but each instance would have all its services replicated as well, regardless of their usage.

01-02-9781917294723.eps

Figure 1.2 A common approach with an external database and file storage for the Pizza API

1.4.3 Serverless approach

Creating serverless applications requires a different approach, as these applications are event-driven and fully distributed.

Instead of having one server with the API endpoints and your business logic, each part of your application is isolated to independent and autoscalable containers.

In a serverless application, your requests are processed with an API router layer that has only one job: it accepts HTTP requests and routes them to the underlying business layer services. The API router in a serverless architecture is always independently managed. That means that application developers don’t maintain the API router, and it’s scaled automatically by the serverless provider to accept all the HTTP requests your API is receiving. Also, you pay only for the requests that are processed.

In the case of your Pizza API, the router will receive all the API requests from the mobile and web applications, and if necessary handle webhooks from chatbots and the payment processor.

After an API request is routed, it is passed to another container with the business layer service to be processed.

Instead of having one monolithic application, the business logic of a serverless application is often split into smaller units. The size of each unit depends on your preferences. A unit can be as small as a single function or as large as a monolithic application. Most of the time, its size does not directly affect the infrastructure cost, because you are paying for function execution. Units are also scaled automatically, and you won’t pay for units that aren’t processing anything, so owning one or a dozen of them costs the same.

However, for small applications and situations in which you don’t have a lot of information, you can save money on hosting and maintenance by bundling functionalities related to one service into a single business unit. For your Pizza API, a sensible solution is to have one unit for processing pizzas and orders, one for handling payments, one for handling chatbot functionality, and one for processing images and files.

The last part of your serverless API is the data layer, which can be similar to the data layer in a scaled monolithic application, with a separately scaled database and file storage service. It would be best if the database and file storage were also independent and autoscalable.

Another benefit of a serverless application is that the data layer can trigger a serverless function out of the box. For example, when a pizza image is uploaded to the file storage, an image processing service can be triggered, and it can resize the photo and associate it with the specific pizza.

You can see the flow of the serverless Pizza API in figure 1.3.

01-03-9781917294723.eps

Figure 1.3 The serverless approach for the Pizza API

1.5 Serverless infrastructure — AWS

Your serverless Pizza API needs infrastructure to run on. Serverless is very young and at the moment has several infrastructure choices. Most of these choices are owned by big vendors, because serverless requires a big infrastructure for scaling. The best-known and most advanced infrastructures are Amazon’s AWS Lambda serverless compute container, Microsoft’s Azure Functions, and Google’s Cloud Functions.

This book focuses on AWS Lambda because AWS has the most mature serverless infrastructure available in the market, with a stable API and many successful stories behind it.

AWS Lambda is an event-driven serverless computing platform provided by Amazon as part of Amazon Web Services. It is a compute service that runs code in response to events and automatically manages the compute resources required by that code.

In the Amazon platform, the word serverless is usually directly related to AWS Lambda. But when you are building a serverless application such as your Pizza API, AWS Lambda is just one of the building blocks. For a full application, you often need other services, such as storage, database, and routing services. In table 1.1 you can see that AWS has fully developed services for all of them:

  • Lambda is used for computing.
  • API Gateway is a router that accepts HTTP requests and invokes other services depending on the routes.
  • DynamoDB is an autoscalable database.
  • Simple Storage Service (S3) is a storage service that abstracts the standard hard drives and offers you unlimited storage.
Table 1.1 The building blocks of serverless applications in AWS
FunctionalityAWS serviceShort description
ComputingLambdaComputing component, used for your business logic
RouterAPI GatewayRouting component, used to route HTTP request data to your Lambda function
DatabaseDynamoDBAutoscalable document database
StorageS3Autoscalable file storage service

Lambda is the most important serverless puzzle piece you need to understand, because it contains your business logic. Lambda is AWS’s serverless computing container that runs your function when an event trigger occurs. It gets scaled automatically if many events trigger the function at the same time. To develop your Pizza API as a serverless application, you will need to use AWS Lambda as its serverless compute container.

When a certain event occurs, such as an HTTP request, a Lambda function is triggered, with the data from the event, context, and a way to reply to the event as its arguments. The Lambda function is a simple function handler written in one of the supported languages. At this time of this writing, AWS Lambda support the following languages:

  • Node.js
  • Python
  • Java (Java 8 compatible) and other JVM languages
  • C# (.NET Core)

In Node.js, event data, context, and a function callback are passed as JSON objects. The context object contains details about your Lambda function and its current execution, such as execution time, what triggered the function, and other information. The third argument that your function receives is a callback function that allows you to reply with some payload that will be sent back to the trigger, or an error. The following listing shows a Node.js sample of a small AWS Lambda function that returns the text Hello from AWS Lambda.

Listing 1.1 An example of the smallest working Lambda function with Node.js

function lambdaFunction(event, context, callback) {    ①  
  callback(null, 'Hello from AWS Lambda')    ②  
}

exports.handler = lambdaFunction    ③  

As mentioned before, the event in your Lambda function is the data passed by the service that triggered your Lambda function. In AWS, functions can be invoked by many things, from common events such as an HTTP request via API Gateway or file manipulation by S3, to more exotic ones such as code deployment, changes in the infrastructure, and even console commands using the AWS SDK.

Here’s a list of the most important events and services that can trigger an AWS Lambda function and how they would translate to your Pizza API:

  • HTTP requests via API Gateway—A website pizza request is sent.
  • Image uploading, deleting, and file manipulation via S3—A new pizza image is uploaded.
  • Changes in the database via DynamoDB—A new pizza order is received.
  • Various notifications via the Simple Notification Service (AWS SNS)—A pizza is delivered.
  • Voice commands via Amazon Alexa—A customer orders a pizza from home using voice commands.

For the full list of triggers, see http://docs.aws.amazon.com/lambda/latest/dg/invoking-lambda-function.html.

Lambda functions come with some limitations, such as limited execution time and memory. For example, by default, your Lambda function’s execution time is up to three seconds, which means that it will time out if your code tries to process something longer. It also has 128 MB of RAM, which means that it is not suitable for complex computations.

Another important characteristic of Lambda functions is that they are stateless, and therefore state is lost between subsequent invocations.

As you can see in figure 1.4, the flow of a Lambda function goes like this:

  • A certain event happens, and the service that handles the event triggers the Lambda function.
  • The function, such as the one shown in listing 1.1, starts its execution.
  • The function execution ends, either with a success or error message, or by timing out.
01-04-9781917294723.eps

Figure 1.4 The flow of an AWS Lambda function

Another important thing that can affect your serverless Pizza API is function latency. Because the Lambda function containers are managed by the provider, not the application operators, there’s no way to know if a trigger will be served by an existing container or if the platform will instantiate a new one. If a container needs to be created and initialized before the function executes, it requires a bit more time and is called a cold start, as shown in figure 1.5. The time it takes to start a new container depends on the size of the application and the platform used to run it. Empirically and at the time of writing of this book, there are noticeably lower latencies with Node.js and Python than with Java.

01-05-9781917294723.eps

Figure 1.5 Cold start versus hot start for an AWS Lambda function

Lambda functions are quite easy to understand and use. The most complex part is the deployment process.

There are a few ways to deploy your serverless application to AWS Lambda. You can deploy through the visual UI on the AWS Lambda console or the terminal via the AWS command-line interface using the AWS API, either directly or via the AWS SDK for one of the supported languages. Deploying a serverless application is simpler than deploying a traditional one, but it can be made even easier.

1.6 What is Claudia, and how does it fit?

Claudia is a Node.js library that eases the deployment of Node.js projects to AWS Lambda and API Gateway. It automates all the error-prone deployment and configuration tasks, and sets everything up the way JavaScript developers expect out of the box.

Claudia is built on top of the AWS SDK to make development easier. It is not a replacement for the AWS SDK or AWS CLI, but an extension that makes some common tasks, such as deployment and setting triggers, easy and fast.

Some of the core values of Claudia are

  • Creating and updating the function with a single command (removing the need to manually zip your application and then upload the zip file via the AWS Dashboard UI)
  • Not using boilerplate, which allows you to focus on your work and keep your preferred project setup
  • Managing multiple versions easily
  • Getting started in minutes with a very flat learning curve

Claudia acts as a command-line tool, and it allows you to create and update your functions from the terminal. But the Claudia ecosystem comes with two other useful Node.js libraries: Claudia API Builder allows you to create the API on API Gateway, and Claudia Bot Builder allows you to create chatbots for many messaging platforms.

As opposed to Claudia, which is a client-side tool never deployed to AWS, API Builder and Bot Builder are always deployed to AWS Lambda (see figure 1.6).

01-06-9781917294723.eps

Figure 1.6 A visual representation of the relationships of Claudia, API Builder, and Bot Builder with the AWS platform

You can work with AWS Lambda and API Gateway without Claudia, either by using the AWS ecosystem directly or by using some of the alternatives.

The best-known alternatives are the following:

  • Serverless Application Model (SAM), created by AWS, which allows you to create and deploy serverless applications via AWS CloudFormation. For more information, visit https://github.com/awslabs/serverless-application-model.
  • Serverless Framework, which has a similar approach to SAM but also supports other platforms, such as Microsoft Azure. To learn more about it, visit https://serverless.com.
  • Apex, another command-line tool that helps you deploy serverless applications but has support for more programming languages, such as Go. To learn more about it, visit http://apex.run.

You are probably wondering why we chose to use Claudia. The Claudia FAQs provide the best explanation:

  • Claudia is a deployment utility, not a framework. It does not abstract away AWS services, but instead makes them easier to get started with. As opposed to Serverless and Seneca, Claudia is not trying to change the way you structure or run projects. The optional API Builder, which simplifies web routing, is the only additional runtime dependency, and it’s structured to be minimal and standalone. Microservice frameworks have many nice plugins and extensions that can help kick-start standard tasks, but Claudia intentionally focuses only on deployment. One of our key design goals is not to introduce too much magic, and let people structure the code the way they want to.
  • Claudia is focused on Node.js. As opposed to Apex and similar deployers, Claudia has a much narrower scope. It works only for Node.js, but does so really well. Generic frameworks support more runtimes, but leave the developers to deal with language-specific issues. Because Claudia focuses on Node.js, it automatically installs templates to convert parameters and results into objects that JavaScript can consume easily, and makes things work the way JavaScript developers expect out of the box.

For more details, see https://github.com/claudiajs/claudia/blob/master/FAQ.md.

The idea of this book is to teach you how to think in a serverless way and how to easily develop and deploy quality serverless applications. Using the AWS ecosystem directly would involve a lot of distractions, such as learning how to interact with and configure different parts of the AWS platform. Rather than try to replace the AWS SDK, Claudia is built on top of it, and Claudia automates most common workflows with single commands.

Claudia favors code over configuration and as a result has almost no configuration at all. That makes it easier to learn, understand, and test. Writing a high-quality application requires proper testing; having lots of configuration doesn’t mean you don’t need to test it.

Claudia has a minimal set of commands that allow you to build serverless applications with a pleasant developer experience. Two of the main ideas behind Claudia are to minimize the magic and to be transparent in showing what happened when a command was invoked.

Despite its small API, Claudia enables you to develop many things: you can build serverless applications from scratch, migrate your current Express.js applications to serverless, and even build your own serverless chatbots and voice assistants.

1.7 When and where you should use it

Serverless architecture is not a silver bullet. It doesn’t solve all problems, and it might not solve yours.

For example, if you are building an application that relies heavily on web sockets, serverless is not for you. AWS Lambda can work for up to 15 minutes, and it can’t stay awake to listen for web socket messages after that.

If latency is critical for your application, even though waking containers is fast, there is always a price to pay for waking up them up. That price is a few dozen milliseconds, but for some applications, that can be too much.

The absence of configuration is one of the main selling points for serverless, but that advantage can be a huge setback for some application types. If you are building an application requiring a system-level configuration, you should consider the traditional approach instead. You can customize AWS Lambda to some extent; you can provide a static binary and use Node.js to invoke it, but that can be overkill in many cases.

Another important disadvantage is so-called vendor lock-in. Functions themselves are not a big problem because they are just standard Node.js functions, but if your full application is built as a serverless application, some services are not easy to migrate. However, this problem is a common one that is not related only to serverless, and it can be minimized with good application architecture.

That said, serverless has many more upsides than downsides, and the rest of this book shows you some of the good use cases.

Summary

  • Serverless is abstracting servers away from software development.
  • A serverless application differs from a traditional one in that serverless applications are event-driven, distributed, and autoscalable.
  • There are a few choices for serverless infrastructure, and the most advanced one is Amazon’s AWS Lambda.
  • AWS Lambda is an event-driven, serverless computing platform that allows you to run functions written in Node.js, Python, C#, or Java and other JVM languages.
  • AWS Lambda has certain limitations, such as execution time, which can be up to 15 minutes, and available memory, which can be up to 3 GB.
  • The most complex parts of a serverless application in AWS are deployment and function configuration.
  • Some tools and frameworks can help you deploy and configure your application more easily. The easiest one to use is Claudia, with its API Builder and Bot Builder.
  • Claudia is a command-line tool that offers a minimal set of commands to allow you to build serverless applications with a pleasant developer experience.
  • Serverless architecture is not a silver bullet, and there are some situations in which it isn’t the best choice, such as for real-time applications with web sockets.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset