Skip to content

Commit

Permalink
implement rabbitmq and complete the architecture locally
Browse files Browse the repository at this point in the history
boyyy did i procrastinate with this one and the reason why is because i had to think quite a bit about how to implement rabbitmq in a clean way as it's quite dirty compared to azure service bus

skills from many resources were used here:
- Building ASP.NET Core 3 Hosted Services and .NET Core 3 Worker Services by Steve Gordan
- RabbitMQ by Example by Stephen Haunts
- Securing Microservices in ASP.NET Core by Kevin Dockx
- RabbitMQ Custom Docker Image with Custom Configuration and Definitions by Mike Møller Nielsen [YouTube]
- How export or import RabbitMQ configuration [Article]

a custom rabbitmq image is built with all the exchanges, queues and bindings configured, i manually configured and exported this using its api

the normal guest account is used for rabbitmq

i created my own naming convention for exchanges and queues [afaik] as follows:
exchange.applicationname.event
         applicationname.event.subscriber.queue

an example:
exchange.seelanstyres.deleteaccount
         seelanstyres.deleteaccount.addressservice.queue

this satisfies my ocd as it's easy to understand what it means

explaining it further:

a publisher publishes messages to an exchange [of type fanout in this case] and queues bind to that exchange and receive a copy of those messages.
each subscriber will listen in on its dedicated queue and process the messages

a visual of a fanout exchange [sort of 😂]:

                      -> queue -> subscriber
publisher -> exchange -> queue -> subscriber
                      -> queue -> subscriber

in the system there's three events:
- deleteaccount
- updateaccount
- updatetyre

the order microservice has data related to all three so a worker is created for each
the address microservice only needs to listen for when a customer deletes their account to remove all their addresses

i tried my best to abstract a lot of the complexity of rabbitmq into the shared library and ensure there isn't much duplication, however,
there's massive duplication for the worker services, in fact, the whole thing is copy and pasted and adjusted for the situation. this is something
that i will have to address later as it's not that simple to extract a common method or extension method

security as well as distributed tracing is maintained across rabbitmq

kevin dockx' implementation for token validation is used across rabbitmq since it's the cleanest way to implement it

now that the system is complete locally, soon it'll be azure time 😁 but before that, there's a lot of optimizations to make in terms of performance and implementing redis locally too
  • Loading branch information
ShaylenReddy42 committed Oct 31, 2022
1 parent c4dc341 commit 9619457
Show file tree
Hide file tree
Showing 55 changed files with 1,844 additions and 41 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,13 @@ set(

"Services | AddressServiceSolution | SeelansTyres.Data.AddressData | No"
"Services | AddressServiceSolution | SeelansTyres.Services.AddressService | Yes"
"Services | AddressServiceSolution | SeelansTyres.Workers.AddressWorker | Yes"

"Services | IdentityServiceSolution | SeelansTyres.Services.IdentityService | Yes"

"Services | OrderServiceSolution | SeelansTyres.Data.OrderData | No"
"Services | OrderServiceSolution | SeelansTyres.Services.OrderService | Yes"
"Services | OrderServiceSolution | SeelansTyres.Workers.OrderWorker | Yes"

"Services | TyresServiceSolution | SeelansTyres.Services.TyresService | Yes"
)
Expand Down
15 changes: 12 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,19 @@ The workers will listen in on dedicated queues for updates and update their copy
* Author: [Stephen Haunts](https://app.pluralsight.com/profile/author/stephen-haunts)
* [Logging and Monitoring in ASP.NET Core 6](https://www.pluralsight.com/courses/logging-monitoring-aspdotnet-core-6)
* Author: [Erik Dahl](https://app.pluralsight.com/profile/author/erik-dahl)
* [RabbitMQ by Example](https://www.pluralsight.com/courses/rabbitmq-by-example)
* Author: [Stephen Haunts](https://app.pluralsight.com/profile/author/stephen-haunts)
* [Building ASP.NET Core 3 Hosted Services and .NET Core 3 Worker Services](https://www.pluralsight.com/courses/building-aspnet-core-hosted-services-net-core-worker-services)
* [Steve Gordan](https://www.pluralsight.com/authors/steve-gordon)
* [Sending Email in C# using FluentEmail](https://www.youtube.com/watch?v=qSeO9886nRM)
* Author: [IAmTimCorey](https://www.youtube.com/user/IAmTimCorey)
* [Intro to Health Checks in .NET Core](https://www.youtube.com/watch?v=Kbfto6Y2xdw)
* Author: [IAmTimCorey](https://www.youtube.com/user/IAmTimCorey)
* [RabbitMQ Custom Docker Image with Custom Configuration and Definitions](https://www.youtube.com/watch?v=I8QHPfMhqAU)
* Author: [Mike Møller Nielsen](https://www.youtube.com/c/MikeM%C3%B8llerNielsen)
* [Microsoft Docs](https://docs.microsoft.com/en-us/)
* [Stack Overflow](https://stackoverflow.com/) [Obviously]
* [How export or import RabbitMQ configuration](https://sleeplessbeastie.eu/2020/03/18/how-export-or-import-rabbitmq-configuration/)

## Required local setup to build and run

Expand All @@ -102,12 +109,14 @@ The workers will listen in on dedicated queues for updates and update their copy
* NOTE: If you use `build-with-docker.cmd`, I recommend you pull these images beforehand:
* [elasticsearch:7.17.6](https://hub.docker.com/_/elasticsearch/)
* [kibana:7.17.6](https://hub.docker.com/_/kibana/)
* [rabbitmq:3-management](https://hub.docker.com/_/rabbitmq/)
* [mcr.microsoft.com/dotnet/aspnet:6.0](https://mcr.microsoft.com/en-us/product/dotnet/aspnet/about)
* [mcr.microsoft.com/dotnet/sdk:6.0](https://mcr.microsoft.com/en-us/product/dotnet/sdk/about)
* [mcr.microsoft.com/mssql/server:2019-latest](https://hub.docker.com/_/microsoft-mssql-server)
* If you use `build-with-loggingsinks.cmd`, pull only these images beforehand:
* If you use `build-with-services.cmd`, pull only these images beforehand:
* [elasticsearch:7.17.6](https://hub.docker.com/_/elasticsearch/)
* [kibana:7.17.6](https://hub.docker.com/_/kibana/)
* [rabbitmq:3-management](https://hub.docker.com/_/rabbitmq/)

* Ensure to set environment variables listed in the `RequiredEnvironmentVariables.txt` file
* Press the Win Key and search for `Edit environment variables for your account`
Expand All @@ -116,9 +125,9 @@ The workers will listen in on dedicated queues for updates and update their copy
* In order to build, I've provided three options for you:
* `build.cmd` which is the regular build
* `build-with-docker.cmd` just to see what it looks like orchestrated with docker compose
* `build-with-loggingsinks.cmd` which is the regular build + elasticsearch and kibana orchestrated with docker compose
* `build-with-services.cmd` which is the regular build + elasticsearch, kibana and rabbitmq orchestrated with docker compose

* Once you run either `build.cmd` or `build-with-loggingsinks.cmd`, CMake will generate `run-all.cmd`
* Once you run either `build.cmd` or `build-with-services.cmd`, CMake will generate `run-all.cmd`
* Thereafter, run `run-all.cmd` which will start all applications minimized and launch the site, simulating orchestration

## Demos
Expand Down
16 changes: 16 additions & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,14 @@ steps:
project: SeelansTyres.Services.AddressService
workDir: '$(workDir)'

- template: .pipelines/templates/publishProject.yml
parameters:
buildConfiguration: $(buildConfiguration)
solutionFolder: Services
solutionSubfolder: AddressServiceSolution
project: SeelansTyres.Workers.AddressWorker
workDir: '$(workDir)'

- template: .pipelines/templates/publishProject.yml
parameters:
buildConfiguration: $(buildConfiguration)
Expand All @@ -134,6 +142,14 @@ steps:
project: SeelansTyres.Services.OrderService
workDir: '$(workDir)'

- template: .pipelines/templates/publishProject.yml
parameters:
buildConfiguration: $(buildConfiguration)
solutionFolder: Services
solutionSubfolder: OrderServiceSolution
project: SeelansTyres.Workers.OrderWorker
workDir: '$(workDir)'

- template: .pipelines/templates/publishProject.yml
parameters:
buildConfiguration: $(buildConfiguration)
Expand Down
32 changes: 32 additions & 0 deletions cmake/AssemblyInfo/SeelansTyres.Workers.AddressWorker.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Reflection;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Seelan's Tyres: Address Worker Service")]
[assembly: AssemblyCompany("Shaylen Reddy")]
[assembly: AssemblyProduct("Seelan's Tyres: Address Worker Service")]
[assembly: AssemblyCopyright("Shaylen Reddy: MIT License")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("c71ce57a-276b-45e3-978d-22d7c71e64b4")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion("@FILE_VERSION@")]
[assembly: AssemblyFileVersion("@FILE_VERSION@")]
[assembly: AssemblyInformationalVersion("@INFORMATIONAL_VERSION@")]

// Custom Metadata
[assembly: AssemblyMetadata("Commit Url", "@COMMIT_URL@")]
32 changes: 32 additions & 0 deletions cmake/AssemblyInfo/SeelansTyres.Workers.OrderWorker.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Reflection;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Seelan's Tyres: Order Worker Service")]
[assembly: AssemblyCompany("Shaylen Reddy")]
[assembly: AssemblyProduct("Seelan's Tyres: Order Worker Service")]
[assembly: AssemblyCopyright("Shaylen Reddy: MIT License")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("bc002c92-571f-4d7c-9001-6ab39d84bde2")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion("@FILE_VERSION@")]
[assembly: AssemblyFileVersion("@FILE_VERSION@")]
[assembly: AssemblyInformationalVersion("@INFORMATIONAL_VERSION@")]

// Custom Metadata
[assembly: AssemblyMetadata("Commit Url", "@COMMIT_URL@")]
3 changes: 3 additions & 0 deletions orchestration/custom-images/rabbitmq/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM rabbitmq:3-management

COPY custom-configuration/ /etc/rabbitmq/
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
{
"users": [
{
"name": "guest",
"password_hash": "gs8lM74gLU9MnfbvJtwNKedQ0VaUVH6dssi7hhTAwuvDQNPH",
"hashing_algorithm": "rabbit_password_hashing_sha256",
"tags": [
"administrator"
],
"limits": {}
}
],
"vhosts": [
{
"name": "/"
}
],
"permissions": [
{
"user": "guest",
"vhost": "/",
"configure": ".*",
"write": ".*",
"read": ".*"
}
],
"topic_permissions": [],
"parameters": [],
"global_parameters": [
{
"name": "internal_cluster_id",
"value": "rabbitmq-cluster-id-F3rLs5lFxjL0F9hKSffbNg"
}
],
"policies": [],
"queues": [
{
"name": "seelanstyres.deleteaccount.addressservice.queue",
"vhost": "/",
"durable": true,
"auto_delete": false,
"arguments": {
"x-queue-type": "classic"
}
},
{
"name": "seelanstyres.updatetyre.orderservice.queue",
"vhost": "/",
"durable": true,
"auto_delete": false,
"arguments": {
"x-queue-type": "classic"
}
},
{
"name": "seelanstyres.deleteaccount.orderservice.queue",
"vhost": "/",
"durable": true,
"auto_delete": false,
"arguments": {
"x-queue-type": "classic"
}
},
{
"name": "seelanstyres.updateaccount.orderservice.queue",
"vhost": "/",
"durable": true,
"auto_delete": false,
"arguments": {
"x-queue-type": "classic"
}
}
],
"exchanges": [
{
"name": "exchange.seelanstyres.deleteaccount",
"vhost": "/",
"type": "fanout",
"durable": true,
"auto_delete": false,
"internal": false,
"arguments": {}
},
{
"name": "exchange.seelanstyres.updateaccount",
"vhost": "/",
"type": "fanout",
"durable": true,
"auto_delete": false,
"internal": false,
"arguments": {}
},
{
"name": "exchange.seelanstyres.updatetyre",
"vhost": "/",
"type": "fanout",
"durable": true,
"auto_delete": false,
"internal": false,
"arguments": {}
}
],
"bindings": [
{
"source": "exchange.seelanstyres.deleteaccount",
"vhost": "/",
"destination": "seelanstyres.deleteaccount.addressservice.queue",
"destination_type": "queue",
"routing_key": "",
"arguments": {}
},
{
"source": "exchange.seelanstyres.deleteaccount",
"vhost": "/",
"destination": "seelanstyres.deleteaccount.orderservice.queue",
"destination_type": "queue",
"routing_key": "",
"arguments": {}
},
{
"source": "exchange.seelanstyres.updateaccount",
"vhost": "/",
"destination": "seelanstyres.updateaccount.orderservice.queue",
"destination_type": "queue",
"routing_key": "",
"arguments": {}
},
{
"source": "exchange.seelanstyres.updatetyre",
"vhost": "/",
"destination": "seelanstyres.updatetyre.orderservice.queue",
"destination_type": "queue",
"routing_key": "",
"arguments": {}
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
management.load_definitions = /etc/rabbitmq/definitions.json
Loading

0 comments on commit 9619457

Please sign in to comment.