Microservices, as defined everywhere, are small, modular and independently deployable service and Docker containers helps to bundle the services and its dependencies, e.g., runtime, proxy server, etc. into a single unit which is then run in an isolated environment. In this article, we will go through the implemented solution where we have four microservices having loosely coupled architecture and the front end implemented in Angular 11. This is the basic course management microservices solution on docker containers where users can buy different courses and solutions contains users, courses, course baskets, and user course management APIs, and for now, we are using Docker Compose for running multiple dockers.
Let’s Start
As described in the Introduction, we have the following four APIs:
- User Microservice: This microservice provides User CRUD operations, i.e.,
Load
, Add
, Update
and Delete
users. In my other blogs on Code Project, etc. I described each and every detail of how to implement User Management solution using the CQRS principle, Mediator, Repository, and Unit of Work Design Patterns. The underlying database is a SQL Server and we are using Dapper micro ORM for database operations. - Course Microservice: This microservice has Course Management CRUD operations and follows the same architecture as User API solutions except we can add, update, delete and load course information that users can purchase.
- Course Basket Microservice: This microservice temporarily stores the user courses in the Redis database that the user adds to his/he basket and is willing to purchase.
- Student Course Microservice: Once the user performs the purchased courses action, the user courses move from Redis to RabitMQ queue. This microservice subscribed to the RabitMQ queue receives the user purchased courses and saves them in the database.
Communication Between Services
Since the Student Course microservice needs to communicate to User and Course microservices, one way is to call these services manually but that certainly creates the coupling among the services. The other solution is a publisher-subscriber pattern, where one service publishes the data to some queue and all services who subscribed to that queue being notified of the data arrival to consume it the way it is configured. The RabbitMQ package is a famous message broker that we are using in this solution.
API Gateway
API Gateway provides the one-stop-shop for all microservices, instead of directly calling the microservices, we can configure the downstream and upstream APIs in configuration file, e.g., using the Ocelot API Gateway package. There are a lot of benefits of API Gateway, e.g., keep the microservices private and only expose API Gateway, implement authentication logic at API Gateway only instead of replicating it in each microservice, caching, handling throttling, etc.
In-memory Data Store
For the Course Management solution, we are storing the checked-out course in an in-memory data source using the Redis package which is a fast, reliable and scalable solution to store the temporary data.
Front End Application
For Course Management applications, the front-end is implemented in Angular 11 where we are invoking all APIs through API Gateway, there is a User and Course Management page along with a Course checkout and buy course page. Since this is not an Angular course, you won’t see a lot of great architecture or design implemented. Read Angular-related articles here.
All projects are on Docker containers using their corresponding docker images, e.g., ASP.NET Core Runtime, Node, Redis and RabbitMQ.
Let’s Understand Course Management Solution
Now that we understand the high-level architecture and business level of solution, let’s briefly understand the projects in solutions. Clone the StudentCourseManagement solution from Github.
User & Course Management
User and Course projects are straightforward projects to add, update, delete and load the users and courses. There are two projects folders, db and src where db contains the database creation script and docker file. The src folder contains the four projects:
- User & Course API: Contains the APIs that interact with the Application projects containing business logic through a mediator.
- Application: The Application projects implement the CQRS principles, i.e., query to load the data and commands for the rest of the operation.
- Domain: Contains the entity classes, repositories, and unit of work interfaces.
- Persistence: Contains the repository and unit of work implementation to perform database operations.
I wrote very detailed articles to explain the clean architecture implemented in User and Course Management projects. Clone the repository and find the learning path here.
Browse http://localhost/swagger after compiling and running the solution to test the User APIs.
Browse http://localhost:90/swagger after compiling and running the solution to test the Course APIs.
Course Basket
Course Basket temporarily stores the selected user and their selected courses in Redis.
Registration Queue
Registration Queue is a class library project that implements the message queue logic using the RabbitMQ package. As we learned earlier, to keep the microservice loosely coupled, it is a cool idea to use the publisher-subscriber pattern where one microservice can subscribe to queue other microservice publish the data. The Course Basket project uses this class library to publish the user and their selected courses. The Student Course
project that we are going to look into next subscribes to the queue and saves that info in the database.
Student Course
This is the last project in a Course Management hierarchy that keeps looking for data in the RabbitMQ queue and triggers the Save user courses API if received any data. You can look into EventBusRabbitMQConsumer
class in StudentCourse.Application
project how data received event is triggering and calling the AddStudentCourseCommand
to save the information.
Browse http://localhost:100/swagger after compiling and running the solution to test the Student Course APIs.
API Gateway
API Gateway project is using the Ocelot package to provide the unified entry for all microservices. Check the ocelot.json file where we defined the upstream and downstream APIs. The SCM.Web
interacts with upstream APIs instead of directly interacting with microservices. The API Gateway base URL is http://localhost:130 so all microservices are accessed through http://localhost:130, e.g., http://localhost:130/Course, http://localhost:130/User, http://localhost:130/CoursesBasket, etc.
SCM (Student Course Management) Web
This is a front-end application developed in Angular 11 where users can perform CRUD operations on User and Courses, add the courses against users in the basket (cart) and purchase the courses in the cart. Please remember, this is not the best Angular Architecture or not a production-ready application, you can view the Clean Architecture solution that really has a clean Angular project that also supports rapid development using Swagger generated HTTP Client and services against APIs (Controller’s actions).
Browse http://localhost:150 after compiling and running the solution to browse the front-end application.
History
- 3rd August, 2021: Initial version