Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Serverless Computing With Spring Cloud and Asynchronous Microservices

DZone's Guide to

Serverless Computing With Spring Cloud and Asynchronous Microservices

Forget AWS Lambda, make your own serverless platform using Spring Cloud, RabbitMQ, MySQL, and other tools to work with asynchronous microservices.

· Cloud Zone
Free Resource

Production-proven Mesosphere DC/OS is now even better with GPU scheduling, pods, troubleshooting, enhanced security, and over 100+ integrated services deployed in one-click.

In this article, my endeavor is to walk you through an example of running asynchronous microservices using Spring Cloud without dedicated servers (serverless) for each task (read microservices).

The complete code is available on my GitHub repository. Let me begin by clarifying a few terms, then build on those terms to present the example.

What Is Serverless Computing?

Serverless does not mean that your services would run without a server. You definitely need a compute layer for your services to run. Serverless simply means that you can run your code without provisioning or managing servers. AWS Lambda is one such example of a serverless compute service. AWS Lambda will execute your code only when needed, scale automatically, and you do not dedicate compute power when your code is not running, which means less cost.

Serverless Framework (Key Pieces)

There are, broadly, three pieces to any serverless program:

Image title

  • Event/Trigger: An event could be a file upload, a database update, an HTTP request, or anything else that you can think of upon which you would want your function/service to act. For example, you could want to create multiple formats of a video file once the user uploads the file in a directory
  • Task/Function: After the event has happened, some work needs to happen. The task is where your write the program logic to do that work.
  • Task Launch Platform: The backbone. Once the event is generated, the platform captures the event and launches a task associated with that event. AWS Lambda is an example of one such platform, which manages such plumbing for you.  Similarly, Spring Cloud has also come up with structures in their classic Spring annotation formats to run such programs.

In the example below, I will walk you through how to build serverless, asynchronous tasks using Spring Cloud.

The Example

In our example, a user POSTs a web request to run either a blue task or red task. These basic tasks print out arguments, which the user sends out as part of POST request body.

The example is drawn in the figure below. The picture also maps various components to the serverless framework that I described above.

Image title

Let us look at individual pieces and associated Spring Cloud plumbing code.

1. Event Trigger via HTTP POST Request

The user sends an HTTP POST request with some dummy text in the request body. We could have used any other event trigger as well, such as a file upload, database update etc. I chose an HTTP trigger for ease of demonstration. The URL looks like this: http://localhost:8080/tasks/{color}.  The color path variable could be either “red” or “blue” to signify whether to run redtask or bluetask. 

2. RestController

The user request is trapped by a standard Spring RestController. We annotate our class with the standard @RestController to enable the behavior:

// Rest Controller intercepts the user POST request

@RestController
public class TaskTriggerController {

    @Autowired
    private TaskProcessor t;

    @RequestMapping(path = "/tasks/{color}", method = RequestMethod.POST)
    public @ResponseBody String launchTask(@RequestBody String s, @PathVariable String color) {

            // delegates responsibility of putting task request on queue to TaskProcessor bean
            t.publishRequest(s, color);

        } // method ends

} // class ends


3. Task Processor

This bean has the sole purpose of putting task launch requests into the queue. We use a standard @Component annotation on top of the class. In order to bind the class to the queue, I have used the @EnableBinding annotation. Along with this, you would also need to specify the RabbitMQ properties. The queue name is where the messages get published:

@Component
@EnableBinding(Source.class)
public class TaskProcessor {

    @Autowired
    private Source source;
    ......

}

Image title

4. Task Launch Request

Tasks are stored in a Maven repository. Furthermore, the Task Launch requires the Maven URL as an input. The maven URL format reads as maven://[groupid]:[artifactid]:jar:[version]. Groupid, artifactid, and version in the URL are the values that we specify in the pom.xml of our Task.

The other argument to the Task Launch request is the input that we want to give to the task. The code below is abbreviated:

public class TaskProcessor {

    ....

    public void publishRequest(String payload, String color) {

            String redUrl = "maven://gauravg.springclouddemo:springcloud-red-task:jar:0.0.1-SNAPSHOT";

            TaskLaunchRequest request = new TaskLaunchRequest(redUrl, input, null, null);
            GenericMessage < TaskLaunchRequest > message = new GenericMessage < > (request);

            // this call places the message on queue
            this.source.output().send(message);

            ....

        } // method ends

} // class ends


5. Task Launcher

Task Launcher consumes the messages published on the queue. The launcher then uses the Maven repository and Maven URL available in the message to launch the request. The @EnableTaskLauncher annotation makes a Boot app our Task Launcher. In addition, we have to specify RabbitMQ properties in the application.properties file similar to what I described above.

@SpringBootApplication
@EnableTaskLauncher
public class TaskLauncherApplication {

    public static void main(String[] args) {
        SpringApplication.run(TaskLauncherApplication.class, args);
    }
}


6. Spring Cloud Task

A Spring Cloud Task is a short-lived, asynchronous microservice where the real action happens. In our example, these are the blue/red tasks. These tasks are Spring Boot apps. Being a Spring Boot app, it also has access to various beans in the Spring container, and it could also subscribe to various lifecycle events.

Spring provides the @EnableTask annotation for classifying Boot apps as a Cloud Task. The business logic would be written in Runner, and you could use multiple runners. The task would complete once all runners are completed.

After we are done with task logic, just run maven –install to put the task in the repository.

@SpringBootApplication
@EnableTask
public class RedTaskApplication {

    public class RedTask implements CommandLineRunner {
        .....
        @Override
        public void run(String...strings) throws Exception {

                // Task logic goes here

            } // method ends

    } // class ends

} // boot class ends


7. Execution History

Each task execution generates task execution history.  This history is saved in a database, which is configured in application.properties for the task.  Multiple tables are generated by Spring Cloud Task. The key tables to look at are task_execution and task_execution_params. These tables carry the task status and params submitted for task execution. 

spring.datasource.url=jdbc:mysql://localhost/tasklogs
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver


This concludes the walkthrough of the example.

In a typical setup, both red and blue tasks would have been deployed as services in dedicated containers. However, Spring Cloud enables us to run these tasks without dedicated servers. Services such as AWS Lambda hide the nuts and bolts of such a platform. Hopefully, this example has given you insights on serverless mechanics and how to build such a platform using Spring Cloud.

Happy Coding!

Simply build, test, and deploy. Mesosphere DC/OS is the best way to run containers and big data anywhere offering production-proven flexibility and reliability.

Topics:
serverless development ,spring cloud ,microservices ,cloud ,tutorial

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}