Bài viết này của tác giả chủ yếu để tác giả học, viết ra thì sẽ học được nhiều hơn là chỉ đọc
Upstream: Request gửi từ Client tới GateWay API
DownStream: Request từ GatewayAPI tới 1 Service
Đại khái là Client sẽ gửi 1 request, request này đi qua thằng gateway, thằng gateway lấy dữ liệu từ 1 service (API) khác
BÌnh thường thằng Client (Postman) truy cập API sẽ dùng localhost:12345, nhưng qua thằng gateway, nó sẽ đổi thành localhost:5000
Ví dụ có 2 thằng api, 1 thằng cổng :12345, 1 thằng :54321, Postman muốn truy cập cả 2 thì phải dùng cả 2 cổng, nhưng giờ có thằng gateway này, sẽ gộp 2 cổng kia lại, chuyển về thằng :5000, vì vậy thằng Postman chỉ cần gọi tới thằng :5000 là đc
Thằng Gateway này là Ocelot API Gateway
SO SÁNH MÔ HÌNH MICROSERVICE VÀ MONOLITH
MONOLITIC | MICROSERVICE |
---|---|
Một solution xử lý tất cả các nghiệp vụ, logic | Mỗi Service thực hiện một chức năng nhất định |
Chỉ một Database | Mỗi service có thể có một database khác nhau |
Một project là một ngôn ngữ lập trình duy nhất | Mỗi service có thể là một ngôn ngữ lập trình/công nghệ khác nhau |
Solution sẽ được triển khai tại một server nhất định và duy nhất, | Mỗi service có thể deploy ở bất cứ server nào mà vẫn có thể call tới nhau |
Services will be tightly coupled to the application itself. | Losely Coupled Architecture. |
GETTING START
Trong bài viết này, mình sẽ sử dụng ASP.NET Core 3.1 Web API
Khởi động visual studio, tạo một Blank Solution, bạn có thể tìm từ khoá blank, sau đó chọn Blank Solution, bấm next
Hãy chắc chắn bạn sử dụng ASP.NET Core 3.1 hoặc phiên bản cao hơn như .NET 5, .NET 6
Tiếp theo, đặt tên cho project, ở đây mình sẽ đặt là Microservices.WebApi
Visual studio sẽ tạo một Solution rỗng cho bạn, Tiếp theo tạo mới một Folder trong solution, đặt tên nó là gì cũng đc, mình đặt là Microservices. Trong folder này, ta sẽ Add tất cả các project service, mỗi project sẽ là một service để thực hiện một chức năng nhất định. CLick chuột phải vào Folder vừa tạo, chọn Add a new Project, Đầu tiên tạo Product Microservice trước. Project này sẽ là WebAPI, Mình sẽ đặt tên nó là Product.Microservice.
Tương tự, ta tạo một service tên là Customer.Microservice (Tên ở đây đặt như nào cũng đc, mỗi project sẽ là một service)
Tiếp theo, một Project khá quan trọng, nó sẽ là cầu nối, kếtt nối tất cả các service với nhau, đặt tên nó là Gateway.API. Project này sẽ là project rỗng, ta sẽ cấu hình nó sau
Kết quả, Solution của bạn sẽ trông như sau:
Về cơ bản, tất cả các chức năng liên quan tới quản lý khách hàng, ta sẽ giao cho Service(Project) Customer quản lý, mọi thứ liên quan tới Sản phẩm sẽ do Service Product quản lý. Người dùng phía máy khách (Trình duyệt) sẽ truy cập vào API Gateway để có thể sử dụng các dịch vụ của Product và Customer thông qua API Gateway's Url, máy khách sẽ không thể truy cập tới Customer và Product nếu không thông qua API Gateway
Cài đặt Microservices
Tiếp theo, mình sẽ tạo các chức năng cơ bản CRUD (Create/read/update/delete) cho từng service
Sử dụng Entity Framework Core để truy nhập database. Mình sẽ tự hiểu là các bạn biết code các chức năng CRUD cho một bảng trong cơ sở dữ liệu nào đó rồi, sử dụng EF Core, thực hiện viết API gồm các phương thức Get/Get(id)/Post(object)/Put(object)/Delete(id) . Mĩnh sẽ skip bước này, nếu bạn nào chưa biết thì hay bỏ qua bài viết này và tìm hiểu về vấn đề đó trước, sau đó quay lại đây đọc sau cũng chưa muộn. Mình cũng gợi ý bạn sử dụng Swagger để quản lý api dễ dàng hơn
Nếu bạn muốn thực hiện chức năng CRUD như trên, mình sẽ gợi ý bạn đọc bài viết này, tuy nhiên sẽ toàn tiếng Anh thôi, có thời gian mình sẽ dịch sau
1. ASP.NET Core căn bản sử dụng Entity Framework Core
2. Kiến trúc CQRS và MediatR trong .NET Core
Oke, tiếp nhé, để thiết thực hơn về tác dụng của Microservices, mình sẽ sử dụng 2 database khác nhau, thậm chí là mỗi database một server khác nhau cho từng service. Sau khu tạo các phương thức CRUD, swaggers của mình sẽ như sau:


Bạn hay để ý rằng, mỗi service sẽ có URL khác nhau, 2 service sẽ là như này khi chưa thông qua gateway, vì là 2 url khác nhau nên khá bất tiện đúng ko, chúng ta sẽ gộp chúng về 1 url trong bước tiếp theo
Giới thiệu về Ocelot API Gateway
Ocelot là một mã nguồn mở API Gateway của nển tảng .NET/Core. Ocelot sẽ tích hợp các đường dẫn mà máy khách gửi đi, và chuyển hướng nó tới từng service nhất định
Oclot cũng đc sử dụng bới một số công ty công nghệ lớn, phiên bản mới nhất của Oclot chỉ hỗ trợ .NET Core 3.1 trở lên, ko hỗ trợ .net framework. Việc tích hợp Ocelot vào project của bạn khá đơn giản, bằng cách cấu hình trong file JSON
Upstream và Downstream là hai khái niệm bạn cần nắm bắt và hiểu rõ.
Như để cập ở đầu bài viết, Upstream là Request được gửi lên từ người dùng, gửi tới API Gateway. Downstream là các request (yêu cầu) gửi từ API Gateway tới Từng service.
Mô hình Upstream/Downstream đơn giản như sau:

Mô hình này sẽ giúp bạn hiểu hơn, API Gateway có cổng là 5000. Trong khi Microservice có cổng là 12345. Bây giờ người dùng sẽ không thể truy cập trực tiếp vào cổng 12345 mà chỉ được phép vào 5000. Như vậy người dùng sẽ gửi Request vào côngtr 5000, ví dụ người dùng truy cập localhost:5000/api/weather để xem thời tiết thế nào. Những gì Ocelot làm sẽ là nhận Request từ người dùng và gửi một HTTP Request khác tới Microservice, Microservice sẽ phản hồi lại Ocelot một Response, có thể dưới dạng JSON, sau khi Ocelot Gateway nhận được Response từ Microservice, Sẽ bắn lại cho người dùng. Người dùng sẽ chỉ biết về Upstream là đường dẫn localhost:5000. Còn localhost:12345 sẽ là Downstream mà chỉ API Gateway mới biết
Bằng cách này, Ocelot Gateway có thể điều hướng các request từ người dùng tới service. Tiếp theo mình sẽ cấu hình các route để Ocelot Gateway có thể điều hướng tới các Services
Một số đặc tính đáng chú ý của Ocelot
- Routing the Incoming Request to the required Microsrvice
- Authentication
- Authorization
- Load Balance for Enterprise Applications.
Xây dựng Ocelot API Gateway
Chúng ta cùng chuyển hướng tập trung vào project Gateway.WebApi đã tạo ở trên
Đầu tiên hãy tải package Ocelot
Install-Package Ocelot
Chạy câu lệnh này trong PM (Package management Console) hoặc bạn có thể vào Nuget Package tìm Ocelot và install về, cứ tải bản mới nhất ấy
Tiếp theo ta sẽ cấu hình Ocelot, mở file Program.cs trong project Gateway.WebApi và sửa hàm CreateHostBuilder thành như sau:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup();
})
.ConfigureAppConfiguration((hostingContext, config) =>
{
config
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);
});
Dòng gần cuối, Ocelot sẽ đọc file oclot.json, file này sẽ cấu hình đường dẫ để trỏ tới các services. Trước đó, ta cần cấu hình Ocelot Middleware cho project
Chuyển tới file Startup.cs
Trong hàm ConfigureServices hãy thêm 1 dòng này
services.AddOcelot();
Tiếp theo, chuyển tới hàm Configure
await app.UseOcelot();
Thêm dòng này vào cuối hàm
Cấu hình Ocelot Routes
Một trong những điều quan trọng nhất trong bài viết này, là cấu hình cho Ocelot để điều hướng Request từ khách hàng tới Microservice hay còn gọi là Upstream/Downstream như trên
Hãy bắt đầu với Product Microservice. Giả sử người dùng muốn lấy danh sách khách hàng thông qua API Gateway
Đầu tiên, trong swagger UI của Product Microservice, Hãy thêm một vài Product vào, sử dụng phương thức post ấy. Sau đó sử dụng phương thức Get để lấy ra danh sách Product vừa thêm vào để làm mẫu

Chú ý đường dẫn URL của Product hiện tại nhé
Tiếp theo tạo file ocelot.json như đã cấu hình ở trên File Program ấy. File này sẽ chứa nội dung để cấu hình Ocelot, nội dung file sẽ như sau:
{
"Routes": [
{
"DownstreamPathTemplate": "/api/product",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44337
}
],
"UpstreamPathTemplate": "/gateway/product",
"UpstreamHttpMethod": [ "POST", "PUT", "GET" ]
}
]
}
Ocelot sẽ nhận một danh sách các Routes
Route đầu tiên sẽ trỏ tới Phương thức GetAllProduct, tiếp theo sẽ là Creare, Update và Delete
DownstreamPathTemplate sẽ là route mà Ocelot trỏ đến Microservice
DownstreamScheme sẽ là HTTP hoặc HTTPS, ở đây mình dùng https, hãy xem url của product thì bạn sẽ thấy ở đây dùng https
DownstreamHostAndPorts định nghĩa địa chỉ, ở đây sẽ là localhost và port, port của Product Microservice là 44337, nhớ nhé
UpstreamPathTemplate sẽ là địa chỉ mà máy khách client trỏ tới, nghĩa là người dùng sẽ gọi tới đường dẫn này để gửi request tới server Ocelot API Gateway
UpstreamHttpMethod sẽ cấu hình để có thể hỗ trợ các phương thức POST, PUT, GET, nếu người dùng gửi 1 HTTP GET tới Ocelot thì Ocelot sẽ gửi 1 phương thức GET tới Microservice, kiểu đấy
Để không trùng cổng thì mình sẽ đặt Gateway có cổng 44382 (nhớ nhé), đường dẫn sẽ là: localhost:44382/gateway/product và mình mong đợi nó sẽ lấy được kết quả từ microservice ( địa chỉ localhost:44337)
Hmm, bạn có thể đổi cổng của Gateway trong File Appsettings.json trong project Gateway như sau

Thực hiện build solution trước, nếu không lỗi thì mới chạy đc. Tuy nhiên, bây giờ ta có tới tận 3 API. Phải cấu hình để cả 3 cái này cùng chạy 1 lúc nhé, lý do thì bạn cứ tưởng tượng 3 cái này là 3 server khác nhau, chúng cần gọi tới nhau nên phải chạy thì mới gọi đc chứ
Để cấu hình chạy cả 3 project thì bạn làm như sau;
Chuột phải vào solution, chọn properties. Ở đây chọn như hình nhé, nhớ chọn Multiple Startup Projects, chỉnh cả 3 về start là đc, thứ tự ko quan trọng đâu

Tiếp theo bạn run Solution lên, và thực hiện gửi 1 request tới đường dẫn localhost:44382/gateway/product. Kết quả nhận được sẽ như sau

Well, vậy là đã thành công như mong đợi rồi, rõ ràng bạn đang truy cập tới Ocelot mà lại lấy đc dữ liệu của Product, Microservice là vậy đó
Để test được nhiều hơn thì bạn sử dụng Postman nhé, ai k có thì tải đi
Bạn có thể test các phương thức như POST/PUT để thêm hoặc update data, 2 cái này cùng đường dẫn với GetAll ấy, chỉ khác phương thức thôi
Tuy nhiên 2 phương thức GetByID và Delete thì khác, chúng cần thêm Id trong params nên sẽ khác đường dẫn, thế thì phải cấu hình thêm thôi
{
"Routes": [
{
"DownstreamPathTemplate": "/api/product",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44337
}
],
"UpstreamPathTemplate": "/gateway/product",
"UpstreamHttpMethod": [ "POST", "PUT", "GET" ]
},
{
"DownstreamPathTemplate": "/api/product/{id}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44337
}
],
"UpstreamPathTemplate": "/gateway/product/{id}",
"UpstreamHttpMethod": [ "GET", "DELETE" ]
}
]
}
Cấu hình tương tự thôi. Và cùng test nào: localhost:44382/gateway/2

Như vậy là xong rồi đó, còn phần cấu hình Customer cũng sẽ tương tư, mình sẽ nhờ bạn làm hộ nhé
Mình sẽ kết thúc bài viết ở đây, bạn có góp ý gì comment giúp mình bên dưới nhé, có gì mình sửa, mình hy vọng các bạn sẽ hiểu hơn về Microservice trong ASP.NET Core sau bài viết này, Trong bài tiếp theo ta sẽ tìm hiểu về RabbitMQ, một Message Queue tuyệt vời trong Microservice
À Link bài viết này mình dịch từ đây nhé, ko phải tự viết đâu :>>
Tags: C# Microservice