/13
lOMoARcPSD| 61552860
BÀI TẬP TRÊN LỚP
MÔN HỌC: HỆ PHÂN TÁN
CHƯƠNG 2: TIẾN TRÌNH VÀ TRAO ĐỔI THÔNG TIN TRONG HPT
HỌ TÊN SV:Nguyễn Xuân Sơn MSSV:20204778
MÃ LỚP:144944 MÃ HỌC PHẦN:IT4611
Câu hỏi 1: Có cần thiết phải giới hạn số lượng các luồng trong một tiến trình server?
Việc giới hạn số lượng luồng (threads) trong một tiến trình server phụ thuộc o nhiều yếu tố, và
không có một quy tắc cố định nào áp dụng cho mọi tình huống. Có một số yếu tố mà bạn nên xem
xét khi quyết định xem cần thiết giới hạn số lượng luồng trong tiến trình server của bạn hay
không
Tùy thuộc vào ứng dụng cụ thể của bạn yêu cầu của nó, bạn có thể quyết định xem cần giới
hạn số lượng luồng hay không. Việc này nên được thực hiện sau khi tiến hành kiểm tra hiệu suất và
sử dụng tài nguyên trong môi trường ứng dụng thực tế. Điều quan trọng là đảm bảo rằng tiến trình
server hoạt động ổn định, hiệu quả và không tiêu tốn quá nhiều tài nguyên.
Câu hỏi 2: Có nên chỉ gắn một luồng đơn duy nhất với một tiến trình nhẹ?
Gắn một luồng đơn duy nhất với một tiến trình nhẹ (lightweight process) một cách tiếp cận
thể hữu ích trong một số tình huống, nhưng không phải lúc nào cũng là tối ưu. Quyết định này phụ
thuộc vào nhiều yếu tố và mục tiêu cụ thể của ứng dụng của bạn.Tuy nhiên, cần lưu ý rằng việc sử
dụng nhiều tiến trình nhẹ cũng có nhược điểm, như tăng sự phức tạp của mã nguồn tăng sử dụng
tài nguyên hệ thống. Quyết định nên sử dụng mô hình một luồng một tiến trình nhẹ hay không phụ
thuộc vào yêu cầu cụ thể của ứng dụng và các yếu tố hiệu suất, bảo mật, và quản lý.
Câu hỏi 3: Có nên chỉ có một tiến trình nhẹ đơn gắn với 1 tiến trình?
Gắn một tiến trình nhẹ (lightweight process) đơn với một tiến trình (process) là mộthình thực
hiện được trong các hệ thống đa tiến trình hoặc đa luồng, có thể hữu ích trong một số tình huống,
nhưng nó phụ thuộc vào mục tiêu cụ thể của ứng dụng và yêu cầu của nó.Tuy nhiên, cần lưu ý rằng
việc gắn một tiến trình nhẹ đơn với mỗi tiến trình có thể tạo ra một overhead về tài nguyên, do đó,
cần xem xét mục tiêu cụ thể của ứng dụng và tài nguyên có sẵn trên hệ thống. Mô hình này thường
được sử dụng trong các hệ thống phân tán hoặc các ứng dụng yêu cầu nh cách ly cao giữa các
phần của mã nguồn.
Câu hỏi 4: Bài toán này yêu cầu bạn so sánh thời gian đọc một tệp (file) của một máy chủ tập tin
(file server) đơn luồng một máy chủ đa luồng. Phải mất tổng cộng 15 ms để nhận 1 yêu cầu
(request) và thực hiện quá trình xử lý, giả định rằng các dữ liệu cần thiết nằm ở bộ nhớ đệm trong
bộ nhớ chính. Nếu cần thiết phải thực hiện một thao tác truy cập đĩa thì cần thêm 75 ms, biết
rằng việc phải thực hiện thao tác này xắc suất là 1/3. Hỏi máy chủ thể nhận bao nhiêu yêu
cầu/giây trong 2 trường hợp: máy chủ là đơn luồng và máy chủ là đa luồng (ngoài luồng nhận
xử lý request, sẽ có thêm 1 luồng để truy cập ổ đĩa nếu cần thiết)? Giải thích.
Để tính toán máy chủ có thể nhận được bao nhiêu yêu cầu/giây trong hai trường hợp: máy chủ đơn
luồng máy chủ đa luồng, chúng ta sẽ sdụng thông tin về thời gian trả lời yêu cầu (response
time) và xác suất yêu cầu cần thêm thời gian truy cập ổ đĩa.
1. Máy chủ đơn luồng:
lOMoARcPSD| 61552860
Thời gian xử lý yêu cầu trong trường hợp tệp (file) nằm trong bộ nhớ chính: 15 ms.
Xác suất cần thực hiện thao tác truy cập ổ đĩa: 1/3.
Thời gian thực hiện thao tác truy cập ổ đĩa (75 ms) cộng thêm vào thời gian xử lý trong trường hợp
không cần truy cập ổ đĩa (15 ms):
Trong trường hợp cần truy cập ổ đĩa: 15 ms (xử lý) + 75 ms (truy cập ổ đĩa) = 90 ms.
Trong trường hợp không cần truy cập ổ đĩa: 15 ms (xử lý).
Giờ ta sẽ tính trung bình thời gian xử lý một yêu cầu:
Thời gian trung bình = (Xác suất cần truy cập đĩa) * (Thời gian xử khi cần truy cập đĩa) +
(Xác suất không cần truy cập đĩa) * (Thời gian xử khi không cần truy cập đĩa) Thời gian
trung bình = (1/3) * 90 ms + (2/3) * 15 ms = 45 ms + 10 ms = 55 ms.
Bây giờ, chúng ta có thể tính số yêu cầu mà máy chủ đơn luồng có thể nhận trong 1 giây:
Số yêu cầu/giây = 1000 ms / Thời gian trung bình = 1000 ms / 55 ms ≈ 18.18 yêu cầu/giây.
2. Máy chủ đa luồng:
Trong trường hợp máy chủ đa luồng, chúng ta có thêm một luồng để thực hiện thao tác truy cập ổ
đĩa. Tuy nhiên, điều quan trọng luồng truy cập đĩa và luồng xử yêu cầu chính phải hoạt
động đồng thời.
Thời gian xử một yêu cầu trong trường hợp tệp nằm trong bộ nhớ chính 15 ms. Tuy nhiên,
với việc thêm luồng truy cập đĩa, chúng ta cần cộng thời gian xử trong cả hai luồng lại với
nhau để tính toán thời gian trung bình.
Thời gian trung bình = Thời gian xử lý yêu cầu chính + Thời gian xử lý luồng truy cập ổ đĩa Thời
gian trung bình = 15 ms + 15 ms = 30 ms.
Số yêu cầu/giây = 1000 ms / Thời gian trung bình = 1000 ms / 30 ms ≈ 33.33 yêu cầu/giây.
Vậy, trong trường hợp máy chủ đa luồng, máy chủ có thể nhận được khoảng 33.33 yêu cầu/giây.
lOMoARcPSD| 61552860
Tóm lại, máy chủ đa luồng thể xử nhiều yêu cầu hơn mỗi giây so với máy chủ đơn luồng
trong tình huống này với điều kiện rằng luồng truy cập ổ đĩa luồng xlý chính thể hoạt động
đồng thời.
Câu hỏi 5: Hệ thống X chỉ định máy của user chưa server, trong khi các ứng dụng lại được coi như
client. Điều đó có vô lý không? Giải thích.
Không, việc đặt máy của người dùng (user) là máy chủ (server) trong một hệ thống không phải lúc
nào cũng vô lý, và nó có thể được thiết kế như vậy để đáp ứng mục tiêu cụ thể của hệ thống. Cách
này có thể hợp lý trong một số tình huống. Dưới đây là một số lý do giải thích:
Tính phân tán và hiệu suất: Trong một số kiến trúc hệ thống phân tán, máy của người dùng (user)
thể đóng vai trò như một máy chủ phân phối dữ liệu hoặc tài nguyên cho các máy khác. Điều
này có thể giúp phân tải và cải thiện hiệu suất của hệ thống bằng cách sử dụng tài nguyên cục bộ
thay vì phải truy cập máy chủ trung tâm từ xa.
Kiến trúc ngang hàng (Peer-to-Peer): Trong các mạng kiến trúc ngang hàng, máy của người dùng
không phải lúc nào cũng chỉ đóng vai trò client. Các máy trong mạng thể cùng chia sẻ tài nguyên
và dữ liệu với nhau, và không có máy chủ trung tâm. Ví dụ, các ứng dụng torrent thường sử dụng
mô hình này.
Tối ưu hóa việc truy cập dữ liệu cục bộ: Trong trường hợp dữ liệu cần được truy cập nhanh chóng
và tối ưu từ máy người dùng, việc sử dụng máy người dùng như một máy chủ thể giảm độ trễ
và tăng hiệu suất, đặc biệt khi dữ liệu được lưu trữ cục bộ.
Bảo mật quản dữ liệu: Người dùng thể muốn kiểm soát bảo mật dữ liệu của họ bằng
cách tự quản lý máy chủ của họ. Điều này đặc biệt quan trọng trong các ứng dụng yêu cầu mức độ
kiểm soát cao và bảo mật.
Tùy thuộc vào mục tiêu cụ thể của hệ thống và cách thiết kế, việc đặt máy của người dùng là máy
chủ thể hợp không lý. Quan trọng nhất đảm bảo rằng kiến trúc này đáp ứng được
yêu cầu và mục tiêu của hệ thống một cách hiệu quả và an toàn.
Câu hỏi 6: Giao thức thiết kế cho hệ thống X gặp phải vấn đề về nh mở rộng. Chỉ ra các giải pháp
để giải quyết vấn đề đó?
Việc giải quyết vấn đề về tính mở rộng trong thiết kế giao thức cho hthống X là rất quan trọng
để đảm bảo rằng hệ thống có thể mở rộng dễ dàng khi cần thiết, đồng thời đảm bảo hiệu suất
tính nhất quán. Dưới đây là một số giải pháp để giải quyết vấn đề về tính mở rộng:
Sử dụng kiến trúc phân tán: Một kiến trúc phân tán cho phép bạn chia nhỏ hệ thống thành các
thành phần độc lập thể mở rộng riêng lẻ. Mỗi thành phần thể tồn tại trên c máy chủ
riêng biệt, cho phép bạn mở rộng từng phần của hệ thống một cách độc lập.
Cân bằng tải (Load Balancing): Sử dụng giải pháp cân bằng tải giữa các máy chủ để phân phối tải
đều đặn giữa các thành phần của hệ thống. Điều này giúp tăng hiệu suất và đảm bảo tính mở rộng
dễ dàng bằng cách thêm máy chủ khi tải tăng.
Dịch vụ dự phòng (Redundancy): Sử dụng dịch vụ dự phòng để đảm bảo tính sẵn sàng giảm
nguy mất mát dữ liệu. Khi một máy chủ hoặc thành phần gặp sự cố, dịch vụ dự phòng thể
tiếp quản và giữ hệ thống hoạt động.
lOMoARcPSD| 61552860
Tạo dự phòng dữ liệu (Data Replication): Sao lưu và sao chép dữ liệu đến nhiều máy chủ để đảm
bảo tính nhất quán sẵn sàng dữ liệu. Các cơ sở dữ liệu phân phối có thể hữu ích để giải quyết
vấn đề này.
Quản lý phiên (Session Management): Để đảm bảo tính nhất quán của phiên người dùng, quản lý
phiên có thể được thực hiện bằng cách sdụng phiên đám mây hoặc phiên dự phòng giữa các máy
chủ.
Tích hợp dịch vụ công cộng (Public Cloud Integration): Sử dụng các dịch vụ đám mây công cộng
(ví dụ: AWS, Azure, Google Cloud) để mở rộng hệ thống theo yêu cầu. Điều này cho phép bạn mở
rộng nhanh chóng và hiệu quả mà không phải mua thêm phần cứng vật lý.
Sử dụng công nghệ container orchestration: Các công nghệ như Docker Kubernetes cho phép
bạn đóng gói ứng dụng và quản chúng trên các máy chủ một cách hiệu quả. Điều này giúp tạo
ra một môi trường mở rộng và dễ quản lý.
Tối ưu hóa sở dữ liệu: Sử dụng sở dữ liệu phân phối hoặc sở dữ liệu NoSQL để tối ưu
hóa việc quản lý dữ liệu và mở rộng dự án.
Sử dụng giao thức RESTful và API: Sử dụng RESTful APIs cho phép các ứng dụng khác giao tiếp
và tương tác với hệ thống của bạn một cách dễ dàng, đồng thời mở rộng dự án.
Sử dụng auto-scaling: Sử dụng công cụ tự động mở rộng để tự động thêm hoặc giảm số máy chủ
dựa trên tải.
Những giải pháp trên có thể được kết hợp và tùy chỉnh để đáp ứng yêu cầu cụ thể của hệ thống và
tình huống mở rộng.
Câu hỏi 7: Với việc xây dựng một server đồng thời, hãy so sánh việc server này tạo một luồng mới
và tạo một tiến trình mới khi nhận được yêu cầu từ phía client.
Khi bạn xây dựng một server đồng thời, việc quyết định liệu nên tạo một luồng mới hay một tiến
trình mới khi nhận được yêu cầu từ phía client phụ thuộc vào mục tiêu cụ thể của ứng dụng và yêu
cầu hiệu suất. Dưới đây một so sánh giữa việc tạo luồng mới và tạo tiến trình mới trong ngữ
cảnh này:
Tạo luồng mới (Multithreading):
Tối ưu cho I/O-bound tasks: Khi ứng dụng chủ yếu thực hiện các hoạt động I/O-bound như đọc/ghi
dữ liệu từ/đến ổ đĩa hoặc giao tiếp mạng, việc sử dụng luồng mới có thể tối ưu hơn. Luồng có thể
được tạo và quản lý một cách hiệu quả hơn so với tiến trình.
Không tiêu tốn nhiều tài nguyên hệ thống: Luồng sử dụng ít tài nguyên hệ thống hơn so với tiến
trình, vì chúng chia sẻ cùng không gian địa chỉ và các tài nguyên khác.
Dễ dàng chia sẻ dữ liệu: Luồng trong cùng một tiến trình có thể chia sẻ dữ liệu dễ dàng. Điều này
có thể hữu ích khi cần chia sẻ dữ liệu giữa các yêu cầu.
Tạo tiến trình mới (Multiprocessing):
lOMoARcPSD| 61552860
Tối ưu cho CPU-bound tasks: Khi ứng dụng thực hiện các tác vụ CPU-bound phức tạp và đòi hỏi
nhiều tính toán, tạo một tiến trình mới thể tối ưu hơn. Mỗi tiến trình có thể sử dụng một lõi CPU
riêng biệt, tận dụng tối đa hiệu suất đa lõi của hệ thống.
Tách biệt an toàn: Mỗi tiến trình không gian địa chỉ riêng, điều này giúp đảm bảo tính tách
biệt và an toàn. Lỗi trong một tiến trình không ảnh hưởng đến các tiến trình khác.
Tích hợp với các ngôn ngữ và thư viện nhiều tiến trình (Multiprocessing Libraries): Các ngôn ngữ
thư viện hỗ trợ tạo và quản lý tiến trình dễ dàng hơn. Ví dụ, Python thư viện multiprocessing
cho việc này.
Tóm lại, việc chọn giữa tạo luồng mới tạo tiến trình mới phụ thuộc vào loại công việc mà server
của bạn cần thực hiện. Nếu chủ yếu I/O-bound cần hiệu suất tốt, sử dụng luồng mới
thể là lựa chọn. Nếu nó là CPU-bound hoặc yêu cầu tính tách biệt cao, thì tạo tiến trình mới có thể
lựa chọn tốt hơn. Đôi khi, việc kết hợp cả hai thể giải pháp tốt nhất, tùy thuộc vào tình
huống cụ thể.
Câu hỏi 8: Nếu bây giờ một webserver tổ chức lưu lại thông tin về địa chỉ IP của client trang
web client đó vừa truy cập. Khi 1 client kết nối với server đó, server sẽ tra xem trong bảng
thông tin, nếu tìm thấy thì sẽ gửi nội dung trang web đó cho client. Server này trạng thái
(stateful) hay không trạng thái (stateless)?
Một server được coi là có trạng thái (stateful) trong trường hợp này, nó duy trì thông tin về trạng
thái của các kết nối trước đó. Trạng thái đây được thể hiện thông qua việc lưu lại thông tin về
địa chỉ IP của client và trang web mà client truy cập. Khi một client kết nối với server, server kiểm
tra bảng thông tin của mình để xác định trang web mà client đã truy cập trước đó và gửi nội dung
trang web đó cho client.
Một server stateful là server có khả năng duy trì thông tin về trạng thái của các kết nối trước đó và
sử dụng thông tin này để phục vụ các yêu cầu sau này. Điều này thể hữu ích trong nhiều
trường hợp, như quản lý phiên của người dùng, theo dõi dữ liệu liên quan đến người dùng, hoặc
cung cấp các tính năng tương tác phức tạp dựa trên lịch sử của client.
Trong khi server stateful có lợi ích về tính nhất quán và quản trạng thái, nó cũng đặt ra các thách
thức về quản trạng thái, khả năng mở rộng bảo mật. Server stateless (không trạng thái) thường
đơn giản hơn dễ quản lý hơn, nhưng không thể theo dõi trạng thái của các kết nối trước đó. Việc
sử dụng server stateful hay stateless phụ thuộc vào yêu cầu cụ thể của ứng dụng và các ưu tiên của
bạn.
Câu hỏi 9: So sánh Docker và Virtual Machine.
Docker và Virtual Machine (VM) hai công nghệ phổ biến trong việc tạo môi trường ảo để chạy
ứng dụng. Mặc cả hai có mục tiêu chung cung cấp một cách để đóng gói chạy ứng dụng
trong môi trường cách ly, chúng sự khác biệt quan trọng về cách hoạt động và mức độ tài nguyên
tiêu tốn. Dưới đây là một so sánh giữa Docker và Virtual Machine:
1. Kiến trúc:
Docker: Docker sử dụng kiến trúc container, nơi các ứng dụng và phụ thuộc của chúng chia sẻ hạt
nhân của hệ điều hành máy chủ chủ. Container Docker chạy trực tiếp trên hệ điều hành và sử dụng
một lớp gọi là Docker Engine để quản lý chúng.
lOMoARcPSD| 61552860
Virtual Machine: VMs các máy ảo độc lập hoàn toàn chứa cả hệ điều hành và ứng dụng của
riêng chúng. Chúng chạy trên một hypervisor, là một lớp trung gian giữa VM và phần cứng vật lý.
2. Tài nguyên:
Docker: Containers sử dụng ít tài nguyên hơn so với VMs. Chúng cần ít dung lượng đĩa và bộ nhớ
hơn, vì chúng chia sẻ hạt nhân và các thư viện với hệ điều hành máy chủ.
Virtual Machine: VMs tiêu tốn nhiều tài nguyên hơn do mỗi VM có một hệ điều hành riêng và phải
chia sẻ phần cứng vật lý với các VM khác.
3. Khởi động và thời gian tắt:
Docker: Containers khởi động và tắt nhanh chóng do chúng chia sẻ hạt nhân với hệ điều hành máy
chủ.
Virtual Machine: VMs cần nhiều thời gian hơn để khởi động tắt do việc khởi động toàn bộ hệ
điều hành của VM.
4. Tích hợp và triển khai:
Docker: Docker containers dễ tích hợp và triển khai. Chúng có thể được đóng gói một cách dễ dàng
trong hình ảnh Docker và chia sẻ qua Docker Hub.
Virtual Machine: VMs có thể được triển khai bằng cách sao lưu và phục hồi toàn bộ hệ thống máy
ảo. Việc này có thể tốn thời gian hơn và phức tạp hơn.
5. Độ cô lập:
Docker: Docker containers cung cấp độ cô lập tương đối. Chúng chia sẻ hạt nhân với hệ điều hành
máy chủ.
Virtual Machine: VMs cung cấp độ lập hoàn toàn. Mỗi VM hệ điều hành phần mềm cài
đặt riêng biệt.
6. Môi trường đa nền tảng:
Docker: Docker containers hỗ trợ đa nền tảng và có thể chạy trên nhiều hệ điều hành máy chủ khác
nhau.
Virtual Machine: VMs thường yêu cầu sử dụng hypervisor phù hợp với hệ điều hành máy chủ.
Tóm lại, Docker Virtual Machine đều ứng dụng riêng của họ trong c tình huống cụ thể.
Docker thích hợp cho việc đóng gói và triển khai ứng dụng một cách dễ dàng và hiệu quả, trong khi
Virtual Machine thích hợp cho việc cung cấp độ cô lập hoàn toàn và chạy nhiều hệ điều hành khác
nhau trên cùng một máy chủ vật lý.
Câu hỏi 10: Trong các giao thức phân tầng, mỗi tầng sẽ một header riêng. Vậy nên triển
khai một hệ thống tất cả các header của các tầng đưa chung vào một phần (gọi header chung),
gắn vào đầu mỗi thông điệp để có thể xử lý chung? Giải thích.
lOMoARcPSD| 61552860
Việc triển khai một hệ thống mà tất cả các header của các tầng được đưa chung vào một phần gọi là
"header chung" để xử chung có thể là một giải pháp hợp lý trong một số trường hợp, nhưng cần
xem xét một số vấn đề quan trọng trước khi quyết định triển khai cách tiếp cận này.
Dưới đây là một số điểm cần xem xét:
1. Mục tiêu và cơ sở giao thức:
Nếu hệ thống của bạn chủ yếu sử dụng các giao thức có sẵn và đã được thiết kế với cơ sở giao thức
cụ thể (ví dụ: TCP/IP), việc tách biệt các tầng header của chúng thể là cách tiếp cận tốt hơn
để duy trì tính nhất quán và tương thích với các giao thức hiện có.
2. Quản lý và bảo trì:
Khi tất cả các header được đưa vào một phần chung, việc quản bảo trì hệ thống thể trở
nên phức tạp. Điều này đặc biệt đúng khi bạn cần thêm hay cập nhật các tầng hoặc header mới.
3. Hiệu suất:
Việc xử lý các header chung có thể gây ra overhead trong việc đọc xử lý thông điệp. Một header
chung phải chứa đủ thông tin để xác định loại giao thức, cổng đích, địa chỉ IP, v.v. Việc này có thể
làm gia tăng độ trễ và tiêu tốn tài nguyên máy tính.
4. Bảo mật:
Việc đưa tất cả thông tin vào một header chung có thể đặt ra các vấn đề về bảo mật. Trong một số
trường hợp, các tầng phân tầng cung cấp lớp bảo mật bổ sung, và việc tổng hợp các header có thể
tạo ra lỗ hổng bảo mật. 5. Tích hợp với giao thức hiện có:
Một số giao thức thể không dễ dàng tích hợp với hình header chung. Một số giao thức
cấu trúc phân tầng cụ thể cho việc đọc và xử lý thông điệp.
6. Tính linh hoạt:
Tùy thuộc vào yêu cầu tình huống cụ thể của ứng dụng, việc tách biệt các header thể cho
phép tùy chỉnh một cách dễ dàng cho từng tầng mà không ảnh hưởng đến các tầng khác. Tóm lại,
việc quyết định nên triển khai hệ thống với "header chung" hay không phụ thuộc vào yêu cầu
mục tiêu cụ thcủa ứng dụng. Trong một số tình huống, việc sử dụng header chung thể giảm
độ phức tạp tối ưu hóa quản lý, trong khi trong những trường hợp khác, việc giữ nguyên cấu
trúc giao thức phân tầng là tối ưu hơn để đảm bảo tính nhất quán, bảo mật và hiệu suất.
Câu hỏi 11: Xét 1 thủ tục incr với 2 tham số nguyên. Thủ tục làm nhiệm vụ là cộng 1 đơn vị vào
mỗi tham số. Bây giờ xét trường hợp chúng ta gọi thủ tục đó với cùng một biến, dụ incr(i, i).
Nếu biến i được khởi tạo giá trị 0, vậy giá trị của i sẽ là bao nhiêu sau khi gọi thủ tục này trong 2
trường hợp sau:
- Lời gọi tham chiếu
- Phương pháp sao chép-phục hồi được sử dụng.
Trong trường hợp bạn gọi thủ tục incr(i, i) với một biến i ban đầu có giá trị là 0, hãy xem xét cả hai
trường hợp:
1. Tham chiếu (Call by Reference):
lOMoARcPSD| 61552860
Trong trường hợp này, cả hai tham số i đều trỏ đến cùng một vùng bộ nhớ, khi bạn gọi thủ tục
incr, cả hai tham số đều tương tác với cùng một biến trong bộ nhớ.
Ban đầu: i = 0
Gọi thủ tục incr(i, i): Cả hai tham số trỏ đến cùng một biến, và giá trị của biến được tăng lên 1. Sau
khi gọi thủ tục này, i sẽ là 1.
2. Sao chép-Phục hồi (Call by Value):
Trong trường hợp này, mỗi tham số i được sao chép vào một biến tạm thời và thủ tục incr sẽ tương
tác với các biến tạm thời này.
Ban đầu: i = 0
Gọi thủ tục incr(i, i): Cả hai tham số i được sao chép vào các biến tạm thời riêng biệt, và thủ tục incr
tương tác với các biến tạm thời này. Do đó, giá trị của i không thay đổi sau khi gọi thủ tục này. Sau
thủ tục, i vẫn là 0.
Vì vậy, trong trường hợp tham chiếu, giá trị của i sau khi gọi thủ tục là 1, trong khi trong trường hợp
sao chép-Phục hồi, giá trị của i vẫn là 0.
lOMoARcPSD| 61552860
Câu hỏi 12: Một kết nối socket cần 4 thông tin nào? Tại sao phải cần đủ 4 thông tin đó? Một
kết nối socket cần bốn thông tin cơ bản sau:
Địa chỉ IP nguồn: Đây là địa chỉ IP của máy gửi dữ liệu hoặc thiết bị mà bạn đang sử dụng để thiết
lập kết nối. Đây là địa chỉ của máy gửi dữ liệu và là nguồn của kết nối.
Cổng nguồn: Cổng nguồn một số cụ thể trên máy gửi dữ liệu. giúp máy chủ hoặc máy đích
xác định ứng dụng mà dữ liệu đang đến và cần được định tuyến tới. Mỗi ứng dụng trên máy tính sẽ
lắng nghe trên một cổng cụ thể để có thể nhận dữ liệu.
Địa chỉ IP đích: Đây là địa chỉ IP của máy chủ hoặc thiết bị đích mà bạn đang cố gắng kết nối đến.
Đây là đích của kết nối.
Cổng đích: Cổng đích cổng trên máy chủ hoặc máy đích mà dữ liệu cố gắng truyền đến. Nó giúp
máy chủ xác định ứng dụng mà dữ liệu nên được gửi tới.
Tại sao cần đủ cả bốn thông tin này:
Địa chỉ IP nguồn và cổng nguồn: Chúng xác định máy gửi dữ liệu và ứng dụng nguồn. Điều này
quan trọng để máy chủ biết phản hồi về đúng máy gửi và ứng dụng.
Địa chỉ IP đích và cổng đích: Chúng xác định máy chủ hoặc máy đích và ứng dụng dữ liệu cố
gắng kết nối đến. cho phép máy chủ xác định đích của dữ liệu định tuyến nó tới ứng dụng
tương ứng.
Các thông tin này là quan trọng để định rõ nguồn và đích của dữ liệu trong quá trình truyền thông
qua mạng và đảm bảo rằng nó được định tuyến và gửi tới đúng ứng dụng và máy tính.
Câu hỏi 13: Tại sao giao thức yêu cầu-trả lời (request-reply) lại được coi đồng bộ tin cậy?
Giao thức yêu cầu-trả lời (request-reply protocol) thường được coi là đồng bộ và tin cậy vì nó thiết
lập một quy trình tương tác giữa hai thực thể hoặc hệ thống mà yêu cầu một phản hồi xác nhận sau
khi gửi một yêu cầu. Dưới đây là một số lý do:
1. Đảm bảo tính nhất quán: Trong giao thức yêu cầu-trả lời, người gửi yêu cầu không tiếp tục
thựchiện bất kỳ hành động nào khác cho đến khi nhận được phản hồi từ bên đích. Điều này đảm
bảo tính nhất quán trong quá trình giao tiếp, yêu cầu một hành động được hoàn thành trước
khi bắt đầu hành động tiếp theo.
2. Đảm bảo tin cậy: Trong giao thức yêu cầu-trả lời, sự tin cậy đòi hỏi rằng bên gửi yêu cầu chỉ
kết thúc quá trình sau khi nhận được phản hồi xác nhận từ bên đích. Nếu không nhận được phản hồi
hoặc phản hồi bị lỗi, gửi lại yêu cầu thể được thực hiện để đảm bảo rằng yêu cầu cuối cùng được
xử lý một cách đúng đắn.
3. Xác định được quy trình giao tiếp: Giao thức yêu cầu-trả lời định rõ một quy trình cthể cho
việc giao tiếp giữa hai bên. Người gửi yêu cầu biết rõ khi nào nên gửi yêu cầu, bên đích biết
cách phản hồi. Điều này giúp giảm thiểu sự nhầm lẫn và tạo ra sự rõ ràng trong quá trình giao tiếp.
lOMoARcPSD| 61552860
4. Hỗ trợ kiểm soát lỗi khôi phục: Giao thức yêu cầu-trlời cung cấp một chế cho việc
xử lýlỗi khôi phục sau lỗi. Nếu xảy ra lỗi trong quá trình giao tiếp, bên gửi thể thực hiện lại
yêu cầu hoặc thực hiện các biện pháp khôi phục khác để đảm bảo tính tin cậy.
Tóm lại, giao thức yêu cầu-trả lời được coi là đồng bộ và tin cậy bởi vì nó đảm bảo tính nhất quán,
đảm bảo sự tin cậy trong giao tiếp, định quy trình giao tiếp cung cấp khả ng kiểm soát lỗi
và khôi phục. Điều này rất quan trọng trong nhiều ứng dụng hệ thống nơi độ tin cậy và độ nhất
quán là yếu tố quan trọng.
Câu hỏi 14: Hai vấn đề chính đối với giao thức RPC là gì?
Giao thức RPC (Remote Procedure Call) một cách để một ứng dụng gọi một hàm hoặc thủ tục
trên một máy tính từ xa nnó đang chạy trên máy tính cục bộ. Tuy nhiên, khi triển khai và sử dụng
giao thức RPC, có hai vấn đề chính cần quan tâm:
Tính nhất quán (Consistency): Vấn đề này liên quan đến việc đảm bảo tính nhất quán dữ liệu giữa
hai máy tính tham gia trong giao thức RPC. Điều này đặc biệt quan trọng khi một hàm hoặc thủ tục
được gọi từ xa, và sau đó máy chủ phải cung cấp một kết quả đúng và nhất quán cho máy khách.
Giải quyết xung đột dữ liệu (Data Conflicts): Đôi khi, hai máy tính thể cố gắng cập nhật cùng
một dữ liệu tại cùng một thời điểm, y ra xung đột dữ liệu. Cách giải quyết xung đột này một
vấn đề quan trọng, cần phải sử dụng các giải pháp như khóa, semaphores, hoặc phiên bản dữ liệu
(versioning) để đảm bảo tính nhất quán.
Quản lý trạng thái: Một hàm hoặc thủ tục có thể thay đổi trạng thái của máy chủ. Điều này đặt ra
câu hỏi về cách quản lý trạng thái và đảm bảo tính nhất quán trong hệ thống.
Bảo mật (Security): Vấn đề bảo mật một thách thức lớn trong giao thức RPC. Vì dữ liệu
được gửi qua mạng, cần xác minh người gửi và đảm bảo nh toàn vẹn của dữ liệu trước khi nó được
chấp nhận bởi máy chủ.
Xác thực (Authentication): Xác thực người gửi là một bước quan trọng để đảm bảo rằng chỉ người
dùng có quyền truy cập được phép gửi yêu cầu RPC.
Mã hóa (Encryption): Dữ liệu gửi qua mạng cần được mã hóa để ngăn người không có quyền đọc
nó. Điều này đặc biệt quan trọng khi dữ liệu nhạy cảm được truyền.
Phân quyền (Authorization): Đảm bảo rằng người dùng chỉ có quyền thực hiện những hành động
được ủy quyền.
Xử những vấn đề này là quan trọng để triển khai giao thức RPC an toàn đáng tin cậy trong
môi trường phân tán.
Câu hỏi 15: Vấn đề đối với truyền tham biến trong RPC gì? Còn đồi với truyền tham chiếu?
Giải pháp đưa ra là gì?
lOMoARcPSD| 61552860
Trong giao thức RPC (Remote Procedure Call), truyền tham biến truyền tham chiếu hai cách
để gửi tham số dữ liệu từ máy khách đến máy chủ hoặc ngược lại. Cả hai cách này đều đặt ra
một số vấn đề cần xem xét:
1. Truyền Tham Biến (Pass by Value): Trong trường hợp này, giá trị của tham số được sao chép
gửi tới máy chủ. Bất kỳ thay đổi nào được thực hiện trên tham số trên máy chủ không ảnh hưởng
đến giá trị ban đầu trên máy khách.
2. Truyền Tham Chiếu (Pass by Reference): Trong trường hợp này, tham số là một tham chiếu
hoặc con trỏ trỏ tới dữ liệu thực sự. Bất kỳ thay đổi nào được thực hiện trên tham số trên máy chủ
cũng ảnh hưởng trực tiếp đến giá trị trên máy khách.
Vấn đề đối với truyền tham biến:
Tính toàn vẹn dữ liệu (Data Integrity): Trong trường hợp truyền tham biến, máy khách và máy chủ
hoạt động với bản sao của dữ liệu. Tuy nhiên, có nguy cơ dữ liệu trên máy khách và máy chủ có thể
trở nên không đồng bộ nếu máy chủ thực hiện thay đổi dữ liệu.
An ninh dữ liệu (Data Security): Dữ liệu truyền bằng truyền tham biến thể trở nên không an toàn
nếu thông tin nhạy cảm được gửi. Bất kỳ thay đổi dữ liệu nào trên máy chủ không thể kiểm soát
hoặc ảnh hưởng đến máy khách.
Vấn đề đối với truyền tham chiếu:
Tính toàn vẹn dữ liệu (Data Integrity): Truyền tham chiếu thể dẫn đến sự không đồng bộ giữa
máy khách và máy chủ nếu không được quản lý cẩn thận. Bất kỳ thay đổi trên máy chủ có thể ảnh
hưởng đến máy khách.
An ninh dữ liệu (Data Security): Truyền tham chiếu cung cấp sự linh hoạt cho việc truy cập
thay đổi dữ liệu, nhưng cũng đặt ra vấn đề về an ninh nếu không kiểm soát cẩn thận.
Giải pháp đưa ra:
Truyền tham biến: Một giải pháp đảm bảo tính toàn vẹn của dliệu bằng cách sao chép dữ liệu
trước khi gửi sau đó so sánh với phiên bản gốc sau khi thực hiện yêu cầu. Điều này giúp phát
hiện sự không đồng bộ và giảm thiểu rủi ro. Tuy nhiên, nó tốn thời gian và tài nguyên.
Truyền tham chiếu: Để đảm bảo tính toàn vẹn và an ninh dữ liệu, cần thiết phải cân nhắc và kiểm
soát cẩn thận việc thay đổi dữ liệu trên máy chủ và gửi thông tin nhạy cảm.
Lựa chọn giữa truyền tham biến và truyền tham chiếu phụ thuộc vào tình huống cụ thể và yêu cầu
an ninh và tính toàn vẹn của ứng dụng RPC.
Câu hỏi 16: So sánh RMI và RPC. Nhược điểm của RMI so với RPC là gì?
RMI (Remote Method Invocation) và RPC (Remote Procedure Call) đều là các công nghệ sử dụng
trong lập trình phân tán để gọi các hàm hoặc thủ tục trên các máy tính từ xa. Tuy nhiên, có sự khác
biệt quan trọng giữa chúng:
RMI (Remote Method Invocation):
lOMoARcPSD| 61552860
Ngôn ngữ Ưu Tiên: RMI thường liên quan chặt chẽ đến Java. một phần của nền tảng Java
và tương thích hoàn toàn với Java.
Tích hợp với Java: RMI dễ dàng tích hợp vào các ứng dụng Java và cho phép gọi các phương thức
của các đối tượng Java từ xa.
Khả năng Mô-đun Hóa: RMI cho phép bạn chia nhỏ ứng dụng thành c đối tượng gọi các
phương thức của chúng từ xa, tạo nên mô hình mô-đun hóa.
Hỗ trợ Marshalling Serialization: RMI hỗ trợ tự động chuyển đổi dữ liệu và đối tượng sang định
dạng thích hợp để truyền qua mạng.
RPC (Remote Procedure Call):
Ngôn Ngữ Đa Dạng: RPC không giới hạn trong việc sử dụng một ngôn ngữ cụ thể. Bạn thể
triển khai RPC trên nhiều ngôn ngữ khác nhau như C, C++, Python, và nhiều ngôn ngữ khác.
Tích hợp Đa Ngôn Ngữ: RPC cho phép gọi các hàm hoặc phương thức viết bằng nhiều ngôn ng
khác nhau.
Cộng đồng Lớn và Hỗ trợ Đa Nền Tảng: Có nhiều thư viện và khung làm việc với RPC, giúp bạn
tích hợp RPC vào các ứng dụng đa nền tảng.
Nhược điểm của RMI so với RPC:
Giới hạn về Ngôn ngữ: Một nhược điểm lớn của RMI là nó được hạn chế trong việc sử dụng ngôn
ngữ. Nếu bạn muốn tích hợp các phần của ứng dụng viết bằng các ngôn ngữ khác với Java, RMI sẽ
gặp khó khăn.
Khả năng Mô-đun Hóa Hạn Chế: Mặc dù RMI cho phép mô-đun hóa ứng dụng bằng cách gọi c
phương thức từ xa, nhưng nó không linh hoạt bằng RPC trong việc tích hợp các ứng dụng viết bằng
nhiều ngôn ngữ khác nhau.
Phụ thuộc vào Java: RMI là một phần của nền tảng Java, vì vậy nó đòi hỏi máy chủ và máy khách
đều phải chạy Java. Điều này giới hạn tính linh hoạt và khả năng sử dụng trong các môi trường đa
ngôn ngữ và đa nền tảng.
Tóm lại, RMI tiêu biểu cho tích hợp trong một môi trường Java đòi hỏi máy chủ máy khách
cùng chạy Java. RPC có khả năng hoạt động đa ngôn ngữ và đa nền tảng, điều này giúp nó phù hợp
với các ứng dụng phân tán lớn và đa dạng.
Câu hỏi 17: Hàm listen được sử dụng bởi TCP server tham số backlog. Giải thích ý nghĩa
tham số đó.
Tham số backlog trong hàm listen của một TCP server là một chỉ số xác định mức độ backlog (hàng
đợi) cho các kết nối đang chờ xử lý. Tham số này quy định số lượng kết nối đang chờ được duyệt
và xử lý bởi máy chủ.
Khi một máy khách cố gắng kết nối đến máy chủ thông qua giao thức TCP, máy chủ sẽ sử dụng
hàm listen để lắng nghe các yêu cầu kết nối đến. Tuy nhiên, không phải tất cả các yêu cầu kết nối
có thể được xử lý ngay lập tức. Điều này có thể xảy ra khi máy chủ đã bận hoặc đang xử lý kết nối
khác.
lOMoARcPSD| 61552860
backlog xác định số lượng kết nối máy chủ thể chấp nhận đồng thời trong hàng đợi đợi xử
lý. Nếu số lượng yêu cầu kết nối đến nhiều hơn backlog, các yêu cầu vượt quá sẽ bị từ chối. Tham
số này đảm bảo rằng máy chủ không quá tải bằng cách giới hạn số lượng kết nối đang chờ xử lý.
Nếu backlog được đặt thành một giá trị cụ thể, ví dụ backlog = 10, thì máy chủ sẽ duyệt và xử
tối đa 10 kết nối cùng một lúc và từ chối các kết nối thêm vào khi hàng đợi đã đầy.
Nhưng cần lưu ý rằng giá trị cụ thể của backlog phụ thuộc vào tài nguyên của máy chủ và yêu cầu
cụ thể của ứng dụng. Nếu bạn đặt backlog quá thấp, máy chủ có thể bị quá tải và từ chối kết nối quá
nhanh. Ngược lại, nếu bạn đặt backlog quá cao, điều này có thể làm tăng tiêu tốn tài nguyên và làm
cho máy chủ trở nên không hiệu quả. Chọn giá trị backlog phải cân nhắc dựa trên nhu cầu cụ thể
của ứng dụng và tài nguyên của máy chủ.
Câu hỏi 18: Trong trao đổi thông tin hướng dòng, những chế thực thi QoS được thực hiện
tầng nào? Giải thích. Trình bày một số cơ chế thực thi QoS để chứng minh điều đó.
Trong hình trao đổi thông tin hướng dòng (unicast) giữa máy tính máy chủ, cơ chế thực thi
QoS (Quality of Service - Chất lượng Dịch vụ) được triển khai chủ yếu tại tầng 3 (tầng Network)
của hình phân tầng OSI. QoS một tập hợp các tiêu chuẩn quy tắc được thiết lập để đảm
bảo chất lượng dịch vụ và hiệu suất tối ưu trong việc truyền tải dữ liệu qua mạng. Dưới đây là một
số cơ chế thực thi QoS ở tầng Network và giải thích cách chúng hoạt động:
Phân Ưu Tiên (Priority Queuing): chế này cho phép bạn xác định các ưu tiên cho các gói dữ
liệu. Các gói dữ liệu được sắp xếp trong hàng đợi theo mức ưu tiên, và các gói có mức ưu tiên cao
sẽ được xử lý trước. Điều này đảm bảo rằng các dịch vụ quan trọng như thoại trực tiếp có thể được
ưu tiên hơn so với dịch vụ không quan trọng.
Điều chỉnh Tốc Độ (Traffic Shaping): Cơ chế này được sử dụng để kiểm soát tốc độ dữ liệu truyền
qua mạng. Nó giúp kiểm soát và giảm đột ngột sự cộng tác của dịch vụ, ngăn chặn quá tải mạng và
đảm bảo dịch vụ ổn định.
Cắt Giữa (Policing): Cơ chế này kiểm tra lưu lượng dữ liệu đang đi qua và thực hiện các biện pháp
như loại bỏ gói dữ liệu không hợp lệ hoặc quá nhiều gói dữ liệu trong một khoảng thời gian cố định.
Quản Lý Rộng Băng Tuyệt Đối (CBWFQ - Class-Based Weighted Fair Queuing): chế này cho
phép bạn gán ưu tiên và quản lý dịch vụ dựa trên các lớp cụ thể. Các lớp này có thể được xác định
dựa trên các tiêu chí như loại ứng dụng hoặc địa chỉ IP và được gán một lượng băng thông cố định.
Kéo Dài Kiểm Soát (Congestion Control): Cơ chế này giúp kiểm soát hiện tượng quá tải mạng. Khi
mạng gặp nguy cơ quá tải, nó có thể điều chỉnh tốc độ truyền dữ liệu hoặc giảm độ ưu tiên của dịch
vụ không quan trọng.
Các cơ chế QoS này được triển khai để đảm bảo rằng các dịch vụ quan trọng như thoại, video trực
tiếp hoặc ứng dụng yêu cầu băng thông cao thể hoạt động một cách ổn định chất lượng cao,
trong khi đảm bảo rằng các dịch vụ không quan trọng không chiếm quá nhiều tài nguyên và không
làm ảnh hưởng đến hiệu suất tổng thể của mạng

Preview text:

lOMoAR cPSD| 61552860 BÀI TẬP TRÊN LỚP
MÔN HỌC: HỆ PHÂN TÁN
CHƯƠNG 2: TIẾN TRÌNH VÀ TRAO ĐỔI THÔNG TIN TRONG HPT
HỌ TÊN SV:Nguyễn Xuân Sơn MSSV:20204778 MÃ LỚP:144944 MÃ HỌC PHẦN:IT4611
Câu hỏi 1: Có cần thiết phải giới hạn số lượng các luồng trong một tiến trình server?
Việc giới hạn số lượng luồng (threads) trong một tiến trình server phụ thuộc vào nhiều yếu tố, và
không có một quy tắc cố định nào áp dụng cho mọi tình huống. Có một số yếu tố mà bạn nên xem
xét khi quyết định xem có cần thiết giới hạn số lượng luồng trong tiến trình server của bạn hay không
Tùy thuộc vào ứng dụng cụ thể của bạn và yêu cầu của nó, bạn có thể quyết định xem có cần giới
hạn số lượng luồng hay không. Việc này nên được thực hiện sau khi tiến hành kiểm tra hiệu suất và
sử dụng tài nguyên trong môi trường ứng dụng thực tế. Điều quan trọng là đảm bảo rằng tiến trình
server hoạt động ổn định, hiệu quả và không tiêu tốn quá nhiều tài nguyên.
Câu hỏi 2: Có nên chỉ gắn một luồng đơn duy nhất với một tiến trình nhẹ?
Gắn một luồng đơn duy nhất với một tiến trình nhẹ (lightweight process) là một cách tiếp cận có
thể hữu ích trong một số tình huống, nhưng không phải lúc nào cũng là tối ưu. Quyết định này phụ
thuộc vào nhiều yếu tố và mục tiêu cụ thể của ứng dụng của bạn.Tuy nhiên, cần lưu ý rằng việc sử
dụng nhiều tiến trình nhẹ cũng có nhược điểm, như tăng sự phức tạp của mã nguồn và tăng sử dụng
tài nguyên hệ thống. Quyết định nên sử dụng mô hình một luồng một tiến trình nhẹ hay không phụ
thuộc vào yêu cầu cụ thể của ứng dụng và các yếu tố hiệu suất, bảo mật, và quản lý.
Câu hỏi 3: Có nên chỉ có một tiến trình nhẹ đơn gắn với 1 tiến trình?
Gắn một tiến trình nhẹ (lightweight process) đơn với một tiến trình (process) là một mô hình thực
hiện được trong các hệ thống đa tiến trình hoặc đa luồng, và có thể hữu ích trong một số tình huống,
nhưng nó phụ thuộc vào mục tiêu cụ thể của ứng dụng và yêu cầu của nó.Tuy nhiên, cần lưu ý rằng
việc gắn một tiến trình nhẹ đơn với mỗi tiến trình có thể tạo ra một overhead về tài nguyên, do đó,
cần xem xét mục tiêu cụ thể của ứng dụng và tài nguyên có sẵn trên hệ thống. Mô hình này thường
được sử dụng trong các hệ thống phân tán hoặc các ứng dụng yêu cầu tính cách ly cao giữa các phần của mã nguồn.
Câu hỏi 4: Bài toán này yêu cầu bạn so sánh thời gian đọc một tệp (file) của một máy chủ tập tin
(file server) đơn luồng và một máy chủ đa luồng. Phải mất tổng cộng 15 ms để nhận 1 yêu cầu
(request) và thực hiện quá trình xử lý, giả định rằng các dữ liệu cần thiết nằm ở bộ nhớ đệm trong
bộ nhớ chính. Nếu cần thiết phải thực hiện một thao tác truy cập ổ đĩa thì cần thêm 75 ms, biết
rằng việc phải thực hiện thao tác này có xắc suất là 1/3. Hỏi máy chủ có thể nhận bao nhiêu yêu
cầu/giây trong 2 trường hợp: máy chủ là đơn luồng và máy chủ là đa luồng (ngoài luồng nhận và
xử lý request, sẽ có thêm 1 luồng để truy cập ổ đĩa nếu cần thiết)? Giải thích.
Để tính toán máy chủ có thể nhận được bao nhiêu yêu cầu/giây trong hai trường hợp: máy chủ đơn
luồng và máy chủ đa luồng, chúng ta sẽ sử dụng thông tin về thời gian trả lời yêu cầu (response
time) và xác suất yêu cầu cần thêm thời gian truy cập ổ đĩa. 1. Máy chủ đơn luồng: lOMoAR cPSD| 61552860
Thời gian xử lý yêu cầu trong trường hợp tệp (file) nằm trong bộ nhớ chính: 15 ms.
Xác suất cần thực hiện thao tác truy cập ổ đĩa: 1/3.
Thời gian thực hiện thao tác truy cập ổ đĩa (75 ms) cộng thêm vào thời gian xử lý trong trường hợp
không cần truy cập ổ đĩa (15 ms):
Trong trường hợp cần truy cập ổ đĩa: 15 ms (xử lý) + 75 ms (truy cập ổ đĩa) = 90 ms.
Trong trường hợp không cần truy cập ổ đĩa: 15 ms (xử lý).
Giờ ta sẽ tính trung bình thời gian xử lý một yêu cầu:
Thời gian trung bình = (Xác suất cần truy cập ổ đĩa) * (Thời gian xử lý khi cần truy cập ổ đĩa) +
(Xác suất không cần truy cập ổ đĩa) * (Thời gian xử lý khi không cần truy cập ổ đĩa) Thời gian
trung bình = (1/3) * 90 ms + (2/3) * 15 ms = 45 ms + 10 ms = 55 ms.
Bây giờ, chúng ta có thể tính số yêu cầu mà máy chủ đơn luồng có thể nhận trong 1 giây:
Số yêu cầu/giây = 1000 ms / Thời gian trung bình = 1000 ms / 55 ms ≈ 18.18 yêu cầu/giây. 2. Máy chủ đa luồng:
Trong trường hợp máy chủ đa luồng, chúng ta có thêm một luồng để thực hiện thao tác truy cập ổ
đĩa. Tuy nhiên, điều quan trọng là luồng truy cập ổ đĩa và luồng xử lý yêu cầu chính phải hoạt động đồng thời.
Thời gian xử lý một yêu cầu trong trường hợp tệp nằm trong bộ nhớ chính là 15 ms. Tuy nhiên,
với việc thêm luồng truy cập ổ đĩa, chúng ta cần cộng thời gian xử lý trong cả hai luồng lại với
nhau để tính toán thời gian trung bình.
Thời gian trung bình = Thời gian xử lý yêu cầu chính + Thời gian xử lý luồng truy cập ổ đĩa Thời
gian trung bình = 15 ms + 15 ms = 30 ms.
Số yêu cầu/giây = 1000 ms / Thời gian trung bình = 1000 ms / 30 ms ≈ 33.33 yêu cầu/giây.
Vậy, trong trường hợp máy chủ đa luồng, máy chủ có thể nhận được khoảng 33.33 yêu cầu/giây. lOMoAR cPSD| 61552860
Tóm lại, máy chủ đa luồng có thể xử lý nhiều yêu cầu hơn mỗi giây so với máy chủ đơn luồng
trong tình huống này với điều kiện rằng luồng truy cập ổ đĩa và luồng xử lý chính có thể hoạt động đồng thời.
Câu hỏi 5: Hệ thống X chỉ định máy của user chưa server, trong khi các ứng dụng lại được coi như
client. Điều đó có vô lý không? Giải thích.
Không, việc đặt máy của người dùng (user) là máy chủ (server) trong một hệ thống không phải lúc
nào cũng vô lý, và nó có thể được thiết kế như vậy để đáp ứng mục tiêu cụ thể của hệ thống. Cách
này có thể hợp lý trong một số tình huống. Dưới đây là một số lý do giải thích:
Tính phân tán và hiệu suất: Trong một số kiến trúc hệ thống phân tán, máy của người dùng (user)
có thể đóng vai trò như một máy chủ phân phối dữ liệu hoặc tài nguyên cho các máy khác. Điều
này có thể giúp phân tải và cải thiện hiệu suất của hệ thống bằng cách sử dụng tài nguyên cục bộ
thay vì phải truy cập máy chủ trung tâm từ xa.
Kiến trúc ngang hàng (Peer-to-Peer): Trong các mạng kiến trúc ngang hàng, máy của người dùng
không phải lúc nào cũng chỉ đóng vai trò client. Các máy trong mạng có thể cùng chia sẻ tài nguyên
và dữ liệu với nhau, và không có máy chủ trung tâm. Ví dụ, các ứng dụng torrent thường sử dụng mô hình này.
Tối ưu hóa việc truy cập dữ liệu cục bộ: Trong trường hợp dữ liệu cần được truy cập nhanh chóng
và tối ưu từ máy người dùng, việc sử dụng máy người dùng như một máy chủ có thể giảm độ trễ
và tăng hiệu suất, đặc biệt khi dữ liệu được lưu trữ cục bộ.
Bảo mật và quản lý dữ liệu: Người dùng có thể muốn kiểm soát và bảo mật dữ liệu của họ bằng
cách tự quản lý máy chủ của họ. Điều này đặc biệt quan trọng trong các ứng dụng yêu cầu mức độ
kiểm soát cao và bảo mật.
Tùy thuộc vào mục tiêu cụ thể của hệ thống và cách thiết kế, việc đặt máy của người dùng là máy
chủ có thể hợp lý và không vô lý. Quan trọng nhất là đảm bảo rằng kiến trúc này đáp ứng được
yêu cầu và mục tiêu của hệ thống một cách hiệu quả và an toàn.
Câu hỏi 6: Giao thức thiết kế cho hệ thống X gặp phải vấn đề về tính mở rộng. Chỉ ra các giải pháp
để giải quyết vấn đề đó?
Việc giải quyết vấn đề về tính mở rộng trong thiết kế giao thức cho hệ thống X là rất quan trọng
để đảm bảo rằng hệ thống có thể mở rộng dễ dàng khi cần thiết, đồng thời đảm bảo hiệu suất và
tính nhất quán. Dưới đây là một số giải pháp để giải quyết vấn đề về tính mở rộng:
Sử dụng kiến trúc phân tán: Một kiến trúc phân tán cho phép bạn chia nhỏ hệ thống thành các
thành phần độc lập mà có thể mở rộng riêng lẻ. Mỗi thành phần có thể tồn tại trên các máy chủ
riêng biệt, cho phép bạn mở rộng từng phần của hệ thống một cách độc lập.
Cân bằng tải (Load Balancing): Sử dụng giải pháp cân bằng tải giữa các máy chủ để phân phối tải
đều đặn giữa các thành phần của hệ thống. Điều này giúp tăng hiệu suất và đảm bảo tính mở rộng
dễ dàng bằng cách thêm máy chủ khi tải tăng.
Dịch vụ dự phòng (Redundancy): Sử dụng dịch vụ dự phòng để đảm bảo tính sẵn sàng và giảm
nguy cơ mất mát dữ liệu. Khi một máy chủ hoặc thành phần gặp sự cố, dịch vụ dự phòng có thể
tiếp quản và giữ hệ thống hoạt động. lOMoAR cPSD| 61552860
Tạo dự phòng dữ liệu (Data Replication): Sao lưu và sao chép dữ liệu đến nhiều máy chủ để đảm
bảo tính nhất quán và sẵn sàng dữ liệu. Các cơ sở dữ liệu phân phối có thể hữu ích để giải quyết vấn đề này.
Quản lý phiên (Session Management): Để đảm bảo tính nhất quán của phiên người dùng, quản lý
phiên có thể được thực hiện bằng cách sử dụng phiên đám mây hoặc phiên dự phòng giữa các máy chủ.
Tích hợp dịch vụ công cộng (Public Cloud Integration): Sử dụng các dịch vụ đám mây công cộng
(ví dụ: AWS, Azure, Google Cloud) để mở rộng hệ thống theo yêu cầu. Điều này cho phép bạn mở
rộng nhanh chóng và hiệu quả mà không phải mua thêm phần cứng vật lý.
Sử dụng công nghệ container và orchestration: Các công nghệ như Docker và Kubernetes cho phép
bạn đóng gói ứng dụng và quản lý chúng trên các máy chủ một cách hiệu quả. Điều này giúp tạo
ra một môi trường mở rộng và dễ quản lý.
Tối ưu hóa cơ sở dữ liệu: Sử dụng cơ sở dữ liệu phân phối hoặc cơ sở dữ liệu NoSQL để tối ưu
hóa việc quản lý dữ liệu và mở rộng dự án.
Sử dụng giao thức RESTful và API: Sử dụng RESTful APIs cho phép các ứng dụng khác giao tiếp
và tương tác với hệ thống của bạn một cách dễ dàng, đồng thời mở rộng dự án.
Sử dụng auto-scaling: Sử dụng công cụ tự động mở rộng để tự động thêm hoặc giảm số máy chủ dựa trên tải.
Những giải pháp trên có thể được kết hợp và tùy chỉnh để đáp ứng yêu cầu cụ thể của hệ thống và tình huống mở rộng.
Câu hỏi 7: Với việc xây dựng một server đồng thời, hãy so sánh việc server này tạo một luồng mới
và tạo một tiến trình mới khi nhận được yêu cầu từ phía client.
Khi bạn xây dựng một server đồng thời, việc quyết định liệu nên tạo một luồng mới hay một tiến
trình mới khi nhận được yêu cầu từ phía client phụ thuộc vào mục tiêu cụ thể của ứng dụng và yêu
cầu hiệu suất. Dưới đây là một so sánh giữa việc tạo luồng mới và tạo tiến trình mới trong ngữ cảnh này:
Tạo luồng mới (Multithreading):
Tối ưu cho I/O-bound tasks: Khi ứng dụng chủ yếu thực hiện các hoạt động I/O-bound như đọc/ghi
dữ liệu từ/đến ổ đĩa hoặc giao tiếp mạng, việc sử dụng luồng mới có thể tối ưu hơn. Luồng có thể
được tạo và quản lý một cách hiệu quả hơn so với tiến trình.
Không tiêu tốn nhiều tài nguyên hệ thống: Luồng sử dụng ít tài nguyên hệ thống hơn so với tiến
trình, vì chúng chia sẻ cùng không gian địa chỉ và các tài nguyên khác.
Dễ dàng chia sẻ dữ liệu: Luồng trong cùng một tiến trình có thể chia sẻ dữ liệu dễ dàng. Điều này
có thể hữu ích khi cần chia sẻ dữ liệu giữa các yêu cầu.
Tạo tiến trình mới (Multiprocessing): lOMoAR cPSD| 61552860
Tối ưu cho CPU-bound tasks: Khi ứng dụng thực hiện các tác vụ CPU-bound phức tạp và đòi hỏi
nhiều tính toán, tạo một tiến trình mới có thể tối ưu hơn. Mỗi tiến trình có thể sử dụng một lõi CPU
riêng biệt, tận dụng tối đa hiệu suất đa lõi của hệ thống.
Tách biệt và an toàn: Mỗi tiến trình có không gian địa chỉ riêng, điều này giúp đảm bảo tính tách
biệt và an toàn. Lỗi trong một tiến trình không ảnh hưởng đến các tiến trình khác.
Tích hợp với các ngôn ngữ và thư viện nhiều tiến trình (Multiprocessing Libraries): Các ngôn ngữ
và thư viện hỗ trợ tạo và quản lý tiến trình dễ dàng hơn. Ví dụ, Python có thư viện multiprocessing cho việc này.
Tóm lại, việc chọn giữa tạo luồng mới và tạo tiến trình mới phụ thuộc vào loại công việc mà server
của bạn cần thực hiện. Nếu nó chủ yếu là I/O-bound và cần hiệu suất tốt, sử dụng luồng mới có
thể là lựa chọn. Nếu nó là CPU-bound hoặc yêu cầu tính tách biệt cao, thì tạo tiến trình mới có thể
là lựa chọn tốt hơn. Đôi khi, việc kết hợp cả hai có thể là giải pháp tốt nhất, tùy thuộc vào tình huống cụ thể.
Câu hỏi 8: Nếu bây giờ một webserver tổ chức lưu lại thông tin về địa chỉ IP của client và trang
web client đó vừa truy cập. Khi có 1 client kết nối với server đó, server sẽ tra xem trong bảng
thông tin, nếu tìm thấy thì sẽ gửi nội dung trang web đó cho client. Server này là có trạng thái
(stateful) hay không trạng thái (stateless)?
Một server được coi là có trạng thái (stateful) trong trường hợp này, vì nó duy trì thông tin về trạng
thái của các kết nối trước đó. Trạng thái ở đây được thể hiện thông qua việc lưu lại thông tin về
địa chỉ IP của client và trang web mà client truy cập. Khi một client kết nối với server, server kiểm
tra bảng thông tin của mình để xác định trang web mà client đã truy cập trước đó và gửi nội dung trang web đó cho client.
Một server stateful là server có khả năng duy trì thông tin về trạng thái của các kết nối trước đó và
sử dụng thông tin này để phục vụ các yêu cầu sau này. Điều này có thể là hữu ích trong nhiều
trường hợp, như quản lý phiên của người dùng, theo dõi dữ liệu liên quan đến người dùng, hoặc
cung cấp các tính năng tương tác phức tạp dựa trên lịch sử của client.
Trong khi server stateful có lợi ích về tính nhất quán và quản lý trạng thái, nó cũng đặt ra các thách
thức về quản lý trạng thái, khả năng mở rộng và bảo mật. Server stateless (không trạng thái) thường
đơn giản hơn và dễ quản lý hơn, nhưng không thể theo dõi trạng thái của các kết nối trước đó. Việc
sử dụng server stateful hay stateless phụ thuộc vào yêu cầu cụ thể của ứng dụng và các ưu tiên của bạn.
Câu hỏi 9: So sánh Docker và Virtual Machine.
Docker và Virtual Machine (VM) là hai công nghệ phổ biến trong việc tạo môi trường ảo để chạy
ứng dụng. Mặc dù cả hai có mục tiêu chung là cung cấp một cách để đóng gói và chạy ứng dụng
trong môi trường cách ly, chúng có sự khác biệt quan trọng về cách hoạt động và mức độ tài nguyên
tiêu tốn. Dưới đây là một so sánh giữa Docker và Virtual Machine: 1. Kiến trúc:
Docker: Docker sử dụng kiến trúc container, nơi các ứng dụng và phụ thuộc của chúng chia sẻ hạt
nhân của hệ điều hành máy chủ chủ. Container Docker chạy trực tiếp trên hệ điều hành và sử dụng
một lớp gọi là Docker Engine để quản lý chúng. lOMoAR cPSD| 61552860
Virtual Machine: VMs là các máy ảo độc lập hoàn toàn và chứa cả hệ điều hành và ứng dụng của
riêng chúng. Chúng chạy trên một hypervisor, là một lớp trung gian giữa VM và phần cứng vật lý. 2. Tài nguyên:
Docker: Containers sử dụng ít tài nguyên hơn so với VMs. Chúng cần ít dung lượng đĩa và bộ nhớ
hơn, vì chúng chia sẻ hạt nhân và các thư viện với hệ điều hành máy chủ.
Virtual Machine: VMs tiêu tốn nhiều tài nguyên hơn do mỗi VM có một hệ điều hành riêng và phải
chia sẻ phần cứng vật lý với các VM khác.
3. Khởi động và thời gian tắt:
Docker: Containers khởi động và tắt nhanh chóng do chúng chia sẻ hạt nhân với hệ điều hành máy chủ.
Virtual Machine: VMs cần nhiều thời gian hơn để khởi động và tắt do việc khởi động toàn bộ hệ điều hành của VM.
4. Tích hợp và triển khai:
Docker: Docker containers dễ tích hợp và triển khai. Chúng có thể được đóng gói một cách dễ dàng
trong hình ảnh Docker và chia sẻ qua Docker Hub.
Virtual Machine: VMs có thể được triển khai bằng cách sao lưu và phục hồi toàn bộ hệ thống máy
ảo. Việc này có thể tốn thời gian hơn và phức tạp hơn. 5. Độ cô lập:
Docker: Docker containers cung cấp độ cô lập tương đối. Chúng chia sẻ hạt nhân với hệ điều hành máy chủ.
Virtual Machine: VMs cung cấp độ cô lập hoàn toàn. Mỗi VM có hệ điều hành và phần mềm cài đặt riêng biệt.
6. Môi trường đa nền tảng:
Docker: Docker containers hỗ trợ đa nền tảng và có thể chạy trên nhiều hệ điều hành máy chủ khác nhau.
Virtual Machine: VMs thường yêu cầu sử dụng hypervisor phù hợp với hệ điều hành máy chủ.
Tóm lại, Docker và Virtual Machine đều có ứng dụng riêng của họ trong các tình huống cụ thể.
Docker thích hợp cho việc đóng gói và triển khai ứng dụng một cách dễ dàng và hiệu quả, trong khi
Virtual Machine thích hợp cho việc cung cấp độ cô lập hoàn toàn và chạy nhiều hệ điều hành khác
nhau trên cùng một máy chủ vật lý.
Câu hỏi 10: Trong các giao thức phân tầng, mỗi tầng sẽ có một header riêng. Vậy có nên triển
khai một hệ thống mà tất cả các header của các tầng đưa chung vào một phần (gọi là header chung),
gắn vào đầu mỗi thông điệp để có thể xử lý chung? Giải thích. lOMoAR cPSD| 61552860
Việc triển khai một hệ thống mà tất cả các header của các tầng được đưa chung vào một phần gọi là
"header chung" để xử lý chung có thể là một giải pháp hợp lý trong một số trường hợp, nhưng cần
xem xét một số vấn đề quan trọng trước khi quyết định triển khai cách tiếp cận này.
Dưới đây là một số điểm cần xem xét:
1. Mục tiêu và cơ sở giao thức:
Nếu hệ thống của bạn chủ yếu sử dụng các giao thức có sẵn và đã được thiết kế với cơ sở giao thức
cụ thể (ví dụ: TCP/IP), việc tách biệt các tầng và header của chúng có thể là cách tiếp cận tốt hơn
để duy trì tính nhất quán và tương thích với các giao thức hiện có. 2. Quản lý và bảo trì:
Khi tất cả các header được đưa vào một phần chung, việc quản lý và bảo trì hệ thống có thể trở
nên phức tạp. Điều này đặc biệt đúng khi bạn cần thêm hay cập nhật các tầng hoặc header mới. 3. Hiệu suất:
Việc xử lý các header chung có thể gây ra overhead trong việc đọc và xử lý thông điệp. Một header
chung phải chứa đủ thông tin để xác định loại giao thức, cổng đích, địa chỉ IP, v.v. Việc này có thể
làm gia tăng độ trễ và tiêu tốn tài nguyên máy tính. 4. Bảo mật:
Việc đưa tất cả thông tin vào một header chung có thể đặt ra các vấn đề về bảo mật. Trong một số
trường hợp, các tầng phân tầng cung cấp lớp bảo mật bổ sung, và việc tổng hợp các header có thể
tạo ra lỗ hổng bảo mật. 5. Tích hợp với giao thức hiện có:
Một số giao thức có thể không dễ dàng tích hợp với mô hình header chung. Một số giao thức có
cấu trúc phân tầng cụ thể cho việc đọc và xử lý thông điệp. 6. Tính linh hoạt:
Tùy thuộc vào yêu cầu và tình huống cụ thể của ứng dụng, việc tách biệt các header có thể cho
phép tùy chỉnh một cách dễ dàng cho từng tầng mà không ảnh hưởng đến các tầng khác. Tóm lại,
việc quyết định có nên triển khai hệ thống với "header chung" hay không phụ thuộc vào yêu cầu
và mục tiêu cụ thể của ứng dụng. Trong một số tình huống, việc sử dụng header chung có thể giảm
độ phức tạp và tối ưu hóa quản lý, trong khi trong những trường hợp khác, việc giữ nguyên cấu
trúc giao thức phân tầng là tối ưu hơn để đảm bảo tính nhất quán, bảo mật và hiệu suất.
Câu hỏi 11: Xét 1 thủ tục incr với 2 tham số nguyên. Thủ tục làm nhiệm vụ là cộng 1 đơn vị vào
mỗi tham số. Bây giờ xét trường hợp chúng ta gọi thủ tục đó với cùng một biến, ví dụ incr(i, i).
Nếu biến i được khởi tạo giá trị 0, vậy giá trị của i sẽ là bao nhiêu sau khi gọi thủ tục này trong 2 trường hợp sau: - Lời gọi tham chiếu
- Phương pháp sao chép-phục hồi được sử dụng.
Trong trường hợp bạn gọi thủ tục incr(i, i) với một biến i ban đầu có giá trị là 0, hãy xem xét cả hai trường hợp:
1. Tham chiếu (Call by Reference): lOMoAR cPSD| 61552860
Trong trường hợp này, cả hai tham số i đều trỏ đến cùng một vùng bộ nhớ, và khi bạn gọi thủ tục
incr, cả hai tham số đều tương tác với cùng một biến trong bộ nhớ. Ban đầu: i = 0
Gọi thủ tục incr(i, i): Cả hai tham số trỏ đến cùng một biến, và giá trị của biến được tăng lên 1. Sau
khi gọi thủ tục này, i sẽ là 1.
2. Sao chép-Phục hồi (Call by Value):
Trong trường hợp này, mỗi tham số i được sao chép vào một biến tạm thời và thủ tục incr sẽ tương
tác với các biến tạm thời này. Ban đầu: i = 0
Gọi thủ tục incr(i, i): Cả hai tham số i được sao chép vào các biến tạm thời riêng biệt, và thủ tục incr
tương tác với các biến tạm thời này. Do đó, giá trị của i không thay đổi sau khi gọi thủ tục này. Sau thủ tục, i vẫn là 0.
Vì vậy, trong trường hợp tham chiếu, giá trị của i sau khi gọi thủ tục là 1, trong khi trong trường hợp
sao chép-Phục hồi, giá trị của i vẫn là 0. lOMoAR cPSD| 61552860
Câu hỏi 12: Một kết nối socket cần 4 thông tin nào? Tại sao phải cần đủ 4 thông tin đó? Một
kết nối socket cần bốn thông tin cơ bản sau:
Địa chỉ IP nguồn: Đây là địa chỉ IP của máy gửi dữ liệu hoặc thiết bị mà bạn đang sử dụng để thiết
lập kết nối. Đây là địa chỉ của máy gửi dữ liệu và là nguồn của kết nối.
Cổng nguồn: Cổng nguồn là một số cụ thể trên máy gửi dữ liệu. Nó giúp máy chủ hoặc máy đích
xác định ứng dụng mà dữ liệu đang đến và cần được định tuyến tới. Mỗi ứng dụng trên máy tính sẽ
lắng nghe trên một cổng cụ thể để có thể nhận dữ liệu.
Địa chỉ IP đích: Đây là địa chỉ IP của máy chủ hoặc thiết bị đích mà bạn đang cố gắng kết nối đến.
Đây là đích của kết nối.
Cổng đích: Cổng đích là cổng trên máy chủ hoặc máy đích mà dữ liệu cố gắng truyền đến. Nó giúp
máy chủ xác định ứng dụng mà dữ liệu nên được gửi tới.
Tại sao cần đủ cả bốn thông tin này:
Địa chỉ IP nguồn và cổng nguồn: Chúng xác định máy gửi dữ liệu và ứng dụng nguồn. Điều này
quan trọng để máy chủ biết phản hồi về đúng máy gửi và ứng dụng.
Địa chỉ IP đích và cổng đích: Chúng xác định máy chủ hoặc máy đích và ứng dụng mà dữ liệu cố
gắng kết nối đến. Nó cho phép máy chủ xác định đích của dữ liệu và định tuyến nó tới ứng dụng tương ứng.
Các thông tin này là quan trọng để định rõ nguồn và đích của dữ liệu trong quá trình truyền thông
qua mạng và đảm bảo rằng nó được định tuyến và gửi tới đúng ứng dụng và máy tính.
Câu hỏi 13: Tại sao giao thức yêu cầu-trả lời (request-reply) lại được coi là đồng bộ tin cậy?
Giao thức yêu cầu-trả lời (request-reply protocol) thường được coi là đồng bộ và tin cậy vì nó thiết
lập một quy trình tương tác giữa hai thực thể hoặc hệ thống mà yêu cầu một phản hồi xác nhận sau
khi gửi một yêu cầu. Dưới đây là một số lý do: 1.
Đảm bảo tính nhất quán: Trong giao thức yêu cầu-trả lời, người gửi yêu cầu không tiếp tục
thựchiện bất kỳ hành động nào khác cho đến khi nhận được phản hồi từ bên đích. Điều này đảm
bảo tính nhất quán trong quá trình giao tiếp, vì nó yêu cầu một hành động được hoàn thành trước
khi bắt đầu hành động tiếp theo. 2.
Đảm bảo tin cậy: Trong giao thức yêu cầu-trả lời, sự tin cậy đòi hỏi rằng bên gửi yêu cầu chỉ
kết thúc quá trình sau khi nhận được phản hồi xác nhận từ bên đích. Nếu không nhận được phản hồi
hoặc phản hồi bị lỗi, gửi lại yêu cầu có thể được thực hiện để đảm bảo rằng yêu cầu cuối cùng được
xử lý một cách đúng đắn. 3.
Xác định được quy trình giao tiếp: Giao thức yêu cầu-trả lời định rõ một quy trình cụ thể cho
việc giao tiếp giữa hai bên. Người gửi yêu cầu biết rõ khi nào nên gửi yêu cầu, và bên đích biết rõ
cách phản hồi. Điều này giúp giảm thiểu sự nhầm lẫn và tạo ra sự rõ ràng trong quá trình giao tiếp. lOMoAR cPSD| 61552860 4.
Hỗ trợ kiểm soát lỗi và khôi phục: Giao thức yêu cầu-trả lời cung cấp một cơ chế cho việc
xử lýlỗi và khôi phục sau lỗi. Nếu xảy ra lỗi trong quá trình giao tiếp, bên gửi có thể thực hiện lại
yêu cầu hoặc thực hiện các biện pháp khôi phục khác để đảm bảo tính tin cậy.
Tóm lại, giao thức yêu cầu-trả lời được coi là đồng bộ và tin cậy bởi vì nó đảm bảo tính nhất quán,
đảm bảo sự tin cậy trong giao tiếp, định rõ quy trình giao tiếp và cung cấp khả năng kiểm soát lỗi
và khôi phục. Điều này rất quan trọng trong nhiều ứng dụng và hệ thống nơi độ tin cậy và độ nhất
quán là yếu tố quan trọng.
Câu hỏi 14: Hai vấn đề chính đối với giao thức RPC là gì?
Giao thức RPC (Remote Procedure Call) là một cách để một ứng dụng gọi một hàm hoặc thủ tục
trên một máy tính từ xa như nó đang chạy trên máy tính cục bộ. Tuy nhiên, khi triển khai và sử dụng
giao thức RPC, có hai vấn đề chính cần quan tâm:
Tính nhất quán (Consistency): Vấn đề này liên quan đến việc đảm bảo tính nhất quán dữ liệu giữa
hai máy tính tham gia trong giao thức RPC. Điều này đặc biệt quan trọng khi một hàm hoặc thủ tục
được gọi từ xa, và sau đó máy chủ phải cung cấp một kết quả đúng và nhất quán cho máy khách.
Giải quyết xung đột dữ liệu (Data Conflicts): Đôi khi, hai máy tính có thể cố gắng cập nhật cùng
một dữ liệu tại cùng một thời điểm, gây ra xung đột dữ liệu. Cách giải quyết xung đột này là một
vấn đề quan trọng, và cần phải sử dụng các giải pháp như khóa, semaphores, hoặc phiên bản dữ liệu
(versioning) để đảm bảo tính nhất quán.
Quản lý trạng thái: Một hàm hoặc thủ tục có thể thay đổi trạng thái của máy chủ. Điều này đặt ra
câu hỏi về cách quản lý trạng thái và đảm bảo tính nhất quán trong hệ thống.
Bảo mật (Security): Vấn đề bảo mật là một thách thức lớn trong giao thức RPC. Vì dữ liệu và mã
được gửi qua mạng, cần xác minh người gửi và đảm bảo tính toàn vẹn của dữ liệu trước khi nó được
chấp nhận bởi máy chủ.
Xác thực (Authentication): Xác thực người gửi là một bước quan trọng để đảm bảo rằng chỉ người
dùng có quyền truy cập được phép gửi yêu cầu RPC.
Mã hóa (Encryption): Dữ liệu gửi qua mạng cần được mã hóa để ngăn người không có quyền đọc
nó. Điều này đặc biệt quan trọng khi dữ liệu nhạy cảm được truyền.
Phân quyền (Authorization): Đảm bảo rằng người dùng chỉ có quyền thực hiện những hành động được ủy quyền.
Xử lý những vấn đề này là quan trọng để triển khai giao thức RPC an toàn và đáng tin cậy trong môi trường phân tán.
Câu hỏi 15: Vấn đề đối với truyền tham biến trong RPC là gì? Còn đồi với truyền tham chiếu?
Giải pháp đưa ra là gì? lOMoAR cPSD| 61552860
Trong giao thức RPC (Remote Procedure Call), truyền tham biến và truyền tham chiếu là hai cách
để gửi tham số và dữ liệu từ máy khách đến máy chủ hoặc ngược lại. Cả hai cách này đều đặt ra
một số vấn đề cần xem xét: 1.
Truyền Tham Biến (Pass by Value): Trong trường hợp này, giá trị của tham số được sao chép
và gửi tới máy chủ. Bất kỳ thay đổi nào được thực hiện trên tham số trên máy chủ không ảnh hưởng
đến giá trị ban đầu trên máy khách. 2.
Truyền Tham Chiếu (Pass by Reference): Trong trường hợp này, tham số là một tham chiếu
hoặc con trỏ trỏ tới dữ liệu thực sự. Bất kỳ thay đổi nào được thực hiện trên tham số trên máy chủ
cũng ảnh hưởng trực tiếp đến giá trị trên máy khách.
Vấn đề đối với truyền tham biến:
Tính toàn vẹn dữ liệu (Data Integrity): Trong trường hợp truyền tham biến, máy khách và máy chủ
hoạt động với bản sao của dữ liệu. Tuy nhiên, có nguy cơ dữ liệu trên máy khách và máy chủ có thể
trở nên không đồng bộ nếu máy chủ thực hiện thay đổi dữ liệu.
An ninh dữ liệu (Data Security): Dữ liệu truyền bằng truyền tham biến có thể trở nên không an toàn
nếu thông tin nhạy cảm được gửi. Bất kỳ thay đổi dữ liệu nào trên máy chủ không thể kiểm soát
hoặc ảnh hưởng đến máy khách.
Vấn đề đối với truyền tham chiếu:
Tính toàn vẹn dữ liệu (Data Integrity): Truyền tham chiếu có thể dẫn đến sự không đồng bộ giữa
máy khách và máy chủ nếu không được quản lý cẩn thận. Bất kỳ thay đổi trên máy chủ có thể ảnh hưởng đến máy khách.
An ninh dữ liệu (Data Security): Truyền tham chiếu cung cấp sự linh hoạt cho việc truy cập và
thay đổi dữ liệu, nhưng cũng đặt ra vấn đề về an ninh nếu không kiểm soát cẩn thận. Giải pháp đưa ra:
Truyền tham biến: Một giải pháp là đảm bảo tính toàn vẹn của dữ liệu bằng cách sao chép dữ liệu
trước khi gửi và sau đó so sánh với phiên bản gốc sau khi thực hiện yêu cầu. Điều này giúp phát
hiện sự không đồng bộ và giảm thiểu rủi ro. Tuy nhiên, nó tốn thời gian và tài nguyên.
Truyền tham chiếu: Để đảm bảo tính toàn vẹn và an ninh dữ liệu, cần thiết phải cân nhắc và kiểm
soát cẩn thận việc thay đổi dữ liệu trên máy chủ và gửi thông tin nhạy cảm.
Lựa chọn giữa truyền tham biến và truyền tham chiếu phụ thuộc vào tình huống cụ thể và yêu cầu
an ninh và tính toàn vẹn của ứng dụng RPC.
Câu hỏi 16: So sánh RMI và RPC. Nhược điểm của RMI so với RPC là gì?
RMI (Remote Method Invocation) và RPC (Remote Procedure Call) đều là các công nghệ sử dụng
trong lập trình phân tán để gọi các hàm hoặc thủ tục trên các máy tính từ xa. Tuy nhiên, có sự khác
biệt quan trọng giữa chúng:
RMI (Remote Method Invocation): lOMoAR cPSD| 61552860
Ngôn ngữ Ưu Tiên: RMI thường liên quan chặt chẽ đến Java. Nó là một phần của nền tảng Java
và tương thích hoàn toàn với Java.
Tích hợp với Java: RMI dễ dàng tích hợp vào các ứng dụng Java và cho phép gọi các phương thức
của các đối tượng Java từ xa.
Khả năng Mô-đun Hóa: RMI cho phép bạn chia nhỏ ứng dụng thành các đối tượng và gọi các
phương thức của chúng từ xa, tạo nên mô hình mô-đun hóa.
Hỗ trợ Marshalling và Serialization: RMI hỗ trợ tự động chuyển đổi dữ liệu và đối tượng sang định
dạng thích hợp để truyền qua mạng. RPC (Remote Procedure Call):
Ngôn Ngữ Đa Dạng: RPC không giới hạn trong việc sử dụng một ngôn ngữ cụ thể. Bạn có thể
triển khai RPC trên nhiều ngôn ngữ khác nhau như C, C++, Python, và nhiều ngôn ngữ khác.
Tích hợp Đa Ngôn Ngữ: RPC cho phép gọi các hàm hoặc phương thức viết bằng nhiều ngôn ngữ khác nhau.
Cộng đồng Lớn và Hỗ trợ Đa Nền Tảng: Có nhiều thư viện và khung làm việc với RPC, giúp bạn
tích hợp RPC vào các ứng dụng đa nền tảng.
Nhược điểm của RMI so với RPC:
Giới hạn về Ngôn ngữ: Một nhược điểm lớn của RMI là nó được hạn chế trong việc sử dụng ngôn
ngữ. Nếu bạn muốn tích hợp các phần của ứng dụng viết bằng các ngôn ngữ khác với Java, RMI sẽ gặp khó khăn.
Khả năng Mô-đun Hóa Hạn Chế: Mặc dù RMI cho phép mô-đun hóa ứng dụng bằng cách gọi các
phương thức từ xa, nhưng nó không linh hoạt bằng RPC trong việc tích hợp các ứng dụng viết bằng
nhiều ngôn ngữ khác nhau.
Phụ thuộc vào Java: RMI là một phần của nền tảng Java, vì vậy nó đòi hỏi máy chủ và máy khách
đều phải chạy Java. Điều này giới hạn tính linh hoạt và khả năng sử dụng trong các môi trường đa
ngôn ngữ và đa nền tảng.
Tóm lại, RMI tiêu biểu cho tích hợp trong một môi trường Java và đòi hỏi máy chủ và máy khách
cùng chạy Java. RPC có khả năng hoạt động đa ngôn ngữ và đa nền tảng, điều này giúp nó phù hợp
với các ứng dụng phân tán lớn và đa dạng.
Câu hỏi 17: Hàm listen được sử dụng bởi TCP server có tham số là backlog. Giải thích ý nghĩa tham số đó.
Tham số backlog trong hàm listen của một TCP server là một chỉ số xác định mức độ backlog (hàng
đợi) cho các kết nối đang chờ xử lý. Tham số này quy định số lượng kết nối đang chờ được duyệt
và xử lý bởi máy chủ.
Khi một máy khách cố gắng kết nối đến máy chủ thông qua giao thức TCP, máy chủ sẽ sử dụng
hàm listen để lắng nghe các yêu cầu kết nối đến. Tuy nhiên, không phải tất cả các yêu cầu kết nối
có thể được xử lý ngay lập tức. Điều này có thể xảy ra khi máy chủ đã bận hoặc đang xử lý kết nối khác. lOMoAR cPSD| 61552860
backlog xác định số lượng kết nối mà máy chủ có thể chấp nhận đồng thời trong hàng đợi đợi xử
lý. Nếu số lượng yêu cầu kết nối đến nhiều hơn backlog, các yêu cầu vượt quá sẽ bị từ chối. Tham
số này đảm bảo rằng máy chủ không quá tải bằng cách giới hạn số lượng kết nối đang chờ xử lý.
Nếu backlog được đặt thành một giá trị cụ thể, ví dụ backlog = 10, thì máy chủ sẽ duyệt và xử lý
tối đa 10 kết nối cùng một lúc và từ chối các kết nối thêm vào khi hàng đợi đã đầy.
Nhưng cần lưu ý rằng giá trị cụ thể của backlog phụ thuộc vào tài nguyên của máy chủ và yêu cầu
cụ thể của ứng dụng. Nếu bạn đặt backlog quá thấp, máy chủ có thể bị quá tải và từ chối kết nối quá
nhanh. Ngược lại, nếu bạn đặt backlog quá cao, điều này có thể làm tăng tiêu tốn tài nguyên và làm
cho máy chủ trở nên không hiệu quả. Chọn giá trị backlog phải cân nhắc dựa trên nhu cầu cụ thể
của ứng dụng và tài nguyên của máy chủ.
Câu hỏi 18: Trong trao đổi thông tin hướng dòng, những cơ chế thực thi QoS được thực hiện ở
tầng nào? Giải thích. Trình bày một số cơ chế thực thi QoS để chứng minh điều đó.
Trong mô hình trao đổi thông tin hướng dòng (unicast) giữa máy tính và máy chủ, cơ chế thực thi
QoS (Quality of Service - Chất lượng Dịch vụ) được triển khai chủ yếu tại tầng 3 (tầng Network)
của mô hình phân tầng OSI. QoS là một tập hợp các tiêu chuẩn và quy tắc được thiết lập để đảm
bảo chất lượng dịch vụ và hiệu suất tối ưu trong việc truyền tải dữ liệu qua mạng. Dưới đây là một
số cơ chế thực thi QoS ở tầng Network và giải thích cách chúng hoạt động:
Phân Ưu Tiên (Priority Queuing): Cơ chế này cho phép bạn xác định các ưu tiên cho các gói dữ
liệu. Các gói dữ liệu được sắp xếp trong hàng đợi theo mức ưu tiên, và các gói có mức ưu tiên cao
sẽ được xử lý trước. Điều này đảm bảo rằng các dịch vụ quan trọng như thoại trực tiếp có thể được
ưu tiên hơn so với dịch vụ không quan trọng.
Điều chỉnh Tốc Độ (Traffic Shaping): Cơ chế này được sử dụng để kiểm soát tốc độ dữ liệu truyền
qua mạng. Nó giúp kiểm soát và giảm đột ngột sự cộng tác của dịch vụ, ngăn chặn quá tải mạng và
đảm bảo dịch vụ ổn định.
Cắt Giữa (Policing): Cơ chế này kiểm tra lưu lượng dữ liệu đang đi qua và thực hiện các biện pháp
như loại bỏ gói dữ liệu không hợp lệ hoặc quá nhiều gói dữ liệu trong một khoảng thời gian cố định.
Quản Lý Rộng Băng Tuyệt Đối (CBWFQ - Class-Based Weighted Fair Queuing): Cơ chế này cho
phép bạn gán ưu tiên và quản lý dịch vụ dựa trên các lớp cụ thể. Các lớp này có thể được xác định
dựa trên các tiêu chí như loại ứng dụng hoặc địa chỉ IP và được gán một lượng băng thông cố định.
Kéo Dài Kiểm Soát (Congestion Control): Cơ chế này giúp kiểm soát hiện tượng quá tải mạng. Khi
mạng gặp nguy cơ quá tải, nó có thể điều chỉnh tốc độ truyền dữ liệu hoặc giảm độ ưu tiên của dịch vụ không quan trọng.
Các cơ chế QoS này được triển khai để đảm bảo rằng các dịch vụ quan trọng như thoại, video trực
tiếp hoặc ứng dụng yêu cầu băng thông cao có thể hoạt động một cách ổn định và chất lượng cao,
trong khi đảm bảo rằng các dịch vụ không quan trọng không chiếm quá nhiều tài nguyên và không
làm ảnh hưởng đến hiệu suất tổng thể của mạng