THỰC CHIẾN XÂY DỰNG KIẾN TRÚC DỰ ÁN MICROSERVICES VÀ TRIỂN KHAI PRODUCT SERVICE (PHẦN 2)

THỰC CHIẾN XÂY DỰNG KIẾN TRÚC DỰ ÁN MICROSERVICES VÀ TRIỂN KHAI PRODUCT SERVICE (PHẦN 2)

Long Nguyen

THỰC CHIẾN XÂY DỰNG KIẾN TRÚC DỰ ÁN MICROSERVICES VÀ TRIỂN KHAI PRODUCT SERVICE (PHẦN 2)

Cài đặt môi trường làm việc cho dự án microservices với docker, xây dựng cấu trúc ban đầu cho dự án, triển khai logging và product service, containerize cho product.service.

THỰC CHIẾN XÂY DỰNG KIẾN TRÚC DỰ ÁN MICROSERVICES VÀ TRIỂN KHAI PRODUCT SERVICE (PHẦN 2)

Xin chào mọi người, chúc mọi người một ngày cuối tuần vui vẻ. 

Tiếp theo series thực chiến Microservices ở phần 1 tổng quan về hệ thống Microservices.
(Tổng quan về Microservices phần 1)

Hôm nay mình sẽ tiếp tục phần 2 đi vào phần thực hành xây dựng kiến trúc dự án Microservices và triển khai Product Service. Hi vọng được thảo luận cùng anh em. Không để mọi người chờ lâu, cùng bắt đầu nào.

1. Giới thiệu tổng quan về dự án Microservices

  • Dự án này mình sẽ làm về một hệ thống bán hàng gồm các nghiệp vụ như quản lý khách hàng, sản phẩm, đặt hàng, tính toán tồn kho… Từng phần trong hệ thống đã được vẽ ở hình trên và giải thích tổng quan ở bên dưới.

    Toàn bộ Source code mình đã đưa lên github, anh em có thể lấy về tham khảo: https://github.com/TechMarDay/aspnetcore-microservices
     
  • ApiGateway giống như một cổng đứng chặn ở giữa ClientApps với các services. Đóng vai trò như một router giúp routing lại các url. 

    Ví dụ: ta có Product.API với url: 5002, Ordering.API với url: 5005. Qua ApiGateWay thì khi client app cần gọi api từ Product hay Ordering chỉ cần giao tiếp qua 1 cổng url: 5000. Đồng thời ApiGateway đóng vai trò giúp loadbalancer giúp cân bằng tải giữa các request. Thậm chí cache được luôn dữ liệu. Khi nào triển khai tới phần ApiGateway với Ocelot mình sẽ đi vào chi tiết.
     
  • WebStatus Healthcheck để kiểm tra các services hoạt động tốt hay không.
     
  • Tiếp theo là các services với các database riêng. Ví dụ như ở hình trên, anh em thấy có 2 database SQL Server nhưng 2 database này là riêng biệt cho 2 services khác nhau.
     
  • Product.API dùng .NET 6 với MySql để xây dựng. Còn Customer.API thì mình dùng minimal api - một feature mới của .NET 6.
     
  • Basket.API thì dùng .NET 6 api với Redis. Dùng Redis bởi vì giỏ hàng chỉ cần lưu trữ tạm thời nên mình dùng Redis để cache lại. Ví dụ dữ liệu giỏ hàng này không cần phải lưu trữ quá lâu: tầm 5h, 24h không thanh toán thì sẽ hủy giỏ hàng.
     
  • Ordering.API thì mình dùng Clean Architecture để triển khai với database SQL Server.
     
  • Invenory.API thì dùng để tính toán sản phẩm tồn kho. Sau khi tính toán tồn kho sẽ gửi message lên RabbitMQ. Sau đó Product.API sẽ consume message để tự động update vào field tồn kho của Product.
     
  • Background.Job để xử lý những tác vụ chạy nền như xóa dữ liệu rác, chạy báo cáo tuần, tháng…
     
  • Cuối cùng là Email.Service để gửi mail.

2. Cài đặt môi trường

  • Để chạy docker compose mọi người mở Developer PowerShell trong Visual Studio lên và chạy lệnh sau:

    cd src

  docker-compose -f docker-compose.yml -f   docker-compose.override.yml up -d --remove-orphans

  • Lưu ý phải cd đến thư mục src bởi vì hai 2 files composes nằm trong thư mục này. Còn lúc mở visual studio lên thấy nằm trong thư mục Solution Items chỉ là thư mục ảo.
  • Sau khi chạy lên ta mở Docker desktop để kiểm tra các container đã chạy thành công chưa:

  • Ngoài ra ta có thể cài Portainer để dễ dàng quản lý các tài nguyên trong dockers (images, containers, networks, volumess,...) Để cài đặt ta vào Extension và chọn install Portainer.

3. Giới thiệu về cấu trúc dự án

  • Thư mục Solution Items sẽ chứa docker-composes và các file về thông tin dự án cũng như version.
     
  • Tiếp theo là thư mục BuildingBlocks sẽ chứa các project:
    • Common.Logging: Quản lý việc ghi log cho toàn bộ các services và applications trong hệ thống.
    • Contracts: Quy định những contract cần tuân thủ, ta sẽ định nghĩa các interfaces dùng chung và các domain abstract class…
      EventBus.Messages để xử lý các message trong hệ thống. Ở đây chúng ta sẽ dùng RabbitMQ.
    • Infrastructure là phần hạ tầng.
    • Shared chứa các model, constants và các ultil helper,... dùng chung cho cả hệ thống.
       
  • Tiếp theo là thư mục Services sẽ chưa toàn bộ services:
    • Product.API: service để quản lý sản phẩm.
    • Inventory.Product.API: service quản lý sản phẩm tồn kho.
    • Ordering.API: service quản lý việc đặt hàng.
    • Basket.API: service quản lý giỏ hàng.
    • Customer.API: service quản lý khách hàng.
    • ScheduledJob/Hangfire.API: service để làm các background job như xóa dữ liệu rác, report....
       
  • Tiếp theo là thư mục WebApps: Hiện tại chỉ có project WebHeathStatus để check status các services. Sau này khi phát triển sẽ thêm các project khác.
     
  • Tiếp theo là thư mục ApiGateways chứa project OcelotApiGw để cấu hình api gateway cho hệ thống.
     
  • Cuối cùng là thư mục tests: để viết unit test cho hệ thống.
     

Note: Ở đây mình chỉ giới thiệu sơ về tổng quan cấu trúc dự án chứ không đi vào cụ thể từng phần riêng. Ở các bài sau mình sẽ đi vào chi tiết và kèm theo code thực hành cho từng phần cụ thể.

4. Cấu hình Logging cho các services

  • Ở đây mình sẽ dùng Serilog để cấu hình Logging cho hệ thống. Nếu anh em nào chưa biết về serilog có thể tham khảo link dưới đây: How to Add logging to ASP.NET Core using Serilog - .NET6
  • Thông thường khi làm ta sẽ cấu hình và ghi log cho từng project, từng service nhưng nếu ta làm riêng từng phần khi muốn thay đổi code về logging thì sẽ phải đổi từng chỗ và sẽ không đồng bộ giữa các services. Vì vậy nên trong hệ thống microservices mình đã tạo ra một Project Common.Logging với kiểu là Library. Việc ghi log rất quan trọng đặc biệt là khi lên production khi gặp lỗi ta không thể nào debug trực tiếp trên code, mọi việc dò lỗi chỉ có thể dựa vào log để xem lỗi xảy ra ở đâu.

  • Để sử dụng Serilog anh em mở NuGet và cài đặt 3 packages:
    • Serilog.AspNetCore
    • Serilog.Enrichers.Environment
    • Serilog.Formatting.Compact

  • Tạo mới static class Serilogger với nội dung như bên dưới. Với cấu hình outputTemplate như dưới ta có thể biết rõ log tại thời gian nào, level, sourceContext và nội dung cụ thể.

  • Add Log cho Product.API. Ta add reference Common.Logging cho Product.API services

  • Cấu hình Serilog ở Program.cs. Ta gọi đến method Extension ở Common.Logging để cấu hình Log

  • Tương tự ta cũng thêm Logging cho các services khác.

 

5. Xây dựng Product.API service - Confiugration, Entities, Repository, UnitOfWork

  • Ở đây mình sử dụng Mysql Workbench để kết nối với database mysql: localhost:3307. Anh em nào chưa cài có thể vào link dưới để cài Mysql Workbench: Download MySQL Workbench

  • Thêm connection string vào file appsettings.json

"ConnectionStrings":{"DefaultConnectionString": "server=localhost;port=3307;database=ProductDB;user=root;[email protected]" }

  • Trong class ServiceExtension ta viết method ConfigureProductDbContext để connect Product.API đến ProductDB (mysql)

  • Ở folder Entites trong Product.API mình sẽ thêm class CatelogProduct.cs gồm các thuộc tính cơ bản sau. Sau này khi làm đến các phần sau ta sẽ bổ sung thêm các thuộc tính sau.

  • Tiếp theo vào project Contracts và thêm các class sau. Các class này chứa các thông tin chung và các field metatdata mà bất kỳ entity nào cũng có nên ta sẽ tách riêng ra thành các abstract class và để Entity cụ thể kế thừa lại abstract class này.

  • Interface IUserTracking thì tạm thời ta chưa đụng tới. Sau này làm tới service Customer.Api ta sẽ sửa lại

  • Quay lại project Product.API mình sẽ thêm vào class ProductContext.cs ở folder Persistence. Trong class này ta sẽ override lại method SaveChangesAsync để tự động update các thông tin CreatedDate, LastModifiedDate khi có data thay đổi.

  • Add migrationupdate database cho Product.API. Mở Package Manager Console và chạy lệnh sau. Sau khi chạy xong ta sẽ có file migration.

  • Chạy lệnh update-database để run migration vừa tạo ra.

  • Kiểm tra thông tin ProductDB ở Mysql Workbench ta thấy ProductDB đã tạo thành công và có table Products với các columns đúng thông tin như ta thiết lập ở Entity Product.

  • Seed data cho Products table. Viết method SeedProductAsync sau đó ta sẽ gọi phương thức này ở program.cs


  • Run Product.API và kiểm tra sau khi seed data thành công.

  • Xây dựng Repository và UnitOfWork. Trong Project Contracts ta thêm vào 2 interfaces IUnitOfWork IRepositoryQueryBaseAsync

  • Trong project Infrastructure ta thêm 2 class RepositoryBaseAsync UnitOfWork kế thừa từ 2 interfaces trên.

  • Product.API service ta thêm interface IProductRepository và class ProductRepository kế thừa RepositoryBaseAsync

  • Tạo ProductController và viết api GetProducts()

  • Run thành công và lấy được thông tin products

6. Xây dựng các API CRUD cho Product.API service

  • Product.API mình sẽ cài đặt 2 package về AutoMapper:

  • Sau đó inject AutoMapper vào ProductController

  • Tạo mapper profile và khai báo ở service extension:

7. Containerize cho Product.API service

  • Để containerize cho Product.API service ta click chuột phải vào Project Product.API và chọn DockerSupport.

  • File Docker sẽ được tạo ra và ta chỉnh sửa nội dung như sau:

Giải thích:

  • Viết câu lệnh FROM để lấy image: FROM mcr.microsoft.com/dotnet/asp.net:6.0 AS base
     
  • Thư mục muốn làm việc trong docker là app: WORKDIR /app
  • Lấy image sdk để làm phần build: FROM 
    mcr.microsoft.com/dotnet/sdk:6.0 AS build
     
  • Thư mục làm việc là src: WORKDIR /src
     
  • Copy project Product.API: COPY ["Services/Product.API/Product.API.csproj", "Services/Product.API/"]
     
  • Tiếp theo 1 số references mà phải đưa vào chung:
    • COPY ["BuildingBlocks/Common.Logging/Common.Logging.csproj", "BuildingBlocks/Common.Logging/"]
    • COPY ["BuildingBlocks/Contracts/Contracts.csproj", "BuildingBlocks/Contracts/"]
    • COPY ["BuildingBlocks/Infrastructure/Infrastructure.csproj", "BuildingBlocks/Infrastructure/"]
    • COPY ["BuildingBlocks/Shared/Shared.csproj", "BuildingBlocks/Shared/"]
       
  • Chạy lệnh dotnet restore để restore về project chính Product.API
     
  • Copy tất cả vào Product.API
    • COPY ..
    • WORKDIR "src/Services/Product.API"
       
  • Chạy câu lệnh build với config Release và output vào folder app/build. Hiện tại ta đang ở folder workdir là build: RUN dotnet build "Product.API.csproj" -c Release -o /app/build
     
  • Publish project: FROM build AS publish RUN dotnet publish "Product.API.csproj" -c Release -o /app/build
     
  • Copy toàn bộ qua thư mục publish. Câu lệnh EntryPoint sẽ chạy file dll để run project

  • Tiếp theo ở file docker-compose.yml ta sẽ chỉnh như sau để tạo image từ docker file ở folder Services/Product.API

  • Tạo container từ image và cấu hình cho container. Lưu ý chuỗi connection string sẽ trỏ đến product productdb và ta khai báo phụ productdb phụ thuộc vào container product.api

  • Chạy câu lệnh để build: docker-compose -f docker-compose.yml -f docker-compose.override.yml up -d --remove-orphans --build

  • Sau khi build thành công ta vào portainer để xem container product.api vừa tạo ra:

  • Có thể xem các thông tin của container product.api

8. Tổng kết


Vậy là chúng ta đã hoàn thành phần 2 trong series thực chiến Microservices. Đã xây dựng được cấu trúc dự án, thiết lập môi trường với docker, triển khai Product service và thành công Containerize Product.API service. Ở phần 3 chúng ta sẽ triển khai customer service (.NET 6 , Minimal api và PostgresSQL).
Cảm ơn mọi người đã xem bài viết. Chúc mọi người một cuối tuần vui vẻ. Nếu có thắc mắc về các phần trong bài này mọi người có thể inbox qua mail: [email protected]. Mình sẽ giải đáp thắc mắc trong tầm hiểu biết. Cảm ơn mọi người.

saigon_technology

Related articles

Build Customer service (.NET, Minimal API, and PostgreSQL)

calendar

19 May 2023

time

5 mins read

Tổng quan về Microservices (Phần 1)

calendar

16 Dec 2022

time

8 mins read

Implement a distributed transaction in microservices software system using Saga pattern

calendar

19 May 2023

time

9 mins read

career_saigon_technology

Ho Chi Minh (Headquater)

location_pin

2nd & 3rd Floor, M.I.D Building, 02 Nguyen The Loc Street, Ward 12 Tan Binh District, Ho Chi Minh City, Vietnam

DMCA.com Protection Status

Quick Links

Opening Jobs

About us

Life at saigontechnology

Blog

Contact Us

PRIVACY POLICY

Follow Us

saigontechnology-great-plage-to-work-partner
saigontechnology-microsoft-partner
iso_9001iso_27001
sao_khue
50_leading

© Copyright 2022 by STS Software Technology JSC, Leading Software Outsourcing Company in Vietnam. All Rights Reserved.