Welcome to this second edition of Practical Microservices with Dapr and .NET! Distributed Application Runtime (Dapr) evolved greatly after the version one release and the innovations in .NET 6 prompted a refreshed and enriched edition of the book.
This chapter will introduce you to the Dapr project to teach you the core concepts of its architecture and prepare you to develop with Dapr.
Dapr accelerates the development of new cloud-native applications and simplifies the adoption of a microservice architecture.
In this chapter, we are going to cover the following main topics:
Learning about these topics is important to establish a solid foundation for our future endeavors with Dapr and microservice architectures. These basic concepts will guide our learning throughout the rest of this book.
Our first steps into the project will start with exploring Dapr and understanding how it works.
The code for this sample can be found on GitHub at https://github.com/PacktPublishing/Practical-Microservices-with-Dapr-and-.NET-Second-Edition/tree/main/chapter01.
In this chapter, the working area for scripts and code is expected to be <repository path>chapter01. In our local environment, it is C:Repospractical-daprchapter01.
Please refer to the Setting up Dapr section for a complete guide to the tools needed to develop with Dapr and work with the samples.
Dapr is an event-driven, portable runtime created by Microsoft with an open source approach and it is a Cloud Native Computing Foundation (CNCF) incubated project.
Being event-driven (which is emphasized in the definition of Dapr) plays an important role in microservices; this is because an application can be designed to efficiently react to events from external systems or other parts of the solution and to produce events as well in order to inform other services of new facts or to continue processing elsewhere, or at a later stage.
Dapr is portable as it can run locally on your development machine in self-hosted mode; it can also be deployed to the edge, or it can run on Kubernetes.
The following diagram shows the many building blocks provided by Dapr:
Figure 1.1 – Dapr architecture
Portability does also extend beyond the hosting environment—while Dapr is an initiative that was started by Microsoft, it can also run on Kubernetes on-premises or in the cloud with Microsoft Azure, Amazon Web Services (AWS), Google Cloud Platform (GCP), or any other cloud vendor.
Dapr has been built on the experience gained by Microsoft in developing hyperscale cloud-native applications. It has been inspired by the design of Orleans and Service Fabric, which in turn enables many Microsoft Azure cloud services to operate resiliently and at a large scale.
A brief history of Dapr
Dapr was first released in October 2019, and you can find more information at https://cloudblogs.microsoft.com/opensource/2019/10/16/announcing-dapr-open-source-project-build-microservice-applications/.
Dapr adopted an open governance model early on in the initial development phase in September 2020; see the description at https://blog.dapr.io/posts/2020/09/30/transitioning-the-dapr-project-to-open-governance/.
Dapr reached the production-ready v1.0 release in February 2021; see https://blog.dapr.io/posts/2021/02/17/announcing-dapr-v1.0/ for more details. In November 2021, Dapr joined CNCF as an incubated project; see the announcement at https://blog.dapr.io/posts/2021/11/03/dapr-joins-cncf-as-an-incubating-project/.
Dapr offers developers an approach to design the tools to build and the runtime to operate applications, based on a microservice architecture style.
Microservices offer a vast array of benefits balanced by increased complexities in team and product management, usually with a significant burden on the developer and the team in order to get started.
What if you could leverage a runtime such as Dapr to help you get through the common patterns you will likely need to adopt, and thus ease your operations?
The following figure shows the two Dapr hosting modes:
Figure 1.2 – Dapr sidecar
As depicted in Figure 1.2, the Dapr runtime operates in sidecar processes, lifting most of the complexity from the application to a separate environment, greatly simplifying development and operations as well. These sidecar processes are run locally in your development environment or as containers in a Pod on Kubernetes.
From an application perspective, Dapr is an Application Programming Interface (API) that can be directly reached via HyperText Transfer Protocol (HTTP), Remote Procedure Call (gRPC) calls, or, even more simply, via any of the Software Development Kits (SDKs) available for .NET, Java, Go, Python, PHP, JavaScript, C++, and Rust languages.
As we will experience later, it is not necessary to adopt the Dapr SDK in your application; a request to a Dapr service can be as simple as an HTTP call to an endpoint, such as http://localhost:3500/v1.0/invoke/<app-id>/method/<methodname>. Nevertheless, using the SDK does provide many benefits if you are writing a Dapr service adopting the server extensions, interacting with Dapr via the client SDK, or leveraging the Dapr actor model with the Actor SDK.
You can learn more about SDKs and the supported languages in the Dapr docs at https://docs.dapr.io/developing-applications/sdks/.
Now that we have learned about the high-level architecture of Dapr, it is time to also clarify what Dapr is not.
While we hope the overview of Dapr has informed and intrigued you enough to spend time on this book, when we have the chance to talk about Dapr, we often find ourselves in need of clarifying what Dapr is not. This makes it easier to eliminate any misconceptions we may have about what Dapr does, as follows:
Dapr is designed to be integrated with service meshes such as Istio, which is out of the scope of this book.
Important note
While this book is heavily skewed toward .NET, Dapr does provide the same benefits to Python developers (just as an example) as it provides SDKs for Dapr and Dapr Actor, with Kubernetes as the deployment target—Dapr welcomes all developers in a vendor-neutral and open approach.
We hope this perspective on the Dapr objectives and role will help you in properly adopting this technology. The next section will be dedicated to understanding the architecture of Dapr.
Dapr has been designed from the ground up as a set of pluggable building blocks—developers can create an application counting on the support of many facilities, while operators can adapt applications to the hosting environment by simply intervening in the configuration.
The following is a complete list of the tools and components of Dapr:
Dapr provides several building blocks that microservice application developers can adopt selectively, based on their needs, and they are as follows:
This building block is presented in more detail in Chapter 4, Service-to-Service Invocation.
You can learn about this building block in Chapter 5, Introducing State Management.
A discussion of this building block is presented in Chapter 6, Publish and Subscribe.
This building block is presented in more detail in Chapter 7, Resource Bindings.
You can learn about this building block in Chapter 8, Using Actors.
This building block is presented in more detail in Chapter 11, Tracing Dapr Applications.
After learning about Dapr architecture and components, and before we can start using them, we need to set up Dapr in our development environment, which will be the topic of the next section.
Dapr is a runtime for every platform and every language. The focus of this book is on C# in .NET, used with Visual Studio Code (VS Code). The code snippets in the book can be appreciated by developers from any background, but nevertheless, you will get the most out of it from a .NET perspective.
The development environment we use is Windows, as you will be able to tell from the screenshots we use in the book. While the CLI, configuration, and files will be the same, if you need more details on how to perform a particular action on Linux or a macOS development machine, we encourage you to check the Dapr documentation at https://docs.dapr.io/.
Dapr roadmap
The Dapr runtime reached the v1.0 production-ready release in February 2021, as announced in the Dapr blog at https://blog.dapr.io/posts/2021/02/17/announcing-dapr-v1.0/, and five new minor versions have been released during 2021. You can learn more about the Dapr roadmap at https://docs.dapr.io/contributing/roadmap/.
The samples and scripts in this book have been updated and tested with v1.8 of Dapr.
In this book, we will also leverage several services on the Azure cloud platform (https://azure.microsoft.com/en-us/explore/), whether as a platform to execute Dapr applications, for exchanging messages via Azure, or for storing data.
Access to an Azure subscription is required. Each chapter will give you instructions and direct you to documentation for further information.
Next, we will accomplish the following steps:
Dapr requires Docker to be present locally in your development environment; therefore, make sure you have it installed. If your development machine is Windows, Docker must be running in Linux container mode.
You can find detailed instructions for running Docker at https://docs.docker.com/install/.
We will immediately start working with Dapr; therefore, you need to install all the necessary tools. The Dapr runtime and its tools can be found at https://github.com/dapr/cli.
On Windows, execute the following command to install the CLI in the c:/dapr directory and add it to the user PATH environment variable so that the tools can be easily found from the command line:
powershell -Command "iwr -useb https://raw.githubusercontent.com/dapr/cli/master/install/install.ps1 | iex"
For more details on the Dapr CLI, please refer to https://docs.dapr.io/getting-started/install-dapr-cli/.
We still need to initialize Dapr on the development machine, which we will do in the Installing Dapr in self-hosted mode section of this chapter.
To install .NET 6, please refer to https://dotnet.microsoft.com/download for the link to the latest binaries.
.NET 6 is a Long-Term Support (LTS) version of .NET, which gets free support and patches for 3 years. Refer to https://dotnet.microsoft.com/en-us/platform/support/policy for more details on the .NET support policy.
On a development machine, it makes sense to install the full SDK, which includes the runtime. Once the install is complete, open a new command prompt and run the dotnet --info command. You should see the following output:
PS C:Reposdapr-sampleschapter01> dotnet --info .NET SDK (reflecting any global.json): Version: 6.0.101 Commit: ef49f6213a Runtime Environment: OS Name: Windows OS Version: 10.0.22000 OS Platform: Windows RID: win10-x64 Base Path: C:Program Filesdotnetsdk6.0.101 Host (useful for support): Version: 6.0.1 Commit: 3a25a7f1cc …
This proves that .NET has been recognized and the framework is working fine.
VS Code is a great multiplatform source code editor by Microsoft. You can install it for free by following the instructions at https://code.visualstudio.com/docs/setup/windows.
Dapr has an extension for VS Code that helps with navigating the Dapr local environment and eases the debugging configuration—we highly recommend it. Please follow the instructions at https://docs.dapr.io/developing-applications/ides/vscode/.
We really love the new Windows Terminal (https://aka.ms/terminal) for its ease of use and configurability. In the following chapters, we will often have to run multiple commands and tools in parallel. Therefore, the tabs feature of Windows Terminal is just one of the reasons why we suggest you adopt it too.
Dapr can be initialized in two modes: self-hosted (or standalone) and Kubernetes.
As it is intended to be used for a development environment, the self-hosted mode locally installs Redis, the Dapr placement services, and Zipkin. The following command initializes Dapr in your local environment:
dapr init
The Dapr binaries and default components to leverage Redis are by default positioned in the %USERPROFILE%.dapr folder.
In a local development environment, it might happen that the ports Dapr might intend to use for Redis, for example, are already in use. In this case, you should identify which processes or containers are using the ports and change them accordingly.
Once you launch the init command, the following is the output you should expect:
PS C:Repospractical-daprchapter01> dapr init Making the jump to hyperspace... Installing runtime version 1.8.4 Downloading binaries and setting up components... Downloaded binaries and completed components set up. daprd binary has been installed to C:Usersdabedin.daprin. dapr_placement container is running. dapr_redis container is running. dapr_zipkin container is running. Use `docker ps` to check running containers. Success! Dapr is up and running. To get started, go here: https://aka.ms/dapr-getting-started
To check your newly initialized Dapr environment, you can use docker ps as follows:
PS C:Repospractical-daprchapter01> docker ps --format "{{. Image}} - {{.Ports}} - {{.Names}}" daprio/dapr:1.8.4 - 0.0.0.0:6050->50005/tcp, :::6050->50005/tcp - dapr_placement openzipkin/zipkin - 9410/tcp, 0.0.0.0:9411->9411/tcp, :::9411- >9411/tcp - dapr_zipkin redis - 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp - dapr_redis
The output shows the Docker container for Dapr running on our machine.
Dapr is specifically intended to be executed on Kubernetes. From your development machine on which you have the Dapr CLI installed, you can set up Dapr on the Kubernetes cluster currently configured as follows:
Alternatively, you can install Dapr on Kubernetes with a Helm v3 chart. You can find more details at https://docs.dapr.io/getting-started/install-dapr-kubernetes/#install-with-helm-advanced.
Important note
If you intend to define a Continuous Integration/Continuous Deployment (CI/CD) pipeline that takes care of the Dapr installation on the Kubernetes cluster too, this can also work, although it is out of scope for the present setup.
To verify the installation was successfully completed, execute the following command:
The command should display the pods in the dapr-system namespace.
On a development Windows machine on which a previous version of Dapr was already present, the CLI can be updated by simply re-installing with the command we saw in a previous section.
As described in https://docs.dapr.io/operations/hosting/self-hosted/self-hosted-upgrade/, on a Windows development machine on which a previous version of Dapr was already present, you must uninstall Dapr first as follows:
PS C:Repospractical-daprchapter01> dapr uninstall --all
With the CLI updated and Dapr uninstalled, we can repeat the Dapr installation as follows:
PS C:Repospractical-daprchapter01> dapr init
After we execute dapr init, checking the Dapr version, we can see it has now moved forward from 1.0 to 1.1 for both the CLI and the runtime, as illustrated in the following code snippet:
PS C:Repospractical-daprchapter01> dapr --version CLI version: 1.8.1 Runtime version: 1.8.4
Our Dapr test environment is up and running. We are now ready to try it with our first sample.
It is time to see Dapr in action. We are going to build a web API that returns a hello world message. We chose to base all our samples in the C:Repospractical-dapr folder, and we created a C:Repospractical-daprchapter01 folder for this first sample. We’ll take the following steps:
PS C:Repospractical-daprchapter01> dotnet new webapi
-o dapr.microservice.webapi
PS C:Repospractical-daprchapter01> dotnet add package
Dapr.AspNetCore --version 1.8.0
We also added app.MapSubscribeHandler(). While this is not necessary for our sample, as we will not use the pub/sub features of Dapr, it is better to have it in mind as the base set of changes you need to apply to a default ASP.NET project.
Finally, in order to simplify the code, we commented app.UseHttpsRedirection().
The following is the modified code of the Program.cs class:
var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers().AddDapr(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } //app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.MapSubscribeHandler(); app.Run();
In the preceding code block, we instructed Dapr to leverage the Model-View-Controller (MVC) pattern in ASP.NET 6.
using Microsoft.AspNetCore.Mvc;
namespace dapr.microservice.webapi.Controllers;
[ApiController]
[Route("[controller]")]
public class HelloController : ControllerBase
{
private readonly ILogger<HelloController> _logger;
public HelloController(ILogger<HelloController>
logger)
{
_logger = logger;
}
[HttpGet()]
public ActionResult<string> Get()
{
return "Hello, World";
}
}
In the preceding code snippet, you can see [Route] and [HttpGet]. These ASP.NET attributes are evaluated by the routing to identify the method name.
dapr run --app-id <your app id> --app-port <port of the
application> --dapr-http-port <port in Dapr> dotnet run
We left the ASP.NET default port as 5000 but we changed the Dapr HTTP port to 5010. The following command line launches the Dapr application:
PS C:Repospractical-daprchapter01dapr.microservice. webapi> dapr run --app-id hello-world --app-port 5000 --dapr-http-port 5010 dotnet run Starting Dapr with id hello-world. HTTP Port: 5010. gRPC Port: 52443
The initial message informs you that Dapr is going to use port 5010 for HTTP as specified, while for gRPC, it is going to auto-select an available port.
The log from Dapr is full of information. To confirm your application is running correctly in the context of the Dapr runtime, you can look for the following code:
Updating metadata for app command: dotnet run You're up and running! Both Dapr and your app logs will appear here.
At this stage, ASP.NET is responding locally on port 5000 and Dapr is responding on port 5010. In order to test Dapr, let’s invoke a curl command as follows, and using the browser is equally fine:
PS C:Repospractical-daprchapter01> curl http:// localhost:5010/v1.0/invoke/hello-world/method/hello Hello, World
This exciting response has been returned by Dapr, which passed our (the client’s) initial request to the ASP.NET Web API framework. You should also see that the same result logged as Console.WriteLine sends its output to the Dapr window as follows:
== APP == Hello, World.
PS C:WindowsSystem32> dapr dashboard
Dapr Dashboard running on http://localhost:8080
We can open the dashboard by navigating to http://localhost:8080 to reveal the following screen:
Figure 1.3 – Dapr dashboard application
The Dapr dashboard shown in Figure 1.3 illustrates the details of our hello-world application.
In this case, the Dapr dashboard shows only this sample application we are running on the development machine. In a Kubernetes environment, it would show all the microservices running, along with the other components.
The Dapr dashboard also displays the configured components in the hosting environment, as we can see in the following screenshot:
Figure 1.4 – Dapr dashboard components
In Figure 1.4, the Dapr dashboard shows us that the local installation of Redis is configured as state store and pub/sub components, in addition to the deployment of Zipkin.
This ends our introductory section, where we were able to build our first Dapr sample.
In this chapter, you have learned about the Dapr project, its components, building blocks, and the sidecar approach. All of these concepts will be explored individually in further depth in the following chapters. You are now able to set up Dapr on your local development machine and prepare all the necessary tools to make this experience easier.
You have also learned how to create a simple ASP.NET project and how to configure and check Dapr, and we have had a glimpse of the Dapr dashboard where we can gain a complete and immediate view of the Dapr environment.
In the next chapter, we will use the newly created environment to learn how to debug Dapr.
3.147.56.45