There's an emerging piece of open source tech I'm very excited about. If you haven't heard of Dapr, it's one of the newest additions to the Cloud Native Computing Foundation (CNCF) and promises to provide portable and reliable microservices. While on the surface that may sound great, a lot of you may be wondering "ok but what is it? how does it work?" While analogies and comparisons will never be perfect, I love to use them to help me contextualize. So while the comparison is imperfect, I personally think of Dapr like jQuery for microservices.
Ok hear me out. I realize that sentiment may evoke a range of emotions, but let me explain. This is heavily influenced by my experiences in web development. So let’s head back in time.
I remember over two decades ago building some of my first web pages. These were the days of GeoCities, and later Blogger and MySpace. I remember using text editors to write static HTML files, and spicing it up with the latest and greatest tech including MIDI files, guest books, and page visit counters.
But as we moved into the 2000s, the web shifted. You may hear folks now reference this as Web 2.0, but to me it was discovering a new paradigm of web experiences, led by Gmail, YouTube, and Facebook.
These pages revolutionized what a website could do. A web page could be dynamic, with controls or content that was able to update without clicking a hyperlink or navigating pages. As I was building web pages, I didn’t even know where to start to try to weave in this type of rich functionality. But in the late aughts that all changed when I got introduced to jQuery. To me, jQuery was magic. Someone like me, with only basic web development skills, could now create dynamic sites. Commands like
$("property").hide unlocked these capabilities by pulling in the jQuery script files onto any page and using that beautiful
$ alias and APIs. At the time, I would recommend jQuery to anyone and everyone building websites because it made the complex simple.
While dynamic web pages are no longer a mystery, modern microservices and cloud native is still heavily evolving. Microservices can trace some roots back to SOA, which is anything but "new," but there are still a set of common challenges when building microservices, including:
- How can I make my services resilient to failures?
- How can I have better logging and tracing of my services?
- How do I secure and encrypt my sevices?
- How can I manage state efficiently and uniformly across my services?
There are a variety of ways to solve each of the above. I could write custom retry logic in my code to catch and retry. I could pull in SDKs for observability and logging solutions, or could integrate service meshes to manage inter-service communication. But in the same way dynamic webpages felt advanced and overwhelming for me without jQuery, solving each of these problems on its own can be a daunting task for any team building microservices. This is why for me, Dapr is doing for microservices what jQuery did for dynamic web pages: providing a simplified and developer friendly way to solve a variety of common challenges.
As mentioned at the beginning of the blog, Dapr is a set of APIs for building portable and reliable microservices. I can pull Dapr into my microservices architecture and have out of the box APIs to perform tasks like secure service invocation, publish & subscribe, and secrets management. Let’s take a simple example.
Imagine I have two services: service A and service B. I have deployed both services, and now want to call service B from service A within an orchestrator like Kubernetes. Without much effort I could call service B over HTTP (
http://serviceB/hello). This works, but it’s missing a few useful capabilities. How can I make sure the network traffic between A and B is secured and encrypted? What if service B has a transient issue I want to automatically handle and retry? How can I make sure whenever service A calls service B I can trace that call and “follow the message” from origin to eventual destination? With these considerations, my simple call over HTTP now falls short.
The good news? I can simply swap out the call over HTTP with the Dapr API to “invoke” and get service A to call service B, but Dapr now layers on resiliency, encryption, and tracing.
await daprClient.invoker.invoke('serviceB' , 'hello', HttpMethod.GET);
That’s just one of many examples in how a simple API call to Dapr will layer on best practices and solutions to common microservices challenges.
I’ve used Dapr a bit in the last year and have really come to value it in my toolchain. I personally find the service invocation APIs and observability APIs the most useful. I may use Dapr for state management, but other times I choose to leverage the state SDKs (like Redis or Cosmos DB) directly in my code. But that’s one part I like about how Dapr was built: you can mix and match just the APIs that make sense for your current project and team.
If you haven’t tried Dapr, it’s simple to get started using the Dapr quickstarts. There are options to try out locally or hosted in Kubernetes.
As our team has been building Azure Container Apps, a serverless container offering built on Kubernetes, we wanted to make it as easy as possible for users to leverage these Dapr APIs for containers and microservices. So we’ve baked Dapr into the service as a feature that can be easily enabled for any container. If you want to try creating a hosted Dapr app, check out this tutorial of creating a microservice with Dapr in container apps.
The same way I would recommend any web developer in the 2000s use jQuery, I strongly recommend Dapr for anyone building microservices in 2022 and beyond. Is it possible in 20 years these patterns and practices from Dapr will be built into these underlying microservice platforms the way jQuery APIs were for web? Who knows. But until I’ll be using Dapr in my microservice development.
Jeff Hollan is Director of Product for Azure PaaS and Serverless. @jeffhollan on Twitter.