Notes:
- If you can't view markdown files with images in your editor of choice, i suggest using Visual Studio Code and click the preview button:
- If grafana is not available it's and issue with permissions. Have tried to configure volumes for the docker-compose, but i don't have access to computer running macOS...
To be able to run this project you must download Docker Compose.
If you are running Windows i would advice to download Docker Desktop: https://www.docker.com/products/docker-desktop/
After download to ensure Docker Compose was installed correctly, check its version:
docker-compose --version
Ensure that the docker-compose version is atleast v2 or above.
If you are running macOS the easiest way is to install from the Github:
1 - Open a terminal and run the following command to download Docker Compose:
sudo curl -L "https://github.com/docker/compose/releases/download/v2.3.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
2 - Run the following command to apply executable permissions to the binary:
sudo chmod +x /usr/local/bin/docker-compose
3 - To ensure Docker Compose was installed correctly, check its version:
docker-compose --version
If you are running Linux the easiest way is to install from Github:
1 - Open a terminal and run the following command to download Docker Compose:
sudo curl -L "https://github.com/docker/compose/releases/download/v2.3.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
2 - Run the following command to apply executable permissions to the binary:
sudo chmod +x /usr/local/bin/docker-compose
3 - To ensure Docker Compose was installed correctly, check its version:
docker-compose --version
In the '\src\MiniECommerce' directory run the following command:
docker-compose up
If there are errors present, try running the command again, or run the following commands in sequence:
docker-compose rm
docker-compose up
When the project is up and running, you can navigate to the web application at: http://localhost:50010/
Note: When starting the application and entering the URL(for the app) you will get prompted for Google Login. Use these credentials (if you'd like):
Username/Email: candidate2038@gmail.com
Password: Kristiania1914
If you are using Docker Desktop it should look like something this:
Or use "docker ps" in the command line:
You can use CTRL + Z, or CTRL + C, any EOF command for your operative system.
In this document, I have not specifically addressed unit testing. This is based on the understanding that, as of 2023, unit testing is a standard and essential practice in software development
The primary objective of this project is to develop an e-commerce website. In line with this goal, i've chosen a microservices-based architecture to ensure high performance and flexibility. The system comprises four main services: product, basket, order, user, and purchase, each tailored to specific use cases defined by their names. From the company's perspective, this system empowers administrators to view and manage orders, baskets, and products effectively. For the end-users, the solution offers a straightforward frontend, enabling them to browse products, add items to their cart, place orders, and check out. I've also incorporated features for viewing order history.
As a user, I want to easily explore the range of products offered by the company. To streamline this process, I'd appreciate efficient filters and search functionality, ensuring I can quickly find specific products and categories. In today's fast-paced world, efficiency is crucial; otherwise, I might switch to a different vendor.
As a user, I'd like the ability to add products to my shopping cart as I browse the catalog. However, I don't always wish to place the order immediately. Sometimes, I prefer to accumulate items and review the total cost. Therefore, I suggest implementing a shopping cart where I can see the total and check stock availability for the products I've added. For convenience, I'd also appreciate the option to save delivery and invoice addresses in my profile settings.
As a user, I expect personalized product suggestions based on my previous orders. For example, if I primarily purchase technology products from the company, I don't want to sift through unrelated items like "clothing". These suggestions should be prominently displayed when I enter the website, given my previous purchase history. If there is no purchase history present, i would suggest to have the most bought products apperaring.
As an administrator of the e-commerce platform, I want to access a dashboard with real-time operational metrics, So that I can quickly identify trends, customer behavior, and performance issues to improve decision-making and platform efficiency.
As an administrator of the e-commerce platform, I want a comprehensive UI for managing products, customer orders, and shopping baskets, So that I can efficiently provide customer support, handle order modifications, and manage the storefront, ensuring a seamless shopping experience for users and maintaining operational efficiency.
Based on the user stories outlined above, several key requirements emerge. The most critical aspects revolve around addressing user-related needs. To meet these requirements, I must gather and manage data effectively. As a starting point, I should focus on the administrative functions.
- Managing products
- Managing orders
- Managing baskets (for customer support)
- Collect simple metrics from the web app
- User login
- Product browsing
- Adding products to the basket
- Placing orders
- Viewing order history
- Profile settings
The microservices architecture requires seamless communication between services, facilitated through a central gateway. This approach supports client-side load balancing and the identification of dependencies between services. The primary services in this project include user-service, basket-service, order-service, product-service, and purchase-service, all of which interact with the gateway.
The product service will handle querying of products from the user's perspective. But there will also be different CRUD functionality for the administration to manage their products.
The order service will handle queries and commands from the user's perspective. This will be things like, starting an order, filling in its details, see orders to confirmation, overview of paid orders and more. Upon different interaction's this service will publish different events, such as: order-started, order-confirmed, order-updated and order-delivered.
The purchase service will have a "dummy" implementation. When the user proceeds to checkout this service will be called and just return "Ok, the purchase went through".
The user service will contain different information about the users(customers). Such as delivery address, invoice address with more.
The basket service will be an in-memory service. This means that when the service is restarted the data will be lost. The service will listen on different events published by the order service to know when to clear the basket.
From a technical view the application will be made in a web framework called Blazor. Blazor has multiple rendering options, but I will go for server-side rendering. Over to specification, there will be two perspectives in the frontend. One will be the customer and the other will be the administration.
The administration will be able to:
- Create and change orders on the customer's behalf
- Add products to the basket on the customer's behalf
- Add/Update the product catalog
The customers will be able to:
- Manage information such as delivery address and invoice address
- Browse the product catalog
- Add/Remove/Increase/Decrease products in basket
- Start the order from the basket
- Overview of orders in progress
To get a better overview of customers visiting different pages of the frontend there is implemented some metrics. There metrics are registered through Prometheus and be visualized through Grafana.
During the development of my microservice-based e-commerce application, several architectural decisions and simplifications were made to streamline the development process and address the core requirements effectively. Below is a summary of these key decisions, along with the assumptions and simplifications that were applied.
Docker Compose was selected for orchestrating the microservices in the local development environment, driven by the need for a simplified setup process and efficient management of multiple service containers. To ensure that the solution was easily runnable on any machine, regardless of the operating system, I published the Docker images of our services to Docker Hub. This approach required an update to the Docker Compose file to reference these images directly from Docker Hub. Consequently, this change facilitated a smooth, system-agnostic deployment process, allowing assessors or users to run the application seamlessly on their machines without the need for a local build, thus enhancing the portability and accessibility of the application.
I chose Ocelot as the API gateway for its compatibility with Docker and .NET Core in my microservices architecture. Ocelot provides efficient routing, load balancing, and easy configuration - essential for directing traffic in the system. Its support for key functionalities like authentication and authorization, along with its lightweight nature, makes it an ideal choice for a streamlined and scalable microservice setup.
Stable Network Communication: It was assumed that the network communication between services and the message broker (RabbitMQ) would be stable and reliable in the development environment.
-
- The Purchase Service in this project features a simplified implementation with a single endpoint that returns a 200 OK status for any incoming request
-
- In a real-world scenario, this service would be more complex, handling various aspects of the purchasing process such as payment processing, order validation, and fraud checks. Additionally, it would implement robust security measures to safeguard against malicious requests and data breaches
-
- For user authentication, Google Authentication was integrated
-
- Real-World Application: In a production environment, a more comprehensive authentication strategy would likely be employed. This would typically involve supporting multiple identity providers to cater to a broader user base and ensuring a more flexible and secure authentication experience
You can reach the profile page by navigating to: http://localhost:50010/profile
The profile of the user contains some different fields:
- FullName
- DeliveryAddress
- DeliveryAddressPostalCode
- DeliveryAddressPostalOffice
- DeliveryAddressCountry
- InvoiceAddress
- InvoiceAddressPostalCode
- InvoiceAddressPostalOffice
- InvoiceAddressCountry
The user has the option to:
- Use dummy data, then save
- Manually enter data, then save
You can reach the products page by navigating to: http://localhost:50010/
The products page consits of some main elements:
- Filter line, Ability to filter between products, names and prices
- Grouping: Displays the products in the group they belong to
- Adding to cart: By clicking the '+' icon you can add a product to the shopping cart
Explanation of the points found in the image above:
-
- Navigates to the product catalog
-
- Generic search function
-
- Filter by categories
-
- Filter from price
-
- Filter to price
-
- Add to shopping cart
You can reach the basket page by navigating to http://localhost:50010/basket or adding a product to the basket.
To add a product to the basket go to the product catalog and click the '+' icon:
When clicking the '+' icon you will be redirected to the basket like so:
Explanation of what you can do next, referings to the points in the image
-
- Increase quantity of the item
-
- Decrease quantity of the item
-
- Continue shopping/go to product catalog
-
- Start the order process
To continue with this step, check the manual for the basket above.
When your basket looks ready for ordering proceed with clicking "Start Order".
As you see in the image above a message will displayed telling you "Order started". From here there are 3 proceeding steps:
- Fill in delivery address (delivery address from profile will be automatically suggested)
- Fill in invoice address (invoice address from profile will be automatically suggested)
- Pay for order (The purchase service does not do anything with the data, but just returns 200 - Ok)
When these three steps are completed you can continue shopping.
Skipping the steps to fill out the address, you will get to the last step, payment.
Payment will always execute as OK. Do not enter any personal information here.
When payment completed, you can either continue shopping or check your orders
You can reach the orders page redirection from basket, clicking the list-icon at the top or navigating to http://localhost:50010/orders
In the following image you can see three points that does the following:
-
- You can navigate to the orders by clicking this icon
-
- You can see your active orders
-
- You can see your historic orders
By clicking on an order you can see the order details
There are five options for the administrator:
- Create/Maintain products
- Order management
- Basket management
- Watch metrics in Prometheus
- Watch metrics with graphs in Grafana
The administrative section is placed in the footer of the website.
You can reach the product management page by clicking the link in the footer, or navigate to this uri: http://localhost:50010/product-management
Entering the page you got two options:
-
- Add a product
-
- Edit a product
To add a product enter the information in the fields and click save.
Same procedure editing a product.
You can reach the order management page by clicking the link in the footer, or navigate to this uri: http://localhost:50010/order-management
Entering the page you have an "Actions" button which can do three things:
-
- Set delivery address
-
- Set invoice address
-
- Set to confirmed
You can reach the basket management page by clicking the link in the footer, or navigate to this uri: http://localhost:50010/basket-management
Click on a user basket to assist them in the checkout.
After clicking on the basket you can see the items in the basket, but also:
-
- Add product to the basket
-
- Refresh the basket, incase the user has done some interactions
After clicking "Add product" you can click the following item to update the users basket. If the user refreshes the site now, the user will get the updated basket.
Available metrics:
- users_in_basket
- users_in_catalog
- users_ordering
You can reach the page by clicking the link in the footer, or navigate to this uri: http://localhost:9090/
When reaching the page it looks like this. In the search field you can search for the metrics listed at the top.
Available metrics:
- users_in_basket
- users_in_catalog
- users_ordering
You can reach the page by clicking the link in the footer, or navigate to this uri: http://localhost:3000/login
To sign in enter the following values:
- Username: admin
- Password: admin
It will prompt you to create a new password, but just click skip.
Tada! You are at the frontpage. Now click on the "Customers Overview" dashboard.
And there you go. Here you can design your own dashboard based on the metrics in the application.
This section is already included as a separate document named "PG3402 - Reflection - 2038.pdf"
RabbitMQ is a widely-used message broker that facilitates asynchronous communication in a distributed system, which is essential in a microservice architecture for decoupling services. It supports various messaging patterns, including publish/subscribe, which are crucial for building scalable and resilient systems.
- Decoupling of Services: RabbitMQ allows services to communicate without being tightly bound to each other, enhancing service independence and resilience
- Reliability and Consistency: It ensures message delivery even in cases of temporary service unavailability, preserving the consistency of operations across microservices
- Scalability: RabbitMQ effectively handles high throughput and can be scaled as the system grows
MassTransit is a lightweight service bus for building distributed applications using .NET. It acts as an abstraction layer over RabbitMQ, simplifying the development and maintenance of message-driven architectures.
- Ease of Use: MassTransit simplifies the integration with RabbitMQ, providing a more intuitive API for .NET developers
- Advanced Features: It offers features like saga coordination, scheduling, and support for various patterns that are beneficial in complex microservice interactions
- Better Error Handling and Monitoring: MassTransit provides enhanced error handling and monitoring capabilities, crucial for maintaining system health
Prometheus is a powerful monitoring tool that collects and stores metrics as time-series data, allowing you to monitor the health and performance of your microservices.
- Real-Time Monitoring: Prometheus's strong querying capabilities allow real-time insight into microservice performance
- Scalability and Reliability: It is designed for reliability and scalability, handling large volumes of data efficiently
Grafana is an open-source platform for monitoring and observability and integrates seamlessly with Prometheus to provide visualizations of the collected data.
- Data Visualization: Grafana allows you to create comprehensive dashboards that visualize metrics from Prometheus, making it easier to understand and respond to the data
- Alerting: Grafana's alerting features enable proactive responses to potential issues, ensuring quick resolution of problems