1 Star 0 Fork 2

SmartIDE / sample-dapr-traffic-control

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
Apache-2.0

Dapr Traffic Control Sample

Attribute Details
Dapr runtime version v1.6.0
Dapr.NET SDK version v1.6.0
Dapr CLI version v1.6.0
Language C#
Platform .NET 6
Environment Self hosted or Kubernetes

This repository contains a sample application that simulates a traffic-control system using Dapr. For this sample I've used a speeding-camera setup as can be found on several Dutch highways. A set of cameras are placed at the beginning and the end of a stretch of highway. Using data from these cameras, the average speed of a vehicle is measured. If this average speed is above the speeding limit on this highway, the driver of the vehicle receives a fine.

Overview

This is an overview of the fictitious setup I'm simulating in this sample:

Speed trap overview

There's 1 entry-camera and 1 exit-camera per lane. When a car passes an entry-camera, the license-number of the car and the timestamp is registered.

When the car passes an exit-camera, this timestamp is also registered by the system. The system then calculates the average speed of the car based on the entry- and exit-timestamp. If a speeding violation is detected, a message is sent to the Central Fine Collection Agency (or CJIB in Dutch). They will retrieve the information of the owner of the vehicle and send him or her a fine.

Simulation

In order to simulate this in code, I created the following services:

Services

  • The Camera Simulation is a .NET Core console application that will simulate passing cars.
  • The Traffic Control Service is an ASP.NET Core WebAPI application that offers 2 endpoints: /entrycam and /exitcam.
  • The Fine Collection Service is an ASP.NET Core WebAPI application that offers 1 endpoint: /collectfine for collecting fines.
  • The Vehicle Registration Service is an ASP.NET Core WebAPI application that offers 1 endpoint: /vehicleinfo/{license-number} for getting the vehicle- and owner-information of speeding vehicle.

The way the simulation works is depicted in the sequence diagram below:

Sequence diagram

  1. The Camera Simulation generates a random license-number and sends a VehicleRegistered message (containing this license-number, a random entry-lane (1-3) and the timestamp) to the /entrycam endpoint of the TrafficControlService.
  2. The TrafficControlService stores the VehicleState (license-number and entry-timestamp).
  3. After some random interval, the Camera Simulation sends a VehicleRegistered message to the /exitcam endpoint of the TrafficControlService (containing the license-number generated in step 1, a random exit-lane (1-3) and the exit timestamp).
  4. The TrafficControlService retrieves the VehicleState that was stored at vehicle entry.
  5. The TrafficControlService calculates the average speed of the vehicle using the entry- and exit-timestamp. It also stores the VehicleState with the exit timestamp for audit purposes, but this is left out of the sequence diagram for clarity.
  6. If the average speed is above the speed-limit, the TrafficControlService calls the /collectfine endpoint of the FineCollectionService. The request payload will be a SpeedingViolation containing the license-number of the vehicle, the identifier of the road, the speeding-violation in KMh and the timestamp of the violation.
  7. The FineCollectionService calculates the fine for the speeding-violation.
  8. The FineCollectionSerivice calls the /vehicleinfo/{license-number} endpoint of the VehicleRegistrationService with the license-number of the speeding vehicle to retrieve its vehicle- and owner-information.
  9. The FineCollectionService sends a fine to the owner of the vehicle by email.

All actions described in this sequence are logged to the console during execution so you can follow the flow.

Dapr

This sample uses Dapr for implementing several aspects of the application. In the diagram below you see a schematic overview of the setup:

Dapr setup

  1. For doing request/response type communication between the FineCollectionService and the VehicleRegistrationService, the service invocation building block is used.
  2. For sending speeding violations to the FineCollectionService, the publish and subscribe building block is used. RabbitMQ is used as message broker.
  3. For storing the state of a vehicle, the state management building block is used. Redis is used as state store.
  4. Fines are sent to the owner of a speeding vehicle by email. For sending the email, the Dapr SMTP output binding is used.
  5. The Dapr input binding for MQTT is used to send simulated car info to the TrafficControlService. Mosquitto is used as MQTT broker.
  6. The FineCollectionService needs credentials for connecting to the smtp server and a license-key for a fine calculator component. It uses the secrets management building block with the local file component to get the credentials and the license-key.
  7. The TrafficControlService has an alternative implementation based on Dapr actors. See Run the application with actors for instructions on how to run this.

Here is the sequence diagram again, but now with all the Dapr building blocks and components:

Sequence diagram with Dapr building blocks

Run the application in Dapr self-hosted mode

In self-hosted mode everything will run on your local machine. To prevent port-collisions, all services listen on a different HTTP port. When running the services with Dapr, you need additional ports voor HTTP and gRPC communication with the sidecars. By default these ports are 3500 and 50001. But to prevent confusion, you'll use totally different port numbers in the assignments. The services 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

The ports can be specified on the command-line when starting a service with the Dapr CLI. The following command-line flags can be used:

  • --app-port
  • --dapr-http-port
  • --dapr-grpc-port

Execute the following steps to run the sample application in self hosted mode:

Start infrastructure components:

  1. Make sure you have installed Dapr on your machine in self-hosted mode as described in the Dapr documentation.
  2. Open a new command-shell.
  3. Change the current folder to the src/infrastructure folder of this repo.
  4. Start the infrastructure services by executing start-all.ps1 script. This script will start Mosquitto (MQTT broker), RabbitMQ (pub/sub broker) and Maildev. Maildev is a development SMTP server that does not actually send out emails (by default). Instead, it offers a web frontend that will act as an email in-box showing the emails that were sent to the SMTP server. This is very convenient for demos of testscenarios.

Start the services:

  1. Open a new command-shell.

  2. Change the current folder to the src/VehicleRegistrationService folder of this repo.

  3. Execute the following command (using the Dapr cli) to run the VehicleRegistrationService:

    dapr run --app-id vehicleregistrationservice --app-port 6002 --dapr-http-port 3602 --dapr-grpc-port 60002 --config ../dapr/config/config.yaml --components-path ../dapr/components dotnet run

    Alternatively you can also run the start-selfhosted.ps1 script.

  4. Open a new command-shell.

  5. Change the current folder to the src/FineCollectionService folder of this repo.

  6. Execute the following command (using the Dapr cli) to run the FineCollectionService:

    dapr run --app-id finecollectionservice --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 --config ../dapr/config/config.yaml --components-path ../dapr/components dotnet run

    Alternatively you can also run the start-selfhosted.ps1 script.

  7. Open a new command-shell.

  8. Change the current folder to the src/TrafficControlService folder of this repo.

  9. Execute the following command (using the Dapr cli) to run the TrafficControlService:

    dapr run --app-id trafficcontrolservice --app-port 6000 --dapr-http-port 3600 --dapr-grpc-port 60000 --config ../dapr/config/config.yaml --components-path ../dapr/components dotnet run

    Alternatively you can also run the start-selfhosted.ps1 script.

  10. Open a new command-shell.

  11. Change the current folder to the src/Simulation folder of this repo.

  12. Execute the following command to run the Camera Simulation:

    dotnet run

You should now see logging in each of the shells, similar to the logging shown below:

Camera Simulation:

Simulation logging

TrafficControlService:

TrafficControlService loggin

FineCollectionService:

FineCollectionService logging

VehicleRegistrationService:

VehicleRegistrationService logging

To see the emails that are sent by the FineCollectionService, open a browser and browse to http://localhost:4000. You should see the emails coming in:

Mailbox

Reserved ports issue

If you're on Windows with Hyper-V enabled, you might run into an issue that you're not able to use one (or more) of the ports used by the services. This could have something to do with aggressive port reservations by Hyper-V. You can check whether or not this is the case by executing this command:

netsh int ipv4 show excludedportrange protocol=tcp

If you see one (or more) of the ports shown as reserved in the output, fix it by executing the following commands in an administrative terminal:

dism.exe /Online /Disable-Feature:Microsoft-Hyper-V
netsh int ipv4 add excludedportrange protocol=tcp startport=6000 numberofports=3
netsh int ipv4 add excludedportrange protocol=tcp startport=3600 numberofports=3
netsh int ipv4 add excludedportrange protocol=tcp startport=3700 numberofports=3
dism.exe /Online /Enable-Feature:Microsoft-Hyper-V /All

Visual Camera Simulation

This repository also contains a graphical version of the Camera Simulation:

Visual simulation

The cars are all driving at different speeds and the simulation uses different "personas" to simulate drivers that tend to drive faster than others. They will also try to overtake where possible. These drivers are most likely to get a speeding ticket.

The simulation runs in a web-browser. In order to start the web-application host and run the simulation, execute the following steps:

  1. Open a new command-shell.

  2. Change the current folder to the src/VisualSimulation folder of this repo.

  3. Execute the following command to run the Visual Camera Simulation:

    dotnet run
  4. Open a browser window and navigate to http://localhost:5000.

  5. Use the arrow keys to scroll and zoom in/out.

Run the application with Dapr actors

The TrafficControlService has an alternative implementation based on Dapr actors.

The TrafficController in the TrafficControlService has 2 implementations of the VehicleEntry and VehicleExit methods. The top two methods contain all the code for handling vehicle registrations and storing vehicle state using the state management building block. The bottom two methods use a VehicleActor that does all the work. A new instance of the VehicleActor is created for each registered vehicle. In stead of using the state management building block, the actor uses its built-in StateManager.

You can find the code of the actor in the file src/TrafficControlService/Actors/VehicleActor.cs.

To use the actor based implementation, uncomment the statement that defines the USE_ACTORMODEL symbol at the top of the controller:

#define USE_ACTORMODEL

Now you can restart the application just as before. The behavior is exactly the same, but you will see that the logging of the TrafficControlService will be emitted by the VehicleActor:

Run the application on Kubernetes

Execute the following steps to run the sample application on Kubernetes:

  1. Make sure you have installed Dapr on your machine on a Kubernetes cluster as described in the Dapr documentation.

  2. Open a new command-shell.

  3. Change the current folder to the src/k8s folder of this repo.

  4. Run the build-docker-images.ps1 script. This script will build Docker images for all the services and a custom Mosquitto image used when running on Kubernetes.

  5. Execute the start.ps1 script. All services will be created in the dapr-trafficcontrol namespace.

You can check whether everything is running correctly by examining the container logs. There are several ways of doing that. Let's do it using the Docker CLI:

  1. Find out the container Id of the services:

    docker ps

For every service, 2 containers will be running: the service and the Dapr sidecar. Make sure you pick the Id of a container running the .NET service and not the Dapr sidecar.

  1. View the log for each of the services (replace the Id with the Id of one of your services):

    docker logs e2ed262f836e

To see the emails that are sent by the FineCollectionService, open a browser and browse to http://localhost:30000.

To stop the application and remove everything from the Kubernetes cluster, execute the stop.ps1 script.

Troubleshooting

If you get any errors while trying to run the application on Kubernetes, please double check whether you have installed Dapr into your Kubernetes cluster. You can check this by executing the command dapr status -k in a command-shell. You should see something like this:

  NAME                   NAMESPACE    HEALTHY  STATUS   REPLICAS  VERSION  AGE  CREATED
  dapr-placement-server  dapr-system  True     Running  1         1.5.0    14d  2021-11-17 20:40.01
  dapr-operator          dapr-system  True     Running  1         1.5.0    14d  2021-11-17 20:40.00
  dapr-sidecar-injector  dapr-system  True     Running  1         1.5.0    14d  2021-11-17 20:40.00
  dapr-sentry            dapr-system  True     Running  1         1.5.0    14d  2021-11-17 20:40.00
  dapr-dashboard         dapr-system  True     Running  1         0.9.0    14d  2021-11-17 20:40.00

If Dapr is not installed correctly in your cluster, you will see this message:

No status returned. Is Dapr initialized in your cluster?

In that case, install Dapr by executing the command dapr init -k in a command-shell.

Dapr for .NET Developers

If you want to learn more about Dapr, read this book that was co-authored by the creator of this sample application:

Dapr for .NET Developers

Dowload the PDF | Read it online

Although the book is targeted at .NET developers, it covers all the concepts and generic APIs of Dapr. So it should also be useful for developers that use a different technology stack.

Disclaimer

The code in this repo is NOT production grade and lacks any automated testing. It is intentionally kept as simple as possible (KISS). Its primary purpose is demonstrating several Dapr concepts and not being a full fledged application that can be put into production as is.

The author can in no way be held liable for damage caused directly or indirectly by using this code.

Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

简介

暂无描述 展开 收起
Apache-2.0
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
C#
1
https://gitee.com/smartide/sample-dapr-traffic-control.git
git@gitee.com:smartide/sample-dapr-traffic-control.git
smartide
sample-dapr-traffic-control
sample-dapr-traffic-control
main

搜索帮助