Press "Enter" to skip to content

Orchestration and choreography in .NET microservices

As more companies adopt microservices architectures for their applications, more developers have had to grapple with the concepts of orchestration and choreography. Although these terms are sometimes used interchangeably, there are key differences between these two architectural patterns.

Orchestration is a centralized approach to make all control decisions about the interactions between services. Here, a central orchestrator service coordinates all the other services that execute a business transaction or workflow. In contrast, a choreography is a decentralized approach to coordinating this workflow, where each service determines its own behavior based on messages it receives from other services.

This article will cover the basics of orchestration and choreography in microservices architectures, and discuss how you can use each (or both) in your microservices-based applications. We will also simulate the orchestration and choreography of microservices in the code examples provided below.

What is microservices architecture?

Microservices refer to a style of software architecture in which a large application can be built as a conglomeration of small, self-contained services. Each microservice has a specific purpose and can be implemented independently.

A microservices architecture makes it easy to scale individual services as needed. It also allows for greater speed and flexibility when making application changes because only the affected service needs to be redeployed.

Two main approaches to managing communication between microservices are orchestration and choreography. Let’s understand the differences.

What is microservice orchestration?

Microservice orchestration refers to a centralized approach, where a central component, known as an orchestrator, is responsible for managing and coordinating the interactions between microservices. Kubernetes and Docker Swarm are examples of orchestration tools.

Orchestration helps ensure consistency and reliability in interactions between microservices by defining the sequence of steps that must be followed. It also helps manage failures and errors by providing a centralized point of control and ensuring that each microservice communicates only with the orchestrator.

Orchestration is useful in scenarios where a centralized authority is needed to control interactions between microservices, and when coordination and management of complex processes involving multiple microservices is needed.

Examples of orchestration include using an API gateway to manage and secure communications between microservices, or using a message broker to coordinate the flow of messages between microservices.

Microservice orchestration example in C#

Workflow Core is a lightweight workflow engine for .NET Core applications. We can use it to implement orchestration. Below is an example of a basic microservice orchestration application in C# using the Workflow Core library.

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using WorkflowCore.Interface;
using WorkflowCore.Models;
namespace MicroservicesOrchestrationExample
{
    class Program
    {
        public static void Main(string[] args)
        {
            IServiceProvider serviceProvider = ConfigureServices();
            var host = serviceProvider.GetService<IWorkflowHost>();
            host.RegisterWorkflow<SampleWorkflow>();       
            host.Start();           
            host.StartWorkflow("Sample");           
            Console.ReadLine();
            host.Stop();
        }
        private static IServiceProvider ConfigureServices()
        {
            IServiceCollection services = new ServiceCollection();
            services.AddLogging();
            services.AddWorkflow();
            services.AddTransient<LastStep>();
            var serviceProvider = services.BuildServiceProvider();
            return serviceProvider;
        }
    }
    public class SampleWorkflow : IWorkflow
    {
        public void Build(IWorkflowBuilder<object> builder)
        {
            builder
                .StartWith<FirstStep>()
                .Then<LastStep>();
        }
        public string Id => "Sample";
        public int Version => 1;
    }
    public class FirstStep : StepBody
    {
        public override ExecutionResult Run(IStepExecutionContext context)
        {
            Console.WriteLine("Microservice A");
            return ExecutionResult.Next();
        }
    }
    public class LastStep : StepBody
    {
        public override ExecutionResult Run(IStepExecutionContext context)
        {
            Console.WriteLine("Microservice B");
            return ExecutionResult.Next();
        }
    }
}

In this example, we have defined a workflow called SampleWorkflow that consists of two steps, FirstStep and LastStep. The Workflow Core library takes care of executing these steps in the correct order. The main method starts the workflow host and waits for the user to press any key to end the program.

What is microservices choreography?

Choreography refers to the decentralized approach to coordinating interactions between microservices, where each service communicates directly with other services, without relying on a central coordinator. This pattern puts the burden of coordinating the interactions on the microservices themselves.

In choreography, each microservice is responsible for maintaining its own state and exchanging messages or events with other microservices to coordinate the workflow. This approach has the advantage of removing the tight link between an orchestrator and the microservices that run the workflow. The drawback is that it increases peer-to-peer communication between microservices.

Choreography helps achieve greater scalability and flexibility in the microservice architecture, as each microservice can evolve and change independently, without affecting the overall system. And because choreography removes reliance on a central orchestrator, it can increase the reliability and resiliency of the entire system.

Examples of choreography include e-commerce websites that make use of different services to provide product information, payment processing, and delivery tracking, but do not use a centralized service to control and coordinate these functions.

Also Read:  Bringing observability to cloud security

Microservices Choreography Example in C#

There are different ways to implement the choreography of microservices. One approach is to use a centralized message broker, such as RabbitMQ or ActiveMQ, to which all services can connect. The message broker acts as a mediator between the services, routing messages as needed.

Another approach is to use a pub/sub model, where each service publishes its events on a central topic and any interested party can subscribe to that topic. This allows for loose coupling between the services, since they do not need to know each other beforehand. But as with the message broker approach, there is still a kind of core dependency.

Below is an example of a basic microservice choreography application in C# using the MassTransit library.

using MassTransit;
namespace HelloWorldChoreography
{
    class Program
    {
        static void Main(string[] args)
        {
            var busControl = Bus.Factory.CreateUsingInMemory(configure =>
            {
                configure.ReceiveEndpoint("sample-queue", endpoint =>
                {
                    endpoint.Consumer<SampleConsumer>();
                });
            });
            busControl.Start();
            Console.WriteLine("Press any key to exit");
            Console.ReadLine();
            busControl.Stop();
        }
    }
    public class SampleConsumer : IConsumer<SampleMessage>
    {
        public Task Consume(ConsumeContext<SampleMessage> context)
        {
            Console.WriteLine("Message received...");
            return Task.FromResult(0);
        }
    }
    public class SampleMessage { }
}

In this example, the consumer class, SampleConsumer, listens to the sample queue and handles incoming messages of type SampleMessage. When a message is received, the consumer will display the text “Message received…” in the console window. When the program starts, the main method activates the MassTransit bus and waits for the user to press any key to end the program.

Orchestration vs Choreography

Orchestration, as the name suggests, is about having centralized control over the various services in a microservices architecture. This can be seen as an advantage, as it gives you more control over how the various services interact with each other. However, this also means that any changes to the overall system will require changes to the orchestrator itself, which can be complex and time consuming.

Choreography, on the other hand, takes a more decentralized approach. Each service is responsible for its own interactions with other services, which means there is no need for a central orchestrator. This can make development and deployment simpler and faster, since there are no dependencies on a central system. However, the choreography can also make debugging and troubleshooting more difficult, as it can be more difficult to understand how the various services interact.

Which should you use?

Orchestration and choreography are key elements of a successful microservices architecture that can significantly improve performance, scalability, and reliability. Through orchestration, microservices can communicate with each other more efficiently, allowing them to scale quickly and easily to accommodate larger workloads.

Orchestration defines a precise sequence of steps that each microservice must follow, which is beneficial for identifying and addressing complex service interdependencies. Additionally, orchestration makes it possible to manage and monitor business logic in one place.

Choreography, on the other hand, is the practice of orchestrating microservices together without a central coordination point. This allows each service to function independently while still being part of the larger architecture.

Orchestration can be used to manage both simple and complex deployments. You can automate the provisioning of resources, the scaling of services, and the application of updates and patches. Orchestration can also provide insight into the performance of individual services and identify issues that need to be addressed.

Choreography is a good option if your app requires frequent updates or new releases. It can be used to define how services interact with each other, but it cannot automate the management of those interactions. Choreography is best suited for managing smaller deployments or for testing purposes.

A hybrid approach

The choice between orchestration and choreography depends on the particular needs and requirements of the architecture. In general, orchestration is used when there is a need for a centralized authority to control the interactions between microservices, while choreography is used when there is a need for more decentralized and autonomous interaction between services.

Alternatively, one could choose a hybrid approach that integrates orchestration and choreography. A hybrid approach could protect your application from orchestrator failures. But again, this choice would depend on your application requirements and your organization’s goals.

Orchestration and choreography play a vital role in managing complex systems, enabling faster development cycles, greater scalability, and less complexity. By implementing one or both approaches with care and consideration, you can create a robust microservices architecture that is scalable, secure, and easily adaptable to changing requirements.

Copyright © 2023 IDG Communications, Inc.

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *