To complete this assignment, you must reach the following goals:
- The VehicleRegistrationService and FineCollectionService are both running with a Dapr sidecar.
- The FineCollectionService uses the Dapr service invocation building block to call the
/vehicleinfo/{licensenumber}
endpoint on the VehicleRegistrationService.
This assignment targets number 1 in the end-state setup:
In assignment 1, you started all the services using dotnet run
. When you want to run a service with a Dapr sidecar that handles its communication, you need to start it using the Dapr CLI. There are a couple of things you need to specify when starting the service:
-
The service needs a unique id which Dapr can use to find it. This is called the app-id (or application Id). You specify this with the
--app-id
flag on the command-line. -
Each of the services listens on a different HTTP port for requests (to prevent port collisions on localhost). The VehicleRegistrationService runs on port
6002
for instance. You need to tell Dapr this port so the Dapr sidecar can communicate with the service. You specify this with the--app-port
flag on the command-line. -
The service can use HTTP or gRPC to communicate with the Dapr sidecar. By default these ports are
3500
and50001
. But to prevent confusion, you'll use totally different port numbers in the assignments. To prevent port collisions on the local machine when running multiple services, you have to specify a unique HTTP and gRPC port per service. You specify this with the--dapr-http-port
and--dapr-grpc-port
flags on the command-line. Throughout the workshop, you will use the following ports:Service Application Port Dapr sidecar HTTP port Dapr sidecar gRPC port TrafficControlService 6000 3600 60000 FineCollectionService 6001 3601 60001 VehicleRegistrationService 6002 3602 60002 -
Finally you need to tell Dapr how to start the service. The services are .NET services which can be started with the command
dotnet run
.
You will use the run
command of the Dapr CLI and specify all the options above on the command-line:
-
Make sure you have started Docker Desktop on your machine and the Dapr CLI and runtime are installed (see the prerequisites).
-
Open the source code folder in VS Code.
-
Open the terminal window in VS Code and make sure the current folder is
VehicleRegistrationService
. -
Enter the following command to run the VehicleRegistrationService with a Dapr sidecar:
dapr run --app-id vehicleregistrationservice --app-port 6002 --dapr-http-port 3602 --dapr-grpc-port 60002 dotnet run
-
Check the logs for any errors. As you can see, both Dapr as well as application logging is shown as output.
Now you're running a 'Daprized' version of the VehicleRegistrationService. As you might have noticed, you didn't need to change any code for this to work. The VehicleRegistrationService is still just a web API listening for requests. Only now, you've started it with a Dapr sidecar next to it that can communicate with it. This means other services can use Dapr to call this service. This is what you'll do in the next step.
In this step, you're going to change the code of the FineCollectionService so it uses Dapr service invocation to call the VehicleRegistrationService.
First you're going to change the code so it calls the Dapr sidecar:
-
Open the file
FineCollectionService/Controllers/CollectionController.cs
in VS Code. -
Inspect the
CollectFine
method. It contains a call to the VehicleRegistrationService to retrieve the vehicle info:// get owner info var vehicleInfo = await _vehicleRegistrationService.GetVehicleInfo(speedingViolation.VehicleId);
The
_vehicleRegistrationService
is an instance of a proxy that uses the .NETHttpClient
to call the VehicleRegistrationService. You are going to change that proxy so it uses Dapr service invocation. -
Open the file
FineCollectionService/Proxies/VehicleRegistrationService.cs
in VS Code. -
Inspect the
GetVehicleInfo
method. You can see that in the HTTP call, the URL of the VehicleRegistrationService (running on port 6002) is used. -
The API for calling the Dapr service invocation building block on a Dapr sidecar is:
http://localhost:<daprPort>/v1.0/invoke/<appId>/method/<method-name>
You can substitute the placeholders in this URL with the appropriate values so the FineCollectionService's sidecar can call the the VehicleRegistrationService, this yields the following URL:
http://localhost:3601/v1.0/invoke/vehicleregistrationservice/method/vehicleinfo/{licenseNumber}
As you can see in this URL, the FineCollectionService's Dapr sidecar will run on HTTP port
3601
. -
Replace the URL in the code with the new Dapr service invocation URL. The code should now look like this:
public async Task<VehicleInfo> GetVehicleInfo(string licenseNumber) { return await _httpClient.GetFromJsonAsync<VehicleInfo>( $"http://localhost:3601/v1.0/invoke/vehicleregistrationservice/method/vehicleinfo/{licenseNumber}"); }
It's important to really grasp the sidecar pattern used by Dapr. In this case, the FineCollectionService calls the VehicleRegistrationService by calling its own Dapr sidecar! The FineCollectionService doesn't need to know anymore where the VehicleRegistrationService lives because its Dapr sidecar will take care of that. It will find it based on the
app-id
specified in the URL and call the target service's sidecar. -
Open a new terminal window in VS Code and make sure the current folder is
FineCollectionService
. -
Check all your code-changes are correct by building the code:
dotnet build
If you see any warnings or errors, review the previous steps to make sure the code is correct.
-
Enter the following command to run the FineCollectionService with a Dapr sidecar:
dapr run --app-id finecollectionservice --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 dotnet run
-
Check the logs for any errors. As you can see, both Dapr as well as application logging is shown as output.
Now you're going to test the application:
-
Open a new terminal window in VS Code and change the current folder to
TrafficControlService
. -
Enter the following command to run the TrafficControlService:
-
dotnet run
The TrafficControlService does not need to run with a Dapr sidecar in this assignment. This is because it will still call the FineCollectionService over HTTP as before.
The services are up & running. Now you're going to test this using the simulation.
-
Open a new terminal window in VS Code and change the current folder to
Simulation
. -
Start the simulation:
dotnet run
You should see similar logging as before when you ran the application. So all the functionality works the same, but now you use Dapr service invocation to communicate between the FineCollectionService and the VehicleRegistrationService.
In this step, you're going to change the code of the FineCollectionService so it uses the Dapr SDK for .NET to call the VehicleRegistrationService. The SDK provides a more integrated way to invoke the Dapr sidecar API.
First stop the simulation:
-
Open the terminal window in VS Code in which the Camera Simulation runs.
-
Stop the simulation by pressing
Ctrl-C
and close the terminal window by clicking the trashcan icon in its title bar (or typing theexit
command). -
Open the terminal window in VS Code in which the FineCollectionService runs.
-
Stop the service by pressing
Ctrl-C
. Keep this terminal window open and focused. -
Add a reference to the Dapr ASP.NET Core integration library:
dotnet add package Dapr.AspNetCore -v 1.4.0
The
Dapr.AspNetCore
package contains theDaprClient
class used to directly invoke the Dapr API as well as additional integrations with ASP.NET Core. Because the services are all ASP.NET Core web APIs, we'll use this package throughout the workshop.
Now you'll change the code to use the Dapr SDK HttpClient
integration to call the VehicleRegistrationService. The HttpClient
integration allows you to keep using the regular HttpClient
to make service calls, while the SDK ensures that calls are routed through the Dapr sidecar.
-
Open the file
FineCollectionService/Startup.cs
in VS Code. -
Add a using statement in this file to make sure you can use the Dapr client:
using Dapr.Client;
-
The
ConfigureServices
method, contains these two lines of code which register the .NETHttpClient
and theVehicleRegistrationService
proxy (which uses theHttpClient
) with dependency injection:// add service proxies services.AddHttpClient(); services.AddSingleton<VehicleRegistrationService>();
-
Replace these two lines with with the following lines:
// add service proxies services.AddSingleton<VehicleRegistrationService>(_ => new VehicleRegistrationService(DaprClient.CreateInvokeHttpClient( "vehicleregistrationservice", "http://localhost:3601")));
As you can see in this snippet, you use the
DaprClient
to create anHttpClient
instance for doing service invocation. You specify theapp-id
of the service you want to communicate with. You also specify the address of the Dapr sidecar, because the FineCollectionService's sidecar does not use the default Dapr HTTP port (3500). The resultingHttpClient
instance is explicitly passed into the constructor of theVehicleRegistrationService
proxy.This is an example of the deep integration of Dapr with ASP.NET Core when you use the
Dapr.AspNetCore
library. You can still use theHttpClient
(and its rich feature-set) in your code, but under the hood the Dapr service invocation building block is used. -
Open the file
FineCollectionService/Proxies/VehicleRegistrationService.cs
in VS Code. -
Because the
HttpClient
passed into this class has already been created for a certainapp-id
, you can omit the host information from the request URL. Change the URL that is used in theGetVehicleInfo
to/vehicleinfo/{license-number}
. The method should now look like this:public async Task<VehicleInfo> GetVehicleInfo(string licenseNumber) { return await _httpClient.GetFromJsonAsync<VehicleInfo>( $"/vehicleinfo/{licenseNumber}"); }
Now the FineCollectionService is changed to use the Dapr SDK for service invocation. Let's test this.
-
If you followed the instructions in this assignment, the VehicleRegistrationService and TrafficControlService are still running.
-
Open the terminal window in VS Code in which the FineCollectionService was running.
-
Enter the following command to start the changed FineCollectionService again:
dapr run --app-id finecollectionservice --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 dotnet run
The services are up & running. Now you're going to test this using the simulation.
-
Open a new terminal window in VS Code and change the current folder to
Simulation
. -
Start the simulation:
dotnet run
You should see similar logging as before when you ran the application.
So how can you check whether or not the call to the VehicleRegistrationService is handled by Dapr? Well, Dapr has some observability built in. You can look at Dapr traffic using Zipkin:
-
Open a browser and go the this URL: http://localhost:9411/zipkin.
-
Click the
RUN QUERY
button in the top right of the screen to search for traces. -
You should see the calls between the FineCollectionService and the VehicleRegistrationService. You can expand and collapse each trace and click the
SHOW
button to get more details: -
If you click the dependencies button and search, you will see the services and the traffic flowing between them:
Make sure you stop all running processes and close all the terminal windows in VS Code before proceeding to the next assignment.
Go to assignment 3.