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.
Click Download Source On GitHub button to go to the code repository and clone it.
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. If you follow my learning path tutorial; ASP.NET Web API & Angular 10 Clean Architecture, 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 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 the RabitMQ queue, receives the user purchased courses and saves them in 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 StudentCourseManagment 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 interacts with the Application projects containing business logic through mediator.
- Application: The Application projects implements the CQRS principles i.e. query to load the data and commands for rest of operation.
- Domain: Contains the entity classes, repositories and unit of work interfaces.
- Persistence: Contains the reposity and unit of work impletation 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.
Hello thnx great aticle,
i reseive a message localhost refused to connect, and i cant find the reson.
do you have any idea
thnx
Can you check your local port is not already occupied? Try using another port.
Very Great Article with basic functionality… enjoying..
Thanks Adi.
Can u explain how to run the project stepwise?
It is pretty straightforward; please see the GitHub repo documentation:
https://github.com/fullstackhub-io/StudentCourseManagement
Let me know if you get any errors.