Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Principal author: Marc Duiker
Developing and local testing of microservices is challenging, especially when you want to run multiple services on your local dev environment simultaneously. You need to make sure all services are configured correctly (no conflicting ports) and then start them all individually. The more services you build, the more complex this becomes.
This quickstart describes how to use the Dapr CLI to run multiple Dapr services at once. This is a great way to speed up the inner development loop.
Microservices with Dapr
Dapr is a portable, event-driven runtime that enables developers to efficiently build resilient, microservice-based applications that runs on the cloud and edge. Developers like to use Dapr since it offers ready to use building blocks for workflow, state management, publish/subscribe, configuration, secrets management, and more. These building block functionalities are exposed through a set of HTTP and gRPC APIs, so any language that supports these protocols can use Dapr.
The multi-app-run GitHub repository contains a demo that uses the Dapr publish/subscribe building block to communicate between services. The demo consists of three services written in Nodejs:
- publisher: Publishes a message to the
orders
every 1 seconds and prints the message to the console. - subscriber1: Subscribes to the
orders
topic and prints the message to the console. - subscriber2: subscribes to the
orders
topic and prints the message to the console.
Note
The message broker in this demo is Redis that is running locally in a container. This container is installed automatically when installing the Dapr CLI.
Prerequisites
In order to run the demo, ensure you use a supported OS and install the required tools:
- Supported OS: Linux or macOS (Windows is not yet supported)
- Nodejs
- Docker Desktop
- Dapr CLI
Running the demo
Clone the multi-app-run repo locally.
Open the
multi-app-run
folder in a new terminal, and run this command to install the Node modules for the three apps:npm run install-all
While still in the root of the repository, run this command to start the Dapr runtime and the three apps using the preconfigured multi-app run template file:
dapr run -f .
The above command will read the dapr.yaml file that contains the multi-app run configuration. The file content is explained in the How it works section below.
The output of the
dapr run -f .
command should be similar to this:⚠ This is a preview feature and subject to change in future releases. ℹ️ Validating config and starting app "subscriber1" == APP - subscriber1 == == APP - subscriber1 == > subscriber1@1.0.0 start == APP - subscriber1 == > node index.js == APP - subscriber1 == == APP - subscriber1 == 2023-08-20T13:46:06.145Z INFO [HTTPServer, HTTPServerImpl] [Topic = orders] Registered Subscription with routes: default == APP - subscriber1 == 2023-08-20T13:46:06.146Z INFO [HTTPServer, HTTPServer] Listening on 5101 == APP - subscriber1 == 2023-08-20T13:46:06.146Z INFO [HTTPServer, HTTPServer] Registering 1 PubSub Subscriptions == APP - subscriber1 == 2023-08-20T13:46:06.157Z INFO [HTTPClient, HTTPClient] Sidecar Started == APP - subscriber1 == 2023-08-20T13:46:06.174Z INFO [HTTPServer, HTTPServer] Registered 1 PubSub Subscriptions ℹ️ Started Dapr with app id "subscriber1". HTTP Port: 54179. gRPC Port: 54180 ℹ️ Writing log files to directory : /Users/marcduiker/dev/diagrid-labs/multi-app-run/src/subscriber1/.dapr/logs ℹ️ Validating config and starting app "subscriber2" == APP - subscriber2 == == APP - subscriber2 == > subscriber2@1.0.0 start == APP - subscriber2 == > node index.js == APP - subscriber2 == == APP - subscriber2 == 2023-08-20T13:46:07.165Z INFO [HTTPServer, HTTPServerImpl] [Topic = orders] Registered Subscription with routes: default == APP - subscriber2 == 2023-08-20T13:46:07.167Z INFO [HTTPServer, HTTPServer] Listening on 5102 == APP - subscriber2 == 2023-08-20T13:46:07.168Z INFO [HTTPServer, HTTPServer] Registering 1 PubSub Subscriptions == APP - subscriber2 == 2023-08-20T13:46:07.182Z INFO [HTTPClient, HTTPClient] Sidecar Started == APP - subscriber2 == 2023-08-20T13:46:07.197Z INFO [HTTPServer, HTTPServer] Registered 1 PubSub Subscriptions ℹ️ Started Dapr with app id "subscriber2". HTTP Port: 54211. gRPC Port: 54212 ℹ️ Writing log files to directory : /Users/marcduiker/dev/diagrid-labs/multi-app-run/src/subscriber2/.dapr/logs ℹ️ Validating config and starting app "publisher" ℹ️ Started Dapr with app id "publisher". HTTP Port: 54245. gRPC Port: 54246 ℹ️ Writing log files to directory : /Users/marcduiker/dev/diagrid-labs/multi-app-run/src/publisher/.dapr/logs == APP - publisher == == APP - publisher == > publisher@1.0.0 start == APP - publisher == > node index.js == APP - publisher == == APP - publisher == 2023-08-20T13:46:09.263Z INFO [HTTPClient, HTTPClient] Sidecar Started == APP - publisher == Published: {"orderId":1} == APP - subscriber2 == Subscriber 2 received: {"orderId":1} == APP - subscriber1 == Subscriber 1 received: {"orderId":1} == APP - publisher == Published: {"orderId":2} == APP - subscriber2 == Subscriber 2 received: {"orderId":2} == APP - subscriber1 == Subscriber 1 received: {"orderId":2} == APP - subscriber2 == Subscriber 2 received: {"orderId":3} == APP - subscriber1 == Subscriber 1 received: {"orderId":3} == APP - publisher == Published: {"orderId":3} == APP - publisher == Published: {"orderId":4} == APP - subscriber2 == Subscriber 2 received: {"orderId":4} == APP - subscriber1 == Subscriber 1 received: {"orderId":4} == APP - subscriber1 == Subscriber 1 received: {"orderId":5} == APP - subscriber2 == Subscriber 2 received: {"orderId":5} == APP - publisher == Published: {"orderId":5} == APP - publisher == Published: {"orderId":6} == APP - subscriber2 == Subscriber 2 received: {"orderId":6} == APP - subscriber1 == Subscriber 1 received: {"orderId":6} == APP - publisher == Published: {"orderId":7} == APP - subscriber1 == Subscriber 1 received: {"orderId":7} == APP - subscriber2 == Subscriber 2 received: {"orderId":7} == APP - publisher == Published: {"orderId":8} == APP - subscriber1 == Subscriber 1 received: {"orderId":8} == APP - subscriber2 == Subscriber 2 received: {"orderId":8} == APP - publisher == Published: {"orderId":9} == APP - subscriber1 == Subscriber 1 received: {"orderId":9} == APP - subscriber2 == Subscriber 2 received: {"orderId":9} == APP - publisher == Published: {"orderId":10} == APP - subscriber1 == Subscriber 1 received: {"orderId":10} == APP - subscriber2 == Subscriber 2 received: {"orderId":10} Exited App successfully
Congratulations! You have now successfully run three Dapr services with one Dapr CLI command.
How it works
Now let's have a look how multi-app run is configured in the dapr.yaml
multi-app run template file:
version: 1
common:
resourcesPath: ./resources/
apps:
- appID: subscriber1
appDirPath: ./src/subscriber1/
appPort: 5101
appProtocol: http
command: ["npm", "start"]
appLogDestination: fileAndConsole
daprdLogDestination: file
- appID: subscriber2
appDirPath: ./src/subscriber2/
appPort: 5102
appProtocol: http
command: ["npm", "start"]
appLogDestination: fileAndConsole
daprdLogDestination: file
- appID: publisher
appDirPath: ./src/publisher/
appProtocol: http
command: ["npm", "start"]
appLogDestination: fileAndConsole
daprdLogDestination: file
Common section
The common section is an optional part of the file where variables can be defined that are shared across all Dapr applications that are part of the apps section.
In this case, all Dapr apps use the same pubsub component that is defined in the resources/pubsub.yaml
file.
Environment variables can also be placed in this common section as follows:
common:
env: # any environment variable shared across apps
DEBUG: true
Apps section
The apps section is a list of Dapr applications that are part of the multi-app run.
Note
Note that the order of the Dapr applications in this section determines the sequence in which they are started.
The following properties have been used for the apps in this demo:
appID
: The ID of the Dapr application. This is used to identify the application in the Dapr dashboard.appDirPath
: The path to the directory where the application is located.appPort
: The port on which the application is listening.appProtocol
: The protocol that the application is using. This can behttp
orgrpc
.command
: The command that is used to start the application.appLogDestination
: The destination of the application logs. This can befile
,console
orfileAndConsole
.daprdLogDestination
: The destination of the Dapr logs. This can befile
,console
orfileAndConsole
.
The full schema of the multi-app run template file can be found in the Dapr documentation.
Running Dapr with multi-app run
To execute Dapr with multi-app run, specify the path to the multi-app run template file with the -f
flag:
dapr run -f <dir_path>
Note
If the multi-app run template file is named dapr.yaml
and is located in the current directory, the command can be simplified to dapr run -f .
.
Next steps
For more information on multi-app run, see the Dapr documentation.
Do you have any questions about Dapr? Join the the Dapr discord and connect with thousands of other developers.
Community Content