Tải bản đầy đủ (.pdf) (46 trang)

đồ án 1 thiết kế và xây dựng hệ thống với net core

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (4.45 MB, 46 trang )

<span class="text_page_counter">Trang 1</span><div class="page_container" data-page="1">

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TINKHOA CÔNG NGHỆ PHẦN MỀM

BÁO CÁO ĐỒ ÁN

<b>Thiết kế và xây dựng hệ thống với.NET Core</b>

<i>Môn học: Đồ án 1Mã lớp: SE121.O11.PMCL</i>

</div><span class="text_page_counter">Trang 2</span><div class="page_container" data-page="2">

MỤC LỤC

<b>Chương 1: Tổng quan về thiết kế hệ thống5</b>

1.1. Thiết kế trong các hệ thống nhỏ và trong các hệ thống lớn 51.2. Các nguyên lý thiết kế hệ thống 6

1.2.4. Fault tolerance 81.2.4.1. Các khái niệm về fault tolerance 81.2.4.2. Byzantine fault 8

3.2.2. Distributed cache 163.2.3. Reverse proxy cache 16

3.2.5. Reverse proxy sidecar cache 183.3. Làm trống cache (Cache eviction) 183.4. Các pattern truy cập trong caching 19

<b>Chương 5: Service discovery & API Gateway24</b>

5.1. Phân loại service discovery 24

</div><span class="text_page_counter">Trang 3</span><div class="page_container" data-page="3">

5.2. Phân loại hình thức register 24

6.5. So sánh Two-phase commit/Three-phase commit và Saga 29

7.2.1. Khái quát về Raft 30

</div><span class="text_page_counter">Trang 4</span><div class="page_container" data-page="4">

9.1.1. Services & Dependency injection 38

</div><span class="text_page_counter">Trang 5</span><div class="page_container" data-page="5">

<b>Chương 1: Tổng quan về thiết kế hệ thống</b>

<b>1.1. Thiết kế trong các hệ thống nhỏ và trong các hệ thống lớn</b>

Đối với các hệ thống nhỏ không quá phức tạp thì ứng dụng của chúng ta sẽ sử dụngkiến trúc Client - Server như hình dưới:

Luồng hoạt động của một ứng dụng đơn giản sử dụng kiến trúc Client - Server sẽ nhưsau:

1. Người dùng sử dụng trình duyệt web hoặc app mobile truy cập vào website củachúng ta thông qua tên miềnapi.mysite.com.

2. Địa chỉ IP của website sẽ được trả về trình duyệt web hoặc app mobile màngười dùng truy cập.

3. Sau khi có được địa chỉ IP của website, HTTP request từ người dùng sẽ đượcgửi trực tiếp tới web server của chúng ta.

4. Web server trả về các trang HTML hoặc dữ liệu JSON và hiển thị các thông tinmà người dùng mong muốn ở chính thiết bị của người dùng.

Tuy nhiên, khi hệ thống có nhiều chức năng phức tạp hay số lượng người dùng truycập hệ thống ngày càng nhiều và phải phục vụ cùng một lúc một số lượng lớn user thìhệ thống đơn giản trên sẽ không đủ khả năng để phục vụ. Như vậy, chúng ta cần phảiáp dụng cách thiết kế khác để đáp ứng nhu cầu trên.

</div><span class="text_page_counter">Trang 6</span><div class="page_container" data-page="6">

Bằng cách sử dụng đồng thời nhiều server thay vì một server lưu trữ tồn bộ nhưtrước thì giờ đây chúng ta sẽ phân tách ra độc lập Web server và Database server chạyriêng biệt hồn tồn. Cơng việc lúc này của chúng ta sẽ phải thiết lập nhiều serverchạy đồng thời song song và đảm bảo chi khi tối ưu khi vận hành.

<b>1.2. Các nguyên lý thiết kế hệ thống</b>

<b>1.2.1. Scalability</b>

Scalability là khả năng mở rộng của hệ thống.

Có 2 cách để scale hệ thống: Vertical scaling và Horizontal scaling.

</div><span class="text_page_counter">Trang 7</span><div class="page_container" data-page="7">

Vertical scaling (scale up): chúng ta nâng cấp phần cứng (CPU, RAM, ổ cứng…) choserver. Đây là một cách đơn giản để cải thiện hiệu suất của hệ thống nhưng chúng takhông thể nâng cấp phần cứng liên tục, không giới hạn CPU, RAM vào server được vìgiới hạn của phần cứng. Đây là nhược điểm lớn nhất của Vertical scaling.

Horizontal scaling (scale out): chúng ta mở rộng, thêm nhiều server khác vào hệthống. Cách này sẽ khắc phục giới hạn của Vertical scaling và là lựa chọn tối ưu nhấtđể thiết kế trong các hệ thống lớn.

</div><span class="text_page_counter">Trang 8</span><div class="page_container" data-page="8">

Như vậy, với mức độ sẵn sàng càng cao thì thời gian sập của hệ thống phải càng ngàycàng được rút ngắn và gần như không để hiện tượng sập xảy ra.

<b>1.2.3. Consistency</b>

Consistency là tính nhất quán của hệ thống. Tại cùng một thời điểm, tất cả người dùngphải đảm bảo thấy được dữ liệu như nhau, đồng nhất ngay cả khi thực hiện các thaotác cập nhật dữ liệu.

<b>1.2.4. Fault tolerance</b>

1.2.4.1. Các khái niệm về fault tolerance

Failure: cả hệ thống bị gián đoạn, không hoạt động. Fault: một phần của hệ thốngkhông hoạt động. Fault tolerance: khả năng chống fault - hệ thống vẫn tiếp tục hoạtđộng khi có fault (khi số lượng fault dưới một ngưỡng tối đa).

1.2.4.2. Byzantine fault

Byzantine fault hay cịn được biết đến với Bài tốn các vị tướng Byzantine, mơ tả việcmột nhóm các vị tướng Byzantine gặp các vấn đề về liên lạc khi cố gắng đạt sự đồngthuận về bước đi tiếp theo.

Bài toán giả định rằng mỗi tướng có quân đội riêng và mỗi tướng đóng quân ở các địađiểm khác nhau xung quanh thành phố mà họ dự định tấn công. Các tướng phải đồngthuận về việc tấn công hoặc rút lui. Vấn đề tấn công hay rút lui không quan trọng màlà sự đồng thuận của tất cả các tướng, tức là, đồng thuận về một quyết định chung đểcùng phối hợp thực hiện.

</div><span class="text_page_counter">Trang 9</span><div class="page_container" data-page="9">

Do đó, chúng ta có thể xem xét kỹ càng các mục tiêu sau để đưa ra quyết định:● Mỗi tướng phải quyết định: tấn cơng hoặc rút lui (có hay khơng).

● Khơng thể thay đổi quyết định sau khi đưa ra.

● Tất cả tướng phải nhất trí về một quyết định giống nhau và tiến hành đồng bộvới nhau.

</div><span class="text_page_counter">Trang 10</span><div class="page_container" data-page="10">

<b>Chương 2: Load balancer</b>

<b>2.1. Load balancer</b>

Load balancer (cân bằng tải) để phân phối đồng đều lưu lượng truy cập giữa các webservers. Đây là một thành phần cực kỳ quan trọng cho hệ thống sử dụng đồng thờinhiều server.

Ưu điểm của Load balancer:

● Phân phối khối lượng công việc trên nhiều server, giảm tải cho hệ thống.● Cải thiện hiệu suất và độ tin cậy cho website.

</div><span class="text_page_counter">Trang 11</span><div class="page_container" data-page="11">

<b>2.2. Phân loại</b>

<b>2.2.1. Hardware & Software</b>

Hardware load balancer: là các thiết bị phần cứng máy tính chạy trên các phần mềmmã nguồn đóng, được xây dựng đặc biệt để có thể vận hành trên các bộ xử lý tùychỉnh. Với càng nhiều lưu lượng truy cập, số lượng các thiết bị cân bằng tải phải tănglên theo tỷ lệ thuận để có thể đáp ứng nhu cầu dịch vụ của khách hàng.

Software load balancer: là giải pháp tiết kiệm chi phí nhưng mang lại hiệu suất vậnhành tối ưu cho doanh nghiệp. Chúng ta chỉ cần cài đặt phần mềm cân bằng tải vàotrong hệ thống của mình, vẫn đảm bảo lưu lượng truy cập mà hệ thống chịu tải trongkhi không cần bỏ một mức chi phí rất lớn cho việc sử dụng và vận hành các hệ thốngcân bằng tải vật lý.

<b>2.2.2. Tầng xử lý</b>

Layer 7 load balancer: hoạt động ở tầng application - tầng cao nhất trong mơ hìnhOSI, nó đưa ra quyết định định tuyến dựa trên các thông tin chi tiết về đặc điểm củacác HTTP/HTTPS header, loại URL hoặc dữ liệu cookie…

</div><span class="text_page_counter">Trang 12</span><div class="page_container" data-page="12">

Layer 3/4 load balancer: hoạt động ở tầng network và tầng transport trong mơ hìnhOSI, sử dụng thơng tin về địa chỉ IP và cổng TCP/UDP để đưa ra quyết định địnhtuyến. Layer 3/4 load balancer thường không kiểm tra nội dung gói tin và chỉ chuyểntiếp các gói tin TCP/UDP đến các máy chủ backend.

Global server load balancer: phân phối lưu lượng truy cập trên các server ở nhiều nơitrên tồn thế giới. Sử dụng DNS và các thơng tin về tài nguyên dịch vụ để đưa raquyết định định tuyến.

</div><span class="text_page_counter">Trang 14</span><div class="page_container" data-page="14">

Client-side load balancing: là phương pháp trong đó việc phân phối lưu lượng mạngđược thực hiện ở phía client. Client sẽ nhận thơng tin về các máy chủ backend từ mộtdịch vụ danh mục (registry service) và sử dụng một thuật toán để chọn một máy chủbackend để gửi yêu cầu. Sau đó, client sẽ gửi yêu cầu trực tiếp đến máy chủ backendđược chọn và nhận kết quả trả về.

<b>2.5. Tăng availability của hệ thống</b>

Về cơ bản sẽ có 5 giải pháp để tăng availability cho hệ thống:

● Replication: với giải pháp này thì dữ liệu gốc sẽ được sao chép đến điểm đíchthơng qua những tác vụ sao chép (agent/job).

● Log Shipping: thông qua những tác vụ sao lưu Transaction Log, dữ liệu gốc sẽđược tiến hành sao chép đến điểm đích.

● Mirroring: thiết lập High availability dành cho database trong MS SQL Serverbằng cách sao chép dữ liệu sơ cấp sang dạng thứ cấp thông qua các networktransactions, nhờ sự hỗ trợ của các connection point cùng với port number.● Clustering: giải pháp này sử dụng dữ liệu đã lưu trữ ở những địa điểm thường

xuyên được truy cập, sử dụng cho máy chủ thứ cấp và sơ cấp. Giải pháp nàycần phải thiết lập Windows Clustering ở những nơi có sự chia sẻ dữ liệu chung.● AlwaysON Availability Groups: dữ liệu sơ cấp sẽ được chuyển sang dạng thứcấp bằng các network transactions. Với giải pháp này thì chúng ta khơng cầnphải thiết lập Windows Clustering.

</div><span class="text_page_counter">Trang 15</span><div class="page_container" data-page="15">

<b>Chương 3: Caching</b>

<b>3.1. Tổng quan về caching</b>

Caching là phương pháp lưu trữ tạm thời kết quả của các phép tính hoặc phản hồithường xuyên vào một vùng nhớ cache, giúp các yêu cầu tiếp theo của cùng phép tínhhoặc phản hồi được truy cập và xử lý nhanh hơn.

<b>3.2. Các pattern trong caching</b>

<b>3.2.1. Local cache</b>

Ưu điểm của Local cache:● Đơn giản, dễ sử dụng.● Có độ trễ thấp.

Nhược điểm của Local cache:● Khả năng scale không tốt.

</div><span class="text_page_counter">Trang 16</span><div class="page_container" data-page="16">

<b>3.2.2. Distributed cache</b>

Ưu điểm của Distributed cache:

● Sử dụng các thuật toán hash để phân mảnh data và lưu chúng trên nhiều nodekhác nhau.

● Tận dụng Redis, Memcache… làm backing data store.● Khả năng scale, chịu lỗi và khả năng phục hồi tốt.Nhược điểm của Distributed cache:

● Độ trễ lớn hơn so với Local cache.

<b>3.2.3. Reverse proxy cache</b>

Ưu điểm của Reverse proxy cache:● Giảm tải cho server.

</div><span class="text_page_counter">Trang 17</span><div class="page_container" data-page="17">

● Cache HTTP request khi Client thực hiện các request lặp lại nhiều lần, tănghiệu suất truy cập.

Nhược điểm của Reverse proxy cache:

● Khơng có khả năng chịu lỗi và phục hồi.

● Phụ thuộc vào API Gateway dẫn đến mức độ availability không cao.

<b>3.2.4. Sidecar cache</b>

Sidecar là một container khác nằm trong một container chính để hỗ trợ chức năng choservice chạy trong container chính.

Ưu điểm của Reverse proxy cache:

● Độ trễ thấp vì sidecar cache hoạt động như local cache.

● Dữ liệu cache không chiếm nhiều bộ nhớ cho ứng dụng đang hoạt động.Nhược điểm của Reverse proxy cache:

● Chỉ có thể triển khai khi dùng các nền tảng hỗ trợ containerized nhưKubernetes.

● Nếu Pod phải khởi động lại khi gặp sự cố nào đó thì cả container sẽ phải khởiđộng lại và dữ liệu cache sẽ bị xóa.

</div><span class="text_page_counter">Trang 18</span><div class="page_container" data-page="18">

<b>3.2.5. Reverse proxy sidecar cache</b>

Đây là sự kết hợp giữa Reverse-proxy và Sidecar cache, được tạo bằng cách chạyReverse-proxy container và cache data container trên cùng một Pod.

Trong cơ chế này thì chỉ có các phản hồi API mới được lưu vào Sidecar cache nhằmphục vụ cho các yêu cầu lặp đi lặp lại.

Thừa hưởng cả ưu điểm và nhược điểm của Reverse-proxy và Sidecar cache.

<b>3.3. Làm trống cache (Cache eviction)</b>

Cache eviction là quá trình loại bỏ các dữ liệu cũ, khơng được sử dụng thường xunhoặc có dung lượng quá lớn ra khỏi cache nhằm tạo ra không gian trống cho các tệpmới.

Chúng ta có thể xóa cache tự động hoặc tự định nghĩa để quyết định khi nào dữ liệucần được giải phóng.

</div><span class="text_page_counter">Trang 19</span><div class="page_container" data-page="19">

<b>3.4. Các pattern truy cập trong caching</b>

<b>3.4.1. Cache-aside</b>

Là cơ chế cache thường được sử dụng nhất, mơ hình hoạt động của nó như sau:

Cơ chế này thường được dùng cho trường hợp đọc nhiều và ghi ít. Ngồi ra cịn phụthuộc vào việc dữ liệu trả về có thay đổi hay khơng (truy vấn theo primary key thìthường hiếm khi thay đổi).

<b>3.4.2. Read-through</b>

Chiến lược này khá giống với cache-aside, thay vì application phải kết nối với cachevà database, giờ đây application chỉ cần giao tiếp với cache còn cache sẽ tự lấy dữ liệuở chính nó hoặc lấy dữ liệu từ database. Trong trường hợp này, cache chính làdatabase chính của ứng dụng và đóng vai trị rất quan trọng trong hệ thống. Vớicache-aside, việc cache bị chết thì ứng dụng vẫn chạy được, nhưng với read throughcache, nếu cache chết thì ứng dụng chết.

<b>3.4.3. Write-through</b>

Với chiến lược này, data sẽ được lưu xuống cache, cache sẽ lưu dữ liệu vào database.

</div><span class="text_page_counter">Trang 20</span><div class="page_container" data-page="20">

Khi một request write tới:

● Dữ liệu sẽ được lưu vào cache.

● Cache sẽ gửi yêu cầu lưu dữ liệu vào database ngay lập tức.

<b>3.4.4. Write-back (Write-behind)</b>

Write-back nhìn sơ khá giống với Write-through. Tuy nhiên, ở write-back, cachekhông lưu dữ liệu xuống database ngay khi nhận request từ application. Cache sẽ đồngbộ dữ liệu xuống database định kỳ theo thời gian, hoặc theo số lượng dữ liệu đượcinsert/update.

Để hiểu đơn giản hơn, chúng ta có thể đơn giản hóa sự khác biệt của write-through vàwrite-back đó là:

<b>● Write-through: lưu dữ liệu từ cache xuống database một cách đồng bộ.● Write-back: lưu dữ liệu từ cache xuống database bất đồng bộ.</b>

Khi một request write tới:

● Dữ liệu sẽ được lưu vào cache.

● Sau một khoảng thời gian, cache sẽ gửi yêu cầu lưu dữ liệu vào database.

</div><span class="text_page_counter">Trang 21</span><div class="page_container" data-page="21">

<b>Chương 4: Microservices</b>

<b>4.1. Miêu tả microservice</b>

Nền tảng của kiến trúc microservices là xây dựng một ứng dụng mà ứng dụng này làtổng hợp của nhiều services nhỏ và độc lập có thể chạy riêng biệt, phát triển và triểnkhai độc lập.

Ta có thể giải quyết các vấn đề của ứng dụng một khối bằng kiến trúc microservices(nhiều dịch vụ nhỏ). Ý tưởng là chia nhỏ ứng dụng lớn ra thành các dịch vụ nhỏ kếtnối với nhau.

Mỗi dịch vụ nhỏ thực hiện một tập các chức năng chuyên biệt như quản lý đơn hàng,quản lý khách hàng. Mỗi dịch vụ là một ứng dụng nhỏ có kiến trúc đa diện lõi làbusiness logic kết nối ra các adapter khác nhau. Một số dịch vụ nhỏ lộ ra giao tiếp lậptrình API cho dịch vụ nhỏ khác hay ứng dụng client gọi tới. Khi vận hành, mỗi dịchvụ nhỏ được chạy trong một máy ảo hoặc Docker container.

Mỗi vùng chức năng bây giờ được thực thi bởi một dịch vụ nhỏ. Ứng dụng web cũngcó thể chia nhỏ hơn chuyên cho từng đối tượng người dùng (hành khách/tài xế). Thiếtkế giao diện cho từng đối tượng người dùng giúp tối ưu trải nghiệm tốt hơn, tốc độnhanh hơn, dễ tương thích hơn trong khi chức năng tối giản hơn.

</div><span class="text_page_counter">Trang 22</span><div class="page_container" data-page="22">

<b>4.2. Phương thức giao tiếp giữa các service</b>

<b>Remote Procedure Invocation (RPI): sử dụng RPI để liên lạc giữa các service, client</b>

sử dụng một request/reply-based protocol để tạo request đến service.Một vài pattern cho RPI:

● REST● gRPC

● Apache Thrift

</div><span class="text_page_counter">Trang 23</span><div class="page_container" data-page="23">

<b>Messaging: sử dụng asynchronous messaging để giao tiếp giữa các services. Các</b>

services trao đổi message qua các kênh message.Một vài pattern về asynchronous messaging:

● Apache Kafka● RabbitMQ

<b>Domain-specific protocol: trong một vài trường hợp đặc biệt chúng ta không thể sử</b>

dụng RPI hay Messaging mà thay vào đó cần dùng domain-specific protocol cho việcgiao tiếp giữa các services.

Một vài ví dụ cụ thể về domain-specific protocol:● Email protocols như: SMTP, IMAP

● Media streaming protocols như: RTMP, HLS, và HDS

<b>4.3. Khuyết điểm của microservice</b>

Cần triển khai việc giao tiếp giữa nhiều inter-services.

Handle partial failure là rất phức tạp vì một luồng xử lý cần đi qua nhiều services.Việc thực hiện các requests trải rộng trên nhiều services, điều này cũng đòi hỏi sự phốihợp cẩn thận giữa các teams.

Khó khăn khi debug và fix bug: khi một service gặp lỗi do liên quan tới nhiều servicekhác thì xảy ra trường hợp mức độ ưu tiên để giải quyết lỗi trong team này thì khẩncấp nhưng với team khác lại khơng cao dẫn đến khó khăn khi fix bug.

Khó khăn trong việc đảm bảo toàn vẹn CSDL nếu triển khai theo kiến trúc cơ sở dữliệu phân vùng.

Triển khai và quản lý microservices nếu làm thủ công theo cách đã làm với ứng dụngmột khối phức tạp hơn rất nhiều.

Phải xử lý sự cố khi kết nối chậm, lỗi khi thông điệp không gửi được hoặc thông điệpgửi đến nhiều đích đến vào các thời điểm khác nhau.

</div><span class="text_page_counter">Trang 24</span><div class="page_container" data-page="24">

<b>Chương 5: Service discovery & API Gateway</b>

<b>5.1. Phân loại service discovery</b>

Client-side: theo cách tiếp cận này, client hoặc API gateway sẽ có được vị trí của mộtservice instance bằng cách truy vấn một service registry.

Server-side: với phương pháp này, client/API gateway sẽ gửi một request đến mộtcomponent (ví dụ như một load balancer) chạy trên một location đã biết. Componentđó sẽ gọi đến service registry và xác định vị trí location mà request cần đến.

<b>5.2. Phân loại hình thức register</b>

Self registration: service sẽ tự động đăng ký với registry khi nó khởi động. Điều nàythường được thực hiện bằng cách sử dụng một thư viện client tích hợp với service,cho phép service giao tiếp với registry và cung cấp thông tin cần thiết để đăng ký.

</div><span class="text_page_counter">Trang 25</span><div class="page_container" data-page="25">

Third party registration: service sẽ được tự động đăng ký mà khơng cần phải sử dụngthư viện tích hợp. Khi này việc phát hiện ra service và register và của một phần kháccủa hệ thống và service sẽ không cần phải biết bất cứ thứ gì về registry. Điều này giúpdecoupled registry với service nhưng lại khó triển khai hơn hẳn so với selfregistration. Mặt khác, ta không bị giới hạn bởi ngôn ngữ mà thư viện để register hỗtrợ.

<b>5.3. Sử dụng service</b>

<b>5.3.1. Direct</b>

Cách thức đầu tiên ta có thể sử dụng service là sử dụng trực tiếp thông qua servicediscovery. Nhưng điều này là khơng nên vì để làm như thế này thì ta cần phải exposecác địa chỉ IP của service và dẫn đến một lỗ hổng trong bảo mật. Mặt khác các requestsẽ trở nên phức tạp hơn vì ta sẽ cần phải tổng hợp lại các thông tin mà ta thu thập từnhiều service khác nhau, ta phải biết service nào cung cấp thông tin nào.

<b>5.3.2. Composite UI</b>

Một cách khác là ta dùng composite UI, khi này ta sẽ thiết kế giao diện dựa trên cácservice trong kiến trúc microservice ở backend. Thay vì ta có một monolithic UI thìbây giờ ta sẽ ánh xạ kiến trúc của backend và thiết kế quanh các service. Việc thiết kếgiao diện này sẽ yêu cầu nhiều kỹ năng hơn từ người lập trình nhưng sẽ giúp phântách nhiệm vụ truy vấn dữ liệu ra. Tuy nhiên cách này vẫn cần phải expose địa chỉ IP,ta có thể giải quyết bằng cách áp dụng một API gateway.

<b>5.3.3. API Gateway</b>

API Gateway là một thành phần trung gian giữa các client và các service trong mộtdistributed system. Nó đóng vai trò như một cửa vào cho các yêu cầu từ client, xử lýcác yêu cầu đó và redirect chúng đến service thích hợp.

Ngồi ra nó sẽ đảm nhận ln vai trị bảo mật API, monitoring, phân tích số lượngrequest cũng như đánh giá tình trạng hệ thống.

Lợi ích khi sử dụng API Gateway:

● Che dấu được cấu trúc của hệ thống microservices với bên ngồi.● Phần code phía frontend sẽ gọn gàng hơn.

● Dễ dàng theo dõi và quản lý traffic.● Requests caching và cân bằng tải.

</div>

×