Getting Started with Serverless

If you are reading this book, you have probably already heard the term serverless on more than one occasion. You might have read more than one definition of the term, like every buzzword. I define serverless computing as a new and efficient software development approach that abstracts infrastructure from the functionality itself, letting the developers focus on their business instead of the infrastructure constraints.

I remember myself and my team struggling with these infrastructure constraints in one of the web shops in the late 2000s. After being born as a pet project in college years, Instela had suddenly grown from having hundreds of visits per day to thousands, and we were hosting it on a shared hosting provider. Our website was eating all the CPU available in those poor Xeon servers and our hosting provider unilaterally decided to shut it down to keep neighboring websites up on the same server with us. The local plumber and the coffee shop were online and we were homeless in the cyber world. We did not have any remedy other than running to buy a cheap desktop computer, make it our first server, and bring Instela up again. Our visitor count was increasing day by day, our ATX server was resetting itself a couple of times per day because of overheating, and we ended up buying our first DELL PowerEdge box, which was like a space station for us back in 2005. Everything was cool in the beginning, but as more visitors started to come, our site started to respond slower and slower. Sometimes it was rather fast, and sometimes it was as slow as molasses. Sometimes, there was viral content that attracts thousands of people, and sometimes we had 100 people online. For our data center, it was exactly the same. They were charging us a fixed price and enjoying it. When we needed a new server, we had to spend at least one week, ask whether the local dealer had it in their stock, wait for the delivery, and install the network and the operating system. And what if one of the machines had a hardware issue? We had to wait for the technician and deal with the traffic with one less machine. It was a real pain and there was no other way to run a web platform.

Virtual servers have already existed since the early 2000s, but one can say that real cloud computing started in 2006 with the launch of AWS EC2. It is worth noting that when this service was launched, it was offering very limited options, and for many companies, it was not a production-ready solution.

Nowadays, this horror story is just a legacy to remember for many companies. Public clouds are providing us with a dedicated compute power from their large machine pools. Cloud computing introduced many new concepts and drastically changed how we build and deploy software. We do not have to worry about maintaining an on-premise SAN we mount via NFS. There are S3, Azure Blog Storage, or Google Cloud Storage, which give us the space we really need. We do not monitor the free space or repair it when it is broken. Within the SLA levels, (99.999999999% for AWS S3 [1]) you always know that your storage engine is just there, working. You need a queue service such as RabbitMQ but have AWS Simple Queue Service or Windows Azure Queue Service? You need to implement a search functionality and are planning to deploy an Elasticsearch cluster? You have a managed one: CloudSearch. AWS is offering a managed service even if you are developing a platform that needs to transcode video. You upload your jobs and get the results.

So far, we have spoken about the supporting services that any size of application might need. Leveraging the managed service offerings from public cloud providers, we see that we have become able to shut down some of the servers we previously needed in an on-premise infrastructure. We might say that this is the first part of the serverless architecture. Some authors are calling this type of service Backend as a Service, or BaaS. However, so far, our software is still running on virtual machines, called instances on AWS and Google Cloud Platform or VMs on Windows Azure. We have to prepare virtual machine images with our application code, spin up instances using them, and configure the auto-scaling rules for cost optimization and scalability. More importantly, we have to pay for these servers on a timely basis, even if you really do not use the reserved compute capacity.

As an alternative to this paradigm, cloud providers came up with the Functions as a Service (FaaS) idea. With FaaS, the vast amount of the business logic is still written by the application developer, but they are deployed to fully managed, ephemeral containers that are live only during the invocation of the functions. These functions respond to specific events. For example, the application developer can author a function that gets binary image data as the input and returns its compressed version. This function can be deployed as an independent 'unit of work and invoked with an image data to get the compressed version. This function would run in an isolated container managed by the cloud provider itself, and the application developer would only be busy with the parameter the cloud provider gets and the return data they give away. Obviously, this function alone does not make much sense, but cloud providers are also providing a mechanism to make these small functions respond to specific cloud events. For instance, you can configure this function to be invoked automatically whenever a new file is added to an S3 Bucket. In this way, this function will always be notified when there is a new image uploaded by your users and save a compressed version of it to another bucket. You can deploy another function that returns plain JSON objects that configure it to respond to HTTP requests via API Gateway. You would now have a fully scalable web service that you pay for as you go.

Sounds good? Then we warmly welcome you to the serverless computing world!

For a good theoretical study on serverless computing, I recommend that you read Mike Robert's Serverless Architectures. He paints a big picture of the topic and carefully analyzes the advantage and drawbacks of a serverless approach. You can find information about this article in the bibliography section.

In this book, we will learn how to build a midsize serverless application with AWS Lambda and the Java language. Although Google Cloud Platform and Windows Azure offer similar functionalities, I picked AWS Lambda because, at the time of writing, AWS is the provider that offers the most mature solutions. I picked Java because, despite its power and popularity, I believe that Java has been always underestimated in the serverless computing community. In my opinion, this is because AWS started with offering JavaScript, thus the trend started with that language and went on with it. However, AWS Lambda has native support for Java, which offers a fully functional JVM 8 to developers. In this book, we will look at how to apply the most common techniques in the Java world, such as Dependency Injection, and try to apply OOP design patterns to our functions. Unlike JavaScript equivalents, our functions will be more sophisticated and we will create great build systems thanks to Gradle. Gradle is Maven like build tool which uses Groovy based language that you can build sophisticated build configurations.

In this journey, we will begin with the following:

CloudFormation is an automated AWS tool for the provisioning of cloud resources. With CloudFormation, you can define your whole cloud platform using a single JSON file without having to deal with CLI or AWS Console and deploy your application with one command in any AWS account. It is a very strong tool and I advise against usage of any other method to build AWS-based applications. With CloudFormation, you can have a solid definition of your application that works everywhere in the same way. Besides the benefits of such solidity in the production environment, CloudFormation also lets us define our infrastructure as code, so we can leverage source control and observe the development of our infrastructure along with our code. Therefore, in this book, you will not find any CLI command or AWS Console screenshot, but will find CloudFormation template files.

You may think that there are many unknown words in this list, especially if you are not familiar with the AWS ecosystem. No worries! We expect you to be familiar only with the Java language and common patterns such as Dependency Injection. Knowledge of Gradle is a plus but not mandatory. We do not expect you to know about the services that AWS offers. We will be covering most details and referring to relevant documentation whenever needed, and after completing this book, you will know what these abbreviations mean. However, you are free to go to the AWS documentation and learn what those services are offering.

The forum application we will be implementing will be a very basic but over-engineered application. It will include the REST API that users can register, create topics and posts under existing topics, update their profiles, and do some other operations. The application will have some supporting services, such as sending mobile notifications to users when someone replies to their posts, an image resizer, and so on. As it is very typical web application and we are assuming that the audience of the book is already familiar with the business requirements of such an application, we are omitting the definition of all the systems at this stage. Instead, we will adopt an iterative agile methodology and define the specifications of these subsystems when we need them in the upcoming chapters.

In this chapter, we will cover the following topics:

As stated earlier, AWS Lambda is the core AWS offering we will be busy with throughout this book. While other services offer us important functionalities such as data storage, message queues, search, and so on, AWS Lambda is the glue that combines all this with our business logic.

In the simplest words, AWS Lambda is a computing service where we can upload our code, create independent functions, and tie them to specific events in the cloud infrastructure. AWS manages all the infrastructure where our functions run and performs all of the administration of the compute resources, including server and operating system maintenance, capacity provisioning and automatic scaling, code monitoring, and logging. When our function has high demand, AWS automatically increases the underlying machine count to ensure that our function performs with the same performance. AWS Lambda supports JavaScript (Node.js), Java, and Python languages natively.

You can write AWS Lambda functions in one of the languages supported natively. Regardless of the chosen language, there is a common pattern that includes the following core concepts:

AWS Lambda functions can be invoked manually or by responding to different events. They are normal functions: you give them an event object and you get the results. During the execution, Lambda functions are totally agnostic about who is calling them. However, invoking them manually does not make much sense. Instead, we configure them to respond to Cloud events. Invoking Lambda functions manually is useful when we test our functions for different type of inputs and we will actually do that when we test our functions manually. However, the real power of Lambda functions appears when their invocation is out of our control. In this book, we will configure AWS functions to respond to different cloud events. Here are examples of some of them:

In the following chapters, you will understand much better how Lambda functions work with practical examples.

After this introduction, it is time to get our hands dirty and write some code.