My favourite definition of what microservices are can be found in Building Microservices: Designing Fine grained systems by Sam Newman
Microservices are small, autonomous services that work together.Building Microservices: Designing Fine grained systems - Sam Newman
I love the simplicity of this definition and just how accurately it describes microservices, however I also feel it also hides a lot of the complexities that are involved in implementing Microservices. I have also previously tried to provide a simplified breakdown of What are microservices
The key aspect of microservices that introduces the complexity is the autonomous services , the definition of the word autonomous means to be independent and to operate without being controlled directly. In the world of microservices this means that a microservice will have everything it needs to operate and it will not share any resources with any other services or applications.
What this typically means is that a Microservice will have it's own autonomous instance of a web server, database, cache, memory etc. This is the probably the first area where teams start to go wrong when they embark on their microservices journey. They may be tempted to start developing a service template for all their microservices.
The primary goal, in theory at least, the service template will aim to achieve is to enable any developer in the organisation to quickly spin up a new service that will have everything it needs already set up and configured at the ready and in theory supposed to enable the developer to only focus on what the service needs to achieve.
In fact, at Denizon when we started to implement the Microservices architecture for our Energy Monitoring and management and Mobile Workforce Management application stacks we made this exact same mistake, and found ourselves in the exact same scenarios that Sam Newman describes later in the book.
You do have to be careful that creating the service template doesn't become the job of a central tools or architecture team who dictates how things should be doneBuilding Microservices: Designing Fine grained systems - Sam Newman
Which was also followed up by this exact same scenario
... many teams morale and productivity destroyed by having a mandated framework thrust upon them. In a drive to improve code reuse, more and more work is placed into a centralised framework until it becomes an overwhelming monstrosityBuilding Microservices: Designing Fine grained systems - Sam Newman
The lessons we learned here is that although it always at first sounds like a great idea to build a framework, the reality is that perceived benefits never really seem to materialise. In my opinion this is especially true if you're a smaller organisation, you will undoubtedly lose a fair chunk of your team to just maintaining/enhancing/bug fixing and improving your framework. The downside is, try as you might your organisation will never always have the desired expertise.
We found that there is a huge cost in maintaining a custom framework, which also incurs a substantial opportunity cost, because we had developers who were primarily focused on developing an in-house product, that didn't always have a positive impact on revenue.
This is one of the fine balancing acts, teams have to preform when embarking on their microservices adventures. Fortunately, in the years we have been using microservices things have certainly moved on a whole lot, and more options are appearing by the day. Teams no longer need roll their own service templates because there are a wide range of options available which are well supported.
Our team at threenine.co.uk, were rather excited by the news on 17 February 2021, that the Dapr the Distributed Application Run Time was officially released as a production ready product. This happened to coincide with us about to start a new project for large FTSE 100 company!
What is Dapr
Dapr helps accelerate the development of new cloud-native applications and simplifies the adoption of microservices architecture.
Dapr is an event-driven, portable runtime created by Microsoft as an open source initiative. Due to the fact that Dapr is event-driven it plays an important role in microservices as the applications can be designed to efficiently react to events from external systems or other parts of the solution, and also produce events in order to inform other services of new facts to continue their processing.
Dapr is entirely portable and can be run locally, or self hosted machines or Kubernetes clusters or even deployed to edge computing resources. Although started and run by Microsoft most Cloud based hosting providers support Dapr i.e. Google, AWS, Digital Ocean, Azure etc.
In the containerized, distributed,and networked cloud native world, the sidecar model has emerged as the preferred approach. The Dapr runtime operates in sidecar processes, lifting the complexity from the application to a separate environment which greatly simplifies the development and operations. The sidecar processes are run locally in your development environment or as containers in a pod on Kubernetes.
Dapr is an API that can be directly accessed via HTTP or gRPC calls or even via a number of available SDK's.
It may not always be necessary to adopt the Dapr SDK in your application because a call to Dapr service can be as simple as an HTTP call, however making use of the SDK does provide many benefits if you are developing a Dapr service leveraging the Dapr actor model.
What Dapr isn't
Dapr is not an opinionated framework, or a programming model with strict rules. Dapr helps developers deal with the complexities of Microservices architectures by not mandating specific approaches or utilities to develop applications.
Dapr is not a service mesh, Dapr is designed to be integrated with the service meshes, although Dapr does provide some of the benefits of service meshes at the application level.
Although Dapr is a Microsoft product it is not just restricted to the Microsoft stack or just Microsoft cloud offerings.
Dapr is not just for .net core, it can be used by almost any common software development stack, it is vendor neutral.
Dapr has been designed as a set of pluggable building blocks.
- Dapr Cli - cross platform command line tool to configure, manage and monitor Dapr environments, it also helps to debug Dapr Applications
- Dapr Api - defines how applications can interact with the Dapr runtime
- Dapr host - runs as a standalone process on your development machine, or a side car container in Kubernetes.
- Dapr operator - Manages bindings and configurations in kubernetes.
- Dapr Sidecar injector - Injects your Dapr sidecar into you application pod in Kubernetes
- Dapr Placement service - distributes actor instances across the Dapr pods.
- Dapr Sentry - Built in certificate authority to issue and manage certificates.
Dapr Building Blocks
Dapr provides several building blocks that enable developers to selectively adopt when developing microservices.
- Service invocation: enables service to service invocation while taking care of the retry policy.
- State Management: Dapr provides many state stores which include Redis, Azure CosmosDB, Azure SQL Server, PostgreSQL which can be plugged in via configuration.
- Publish & Subscribe: enables decoupled communication between microservices, exchanging messages.
- Resource Bindings: Trigger code from events raised by external resources with bi-directional communication
- Actors: Encapsulate logic and data in reusable actor objects.
- Observability: Dapr enables developers and operators to observe the behaviour of system services and applications without instrumenting them.
- Secret Management: Securely access external secret stores
Setting Dapr on Ubuntu
Dapr is a runtime for every platform and every language. In this post I will focus on setting up Dapr on Ubuntu and .net core.
To install Dapr simply run the following script, ensuring you have WGET installed in Linux
Once the install has completed, refresh your terminal window
Then we can verify the CLI has been successfully installed by initiating the Dapr command
The we should see the following response
Dapr requires docker locally on your development environment. If you haven't already installed docker on your local machine you may want to do so. Install Docker on Ubuntu, once you have completed installing docker then ensure you login into your docker hub account using
Install Self-Hosted Dapr
Dapr can be initialized in two modes: self-hosted which is essentially a self hosted version for local development and Kubernetes.
The self hosted mode installs Redis, Dapr Placement services and Zipkin. If you have any of these services running locally and using the default ports you may want to stop them at this stage.
To get a self hosted instance of dapr running simply execute
Which should result in the following screen displayed
You can easily check your newly initialised Dapr environment using the
Building a Simple Dapr Application
Lets build the most basic application, we'll use the standard Weatherforecast Web Api project template to get started. This is purely an attempt to get you familiar with Dapr, using nothing but terminal window.
First step is generate the basic project using the dotnet web api template,
all we've done here is generated the project and set the output to be a folder we've called weatherservice. In this post we're not going to touch any further code at all, just illustrate that we can effectively create a dapr project from very little code.
We just need to change into the newly created directory
Now assuming you have already initialised dapr previously using the
dapr init we now effectively use a number of switches available on the
dapr run command to get more information on these switches simply use
dapr run --help
For now we are going to run the following command to get our application to run using dapr
You should be displayed a confirmation that your application is running correctly and everything is working as expected
Thats pretty cool, with a minimal amount of effort have created our first dapr app!
We can verify further details about our app, by inspecting making use of a handy utility that is shipped with Dapr called the Dapr Dashboard. All we need to do is start it. Open another terminal window and execute the following command
You'll be notified that the dashboard is up and running and available on http://localhost:8080
If you open your browser and visit the link , you should see your app listed as one of the Dapr applications
If we click on the link we can drill down further to get more details about the application. We only have some really basic information at the moment, but the more you work with dapr the more useful this dashboard will become
Our application is running is dapr but is it actually working?
We can use the terminal to check our application is responding and we can use the dapr command to do so. We can make use of curl on ubuntu to invoke our sidecar url making use of the native invoke API which is included in dapr.
The command structure is typically as follows
Executing the curl command we'll see the result in the window.
We have successfully built our first microservice using Dapr! We'll dive a little deeper into how services work in Dapr
Admittedly we have only just scraped the tip of the iceberg as to what Dapr can offer when it comes to building microservices. There is still a whole lot more to go through, but we have built on a solid foundation and even with this highly simplistic example we have already used a lot of what the runtime can provide.
A key goal of Dapr is to abstract infrastructural details away from developers . Through Dapr Building Blocks, application code is completely isolated from the underlying infrastructure, allowing the application to be configured and reconfigured on different platforms at operation time without needing to change the application code. This is a powerful feature that enables scenarios such edge and multicloud applications.
In future articles I will help you to explore and understand the inner workings of Dapr and how you can use it build Enterprise scale microservices.