MICROSERVICE ORCHESTRATION MODEL USING NETFLIX CONDUCTOR ENGINE
Hewlett Packard Enterprises
INTRODUCTION
Microservice architecture, or simply microservices, is a distinctive method of developing software systems that tries to focus on building single-function modules with well-defined interfaces and operations. The trend has grown popular in recent years as Enterprises look to become more Agile and move towards a DevOps and continuous testing.
What are Microservices ?
Microservices solve these challenges of monolithic systems by being as modular as possible. In the simplest form, they help build an application as a suite of small services, each running in its own process and are independently deployable. These services may be written in different programming languages and may use different data storage techniques. While this results in the development of systems that are scalable and flexible, it needs a dynamic makeover. Microservices are often connected via APIs and can leverage many of the same tools and solutions that have grown in the RESTful and web service ecosystem. Testing these APIs can help validate the flow of data and information throughout your microservice deployment.
Orchestration is the traditional way of handling interactions between different services in Service-Oriented Architecture (SOA). With orchestration, there is typically one controller that acts as the “orchestrator” of the overall service interactions. This typically follows a request/response type pattern. Consider the below example we have an orchestrator and few services who need to be executed, now the Orchestrator acts as a broker who assigns “who should execute what and in which order”
What is Microservice Orchestration ?
ORCHESTRATOR
SERVICE A
SERVICE B
SERVICE C
Request
Response
Request
Request
Response
Response
If three services needed to be called in a particular order, the orchestrator makes a call to each one, waiting for a response before calling the next.
ORCHESTRATION
Why do we need Orchestration?
BENEFITS OF ORCHESTRATION
Most people think a microservice architecture is good for building scalable applications. This isn’t false but we should have a closer look at which dimension this architecture style scales at its best. The dimension that comes into people’s mind first is the dimension of load. This means it should be possible to add additional resources to keep the performance the same when workload increases. In fact, this is not for what microservices are good for in the first place. The dimension the microservice architecture scales is the functional dimension. In other words, it is easy to introduce new functions and qualities at any stage of the product. This leads to the consideration that it’s simply possible to react to imminent load problems with new requirements. Here are some of the major benefits of orchestration
Here is what an orchestrator does…
PROJECT - WORK
A MIRCROSERVICE ORCHESTRATOR FOR AN E-COMMERCE SERVICE USING NETFLIX CONDUCTOR
Let’s have a look…
ABSTRACT
Our project focuses on implementation of orchestration model for an e-commerce scenario. There are 4 major microservices as part of the application which are
In this project we worked on creating these microservices for which we will be carrying out the Orchestration of these microservices using the Netflix Conductor tool. We have also developed user interface for each services and presented the services collectively in the form a web application, We shall see the detailed description of the services and the workflows associated with these services respectively in upcoming slides.
CONDUCTOR ARCHITECTURE
Conductor enables orchestration across services while providing control and visibility into their interactions. Having the ability to orchestrate across microservices also helped us in leveraging existing services to build new flows or update existing flows to use Conductor very quickly, effectively providing an easier route to adoption.
WORKER IMPLEMENTATION
At the heart of the engine is a state machine service aka Decider service. As the workflow events occur (e.g., task completion, failure etc.), Decider combines the workflow blueprint with the current state of the workflow, identifies the next state, and schedules appropriate tasks and/or updates the status of the workflow.
Decider works with a distributed queue to manage scheduled tasks. We have been using dyno-queues on top of Dynomite for managing distributed delayed queues. Tasks, implemented by worker applications, communicate via the API layer. Workers achieve this by either implementing a REST endpoint that can be called by the orchestration engine or by implementing a polling loop that periodically checks for pending tasks. Workers are intended to be idempotent stateless functions. The polling model allows us to handle backpressure on the workers and provide auto-scalability based on the queue depth when possible. Conductor provides APIs to inspect the workload size for each worker that can be used to auto scale worker instances.
The APIs are exposed over HTTP — using HTTP allows for ease of integration with different clients. However, adding another protocol (e.g., gRPC) should be possible and relatively straightforward.
We use Dynomite “as a storage engine” along with Elasticsearch for indexing the execution flows. The storage APIs are pluggable and can be adapted for various storage systems including traditional RDBMSs or Apache Cassandra like NoSQL stores.
WORKER IMPLEMENTATION DIAGRAM
PROJECT FLOW
The general flow of the project is given below in the form of a flowchart covering all the important stages in the project execution
PIPELINE
There are various elements that are part of this project, these elements form the very basis for the microservices and the flow of execution that the orchestrator will orchestrate. The important elements in the orchestration module are stated below:
Let us consider the example of a dummy workflow to understand of the Netflix Conductor Orchestrator works.
How it all works ?
Task Definition
We created the task definition for the tasks of each services using JSON in postman. This is necessary for understanding all the possible tasks that we have which need to polled and triggered by the orchestrator. All the task definitions individually had features like timeoutseconds, retrycount, retrylogic etc. Below we can see the task definition for the dummy task
[
{
"name": "Test",
"retryCount": 3,
"retryLogic": "FIXED",
"retryDelaySeconds": 10,
"timeoutSeconds": 300,
"timeoutPolicy": "TIME_OUT_WF",
"responseTimeoutSeconds": 180,
"ownerEmail": ” psri.siddarth2018@vitstudent.ac.in"
}
]
Task name
In case the polling is failed we set the number of times the orchestrator should retry
Retry logic is fixed and the orchestrator will retry the polling after the time out of 300 seconds under the specified time out policy
E-mail of the service owner
Workflow Definition
The workflow for the same is created for understanding the flow of tasks . The workflow was first created for all individual tasks and stitched together for all the microservices combined. Below we can see the workflow definition for the dummy task
Start Task – This task is the start point of the workflow
End Task – This task is the end point of the workflow
Test Task – This is the task that is user-defined whose definition was stated in the previous slide. This task takes only an input from the user.
Conductor is now ready to orchestrate this Workflow. As stated on high level process, a workflow can be started through multiple sources. After Conductor has a task to be completed, the worker picks up the work and completes it.
Worker
Then on a HTTP Request, we are impersonating a Worker, that theoretically speaking is constantly polling tasks to be completed from Conductor. Worker needs to indicate what the type of work its seeking to complete by providing Task definition name. Below we can see the worker code for the demo Task using the python client.
import json
import requests
headers = {'Content-type': 'application/json', 'Accept': 'text/plain’}
Schedule_worker= {
"name": "Demo",
"version": 2,
"correlationId": "Demo_1",
"input": {
"inputno": "987654321"
}
}
url = "http://localhost:8080/api/workflow"
json_object = json.dumps(Schedule_worker)
r = requests.post(url, data=json_object, headers = headers)
Worker – Here we have the worker code that will schedule the “Demo” workflow and pass the input data needed for the task ”Demo_1” so this particular worker will trigger the “Start” task in the “Demo” workflow.
The URL where we need to send the HTTP request (Netflix Conductor Server)
We need to POST the worker to the Conductor Server, hence we use the post function here
The workflow is being scheduled for the worker to Poll and Execute the Tasks
Workflow_id – This is the unique ID that the Conductor server assigns to a workflow when it is scheduled
Poll Tasks
Once we schedule the workflow all the tasks need to be triggered by the workers for all the individual services that are being polled . A Worker polls the “Scheduled Task” so that the worker can execute it. Below we can see the task definition for the dummy task
url = "http://localhost:8080/api/tasks"
headers = {'Content-type': 'application/json', 'Accept': 'text/plain’}
worker_data = {
"workflowInstanceId": "87a4a6c4-d053-448f-a22e-11761766e43f",
"taskId": "e8f48563-0521-4cfb-81c0-12c4fbec8704",
"reasonForIncompletion": "",
"callbackAfterSeconds": 0,
"workerId": "Marcos-Worker-2020",
"status": "COMPLETED",
"inputData": {
"inputno": 123434
}
}
r = requests.post(url, json = worker_data, headers=headers)
We need to POST the worker to the Conductor Server to mark the task as completed when it gets the input
Worker – This code will make the worker to Poll the task that corresponds with the task-id given here and polls the workflow based on the ID given here. We can assign any name for the “WorkerID”. The “inputData” parameter consists all the input needed for that task
The URL where we need to send the HTTP request for executing the workflow (Netflix Conductor Server)
We change the ”STATUS” of the task to completed once we poll for that task.
Execute Workflow
The Worker Polls the Task and the Task’s status is changed to COMPLETED once the worker polled the task. Below we can see the execution of the ”Demo” workflow.
UI Visibility
Once we complete the execution of any workflow, we can see the poll count and the worker that polled that workflow in the Conductor UI, this allows for us to monitor how many workers poll for the workflows and how the Orchestrator handles these poll requests
E-COMMERCE APPLICATION
In this project we have decided to demonstrate the microservice orchestration for a real-time application. We have implemented an e-commerce web application with a minimalist user interface which includes the following fundamental services as part of the application
Application Flow
AUTHENTICATION SERVICE
PRODUCT CATALOGUE SERVICE
DISCOUNT SERVICE
PAYMENT SERVICE
SYSTEM ARCHITECTURE
E-COMMERCE SHOPPING SERVICE
Authentication Service
Product Catalogue Service
Product Discount Service
Payment Service
POSTGRE DB
POSTGRE DB
POSTGRE DB
POSTGRE DB
MICROSERVICES
Authentication microservice
This task will get the input called “usertype” which then triggers the decision task below to check the user’s type
This is a Decision Task(System Task) that takes the output from the ”Check_User” task and applies the check condition that is to classify the user as an ”existing” or ”new” category.
If the user is new this task is scheduled and the worker polls for this task that takes the new username and password as inputs
If the user is an existing user, this task is scheduled and the worker polls for this task that takes the username and password of the user as inputs
MICROSERVICES
Product Catalogue microservice
If the user is finishing the purchase, then the product that the user decided to buy is checked by the task and it adds the user’s product to their cart
This is a decision task that checks if the user has completed their shopping
This task in invoked when the user has “logged-in” and shops for products in the e-commerce application. This task requires the product ID of the product that the user shops.
If the user decides to not shop that product, then the item is dispensed that is the product is discarded and not added to the user’s cart.
MICROSERVICES
Discount microservice
This is a decision task that checks if the product that the user has purchased and added to cart has any discount associated with it.
This task takes the order ID of the user purchased to check if there are any products with discounts.
This task will assign the discount associated with the product and return the discount percentage so that it can be applied before the payment.
MICROSERVICES
Payment microservice
This task will process the payment and return the message ”payment success” once the previous tasks have verified the payment inputs.
This task will not process the payment and return the message ”payment unsuccessful” once the previous tasks have verified the payment inputs.
This task will take the output of the previous task that consists all the card details and verifies these details in order to process the payment.
This task takes the user’s details like name, address, etc. to process the bill in the web application.
This is a decision task that will decide if the payment is valid and should the user’s transaction be successful or not.
TECH STACK
Here are the various frameworks, languages and tools used to develop the project
CONCLUSION
The project’s objective was to learn, study and implement orchestration model using conductor as the back-end component for the project which has been successfully achieved. The use of orchestration is to call services independent of each other so that the bigger projects can be broken down into smaller services called microservices which makes the process of making changes in the project very easy and less time consuming. The individual tasks and services fulfil their own objectives and then they are stitched together to work as a complete model using the concept of orchestration.
---------THANK YOU----------