Trong các ứng dụng web và phần mềm hiện đại, các thao tác Input/Output (I/O) như đọc tệp tin, truy vấn cơ sở dữ liệu hay giao tiếp qua mạng đóng vai trò quan trọng trong việc quyết định hiệu năng hệ thống. Để xử lý các tác vụ này, hai mô hình phổ biến nhất hiện nay là Blocking IO và Non Blocking IO. Mỗi mô hình có cơ chế hoạt động, ưu điểm và hạn chế riêng, ảnh hưởng trực tiếp đến khả năng xử lý đồng thời, mức tiêu thụ tài nguyên và khả năng mở rộng của ứng dụng. Vậy Blocking IO và Non Blocking IO là gì, khác nhau như thế nào và nên sử dụng trong những trường hợp nào? Cùng tìm hiểu chi tiết trong bài viết dưới đây!

- Blocking IO và Non Blocking IO là gì?
- So sánh Blocking IO và Non Blocking IO
- Ứng dụng của Blocking IO và Non Blocking IO trong phát triển web
- IO Blocking vs Non Blocking IO trong các ngôn ngữ lập trình
- Cách tối ưu hiệu năng khi làm việc với Blocking IO và Non Blocking IO
- 1. Giảm thiểu các tác vụ Blocking không cần thiết
- 2. Tận dụng bất đồng bộ (Async) đúng cách
- 3. Sử dụng connection pooling cho database
- 4. Giảm số lần truy cập I/O
- 5. Tránh bottleneck trong event loop
- 6. Xử lý lỗi hiệu quả trong I/O bất đồng bộ
- 7. Sử dụng streaming thay vì load toàn bộ dữ liệu
- 8. Tối ưu tài nguyên hệ thống
- Những lỗi thường gặp khi sử dụng Blocking IO và Non Blocking IO
- Xu hướng phát triển của Non Blocking IO và Blocking IO trong tương lai
- Một số câu hỏi thường gặp về Blocking IO và Non Blocking IO
Blocking IO và Non Blocking IO là gì?
Trong lập trình và phát triển hệ thống, trao đổi dữ liệu giữa ứng dụng với các thiết bị ngoại vi, tệp tin, cơ sở dữ liệu hoặc mạng đều được thực hiện thông qua các thao tác Input/Output (I/O). Tùy thuộc vào cách chương trình xử lý các tác vụ I/O, người ta chia thành 2 mô hình phổ biến là Blocking IO và Non Blocking IO. Mỗi mô hình có cơ chế hoạt động riêng, ảnh hưởng trực tiếp đến hiệu suất, khả năng mở rộng và trải nghiệm người dùng của ứng dụng. Hiểu rõ sự khác biệt giữa Blocking IO và Non Blocking IO sẽ giúp lập trình viên lựa chọn giải pháp phù hợp cho từng bài toán cụ thể.
Blocking IO
Blocking IO là một trong những mô hình xử lý I/O phổ biến nhất hiện nay. Trong mô hình này, luồng thực thi phải chờ thao tác I/O hoàn tất trước khi tiếp tục xử lý các công việc tiếp theo.
1. Blocking IO là gì?
Blocking IO (Blocking Input/Output) là mô hình xử lý nhập/xuất trong đó tiến trình hoặc luồng thực thi sẽ bị tạm dừng khi gửi yêu cầu đọc hoặc ghi dữ liệu. Luồng này chỉ có thể tiếp tục thực hiện các tác vụ tiếp theo sau khi thao tác I/O hoàn tất và kết quả được trả về từ hệ điều hành.
Điều này có nghĩa là khi chương trình cần truy cập dữ liệu từ tệp tin, cơ sở dữ liệu, thiết bị ngoại vi hoặc nhận dữ liệu từ mạng, nó phải chờ cho đến khi dữ liệu sẵn sàng. Trong khoảng thời gian chờ đợi, luồng đang thực thi không thể xử lý bất kỳ công việc nào khác. Blocking IO là mô hình I/O truyền thống được sử dụng rộng rãi nhờ cơ chế hoạt động đơn giản, dễ triển khai và dễ quản lý luồng xử lý.
Đặc điểm của Blocking IO:
- Luồng thực thi bị chặn trong thời gian chờ dữ liệu: Khi yêu cầu I/O được gửi đi, luồng phải tạm dừng cho đến khi thao tác hoàn tất.
- Cơ chế hoạt động đơn giản: Luồng xử lý theo trình tự tuần tự, giúp mã nguồn dễ đọc, dễ phát triển và dễ gỡ lỗi.
- Dễ quản lý trạng thái chương trình: Lập trình viên không cần xây dựng các cơ chế callback, event hoặc xử lý bất đồng bộ phức tạp.
- Phù hợp với hệ thống quy mô nhỏ: Các ứng dụng có ít người dùng đồng thời hoặc ít yêu cầu I/O thường hoạt động hiệu quả với Blocking IO.
- Tiêu tốn nhiều tài nguyên khi mở rộng: Khi số lượng kết nối tăng cao, hệ thống cần tạo thêm nhiều luồng để xử lý, dẫn đến tiêu hao CPU và bộ nhớ. Trong các hệ thống có nhiều kết nối đồng thời, nhiều luồng liên tục ở trạng thái chờ sẽ làm giảm khả năng tận dụng CPU và ảnh hưởng đến hiệu suất tổng thể.
Mặc dù còn tồn tại những hạn chế về khả năng xử lý đồng thời, Blocking IO vẫn được sử dụng phổ biến trong nhiều ứng dụng desktop, công cụ nội bộ, hệ thống quản trị doanh nghiệp và các dịch vụ không yêu cầu khả năng mở rộng lớn.

2. Cơ chế hoạt động của Blocking IO
Trong mô hình Blocking IO, luồng thực thi sẽ phải dừng lại và chờ cho đến khi thao tác I/O hoàn tất. Điều này khiến chương trình xử lý các tác vụ theo kiểu tuần tự: hoàn thành việc hiện tại rồi mới chuyển sang công việc tiếp theo. Quá trình hoạt động của Blocking IO thường diễn ra theo các bước sau:
Bước 1: Ứng dụng gửi yêu cầu I/O
Khi chương trình cần dữ liệu từ một nguồn bên ngoài như tệp tin, cơ sở dữ liệu hoặc máy chủ khác, nó sẽ gửi yêu cầu đến hệ điều hành. Ví dụ, một website cần lấy thông tin người dùng từ cơ sở dữ liệu để hiển thị trên giao diện.
Bước 2: Hệ điều hành tiếp nhận yêu cầu và bắt đầu xử lý
Sau khi nhận được yêu cầu, hệ điều hành sẽ thực hiện các thao tác cần thiết để truy xuất dữ liệu. Quá trình này có thể bao gồm đọc dữ liệu từ ổ cứng, gửi truy vấn đến database hoặc chờ phản hồi từ máy chủ qua mạng. Tùy thuộc vào tốc độ của thiết bị hoặc mạng, thời gian xử lý có thể chỉ vài mili giây hoặc kéo dài vài giây.
Bước 3: Luồng thực thi bị khóa (blocked) và chuyển sang trạng thái chờ
Đây là bước quan trọng nhất của cơ chế Blocking IO. Trong khi hệ điều hành đang xử lý yêu cầu, luồng đã gửi yêu cầu sẽ bị tạm dừng hoàn toàn. Luồng này không thể thực hiện thêm bất kỳ công việc nào khác cho đến khi dữ liệu được trả về.
Bước 4: Dữ liệu sẵn sàng và hệ điều hành trả kết quả
Khi thao tác I/O hoàn tất, hệ điều hành sẽ chuyển dữ liệu về cho ứng dụng.
Ví dụ: Database trả về thông tin người dùng gồm tên, email và số điện thoại sau khi hoàn thành truy vấn.
Bước 5: Luồng được kích hoạt trở lại và tiếp tục xử lý
Sau khi nhận được dữ liệu, luồng đang chờ sẽ được hệ thống kích hoạt và tiếp tục thực hiện các câu lệnh còn lại trong chương trình.
Ví dụ: Website nhận được thông tin người dùng từ database và tiếp tục tạo trang HTML để gửi cho trình duyệt.
3. Ví dụ về Blocking IO
Ví dụ đơn giản của Blocking IO là thao tác đọc tệp tin trong chương trình. Giả sử ứng dụng cần đọc nội dung từ một tệp văn bản có dung lượng lớn:
- Chương trình gửi yêu cầu đọc file đến hệ điều hành.
- Hệ điều hành bắt đầu truy xuất dữ liệu từ ổ cứng.
- Luồng thực thi bị chặn trong thời gian chờ dữ liệu được đọc.
- Sau khi quá trình đọc hoàn tất, dữ liệu được trả về cho chương trình.
- Chương trình tiếp tục xử lý nội dung của tệp.
Trong thời gian đọc file, luồng thực thi không thể thực hiện bất kỳ công việc nào khác. Nếu tệp có dung lượng lớn hoặc thiết bị lưu trữ phản hồi chậm, thời gian chờ sẽ càng kéo dài.
Tương tự trong các ứng dụng web sử dụng Blocking IO, mỗi yêu cầu từ người dùng thường được xử lý bởi một luồng riêng. Khi hàng nghìn người dùng truy cập cùng lúc, rất nhiều luồng sẽ ở trạng thái chờ dữ liệu từ cơ sở dữ liệu hoặc mạng. Điều này làm tăng mức sử dụng CPU và bộ nhớ, đồng thời ảnh hưởng đến khả năng mở rộng của hệ thống.

Non Blocking IO
Nếu Blocking IO yêu cầu luồng thực thi phải dừng lại để chờ dữ liệu thì Non Blocking IO được thiết kế để khắc phục hạn chế này. Với mô hình Non Blocking IO, chương trình có thể tiếp tục thực hiện các tác vụ khác trong khi chờ thao tác I/O hoàn tất. Nhờ đó, hệ thống tận dụng tài nguyên hiệu quả hơn và có khả năng xử lý nhiều kết nối đồng thời, đặc biệt trong các ứng dụng web, dịch vụ thời gian thực và kiến trúc microservices hiện đại.
1. Non Blocking IO là gì?
Non Blocking IO (Non-Blocking Input/Output) là mô hình xử lý nhập/xuất trong đó luồng thực thi không bị tạm dừng khi gửi yêu cầu đọc hoặc ghi dữ liệu. Thay vì chờ thao tác I/O hoàn tất, chương trình sẽ tiếp tục thực hiện các công việc khác và chỉ xử lý dữ liệu khi dữ liệu thực sự sẵn sàng.
Nói cách khác, khi ứng dụng gửi yêu cầu truy xuất dữ liệu từ tệp tin, cơ sở dữ liệu hoặc máy chủ khác, hệ điều hành sẽ trả về ngay trạng thái hiện tại của yêu cầu. Nếu dữ liệu chưa sẵn sàng, luồng thực thi vẫn tiếp tục hoạt động thay vì bị đưa vào trạng thái chờ như trong Blocking IO. Điều này giúp giảm thời gian nhàn rỗi của luồng xử lý, đồng thời cho phép một luồng có thể quản lý nhiều kết nối hoặc nhiều tác vụ I/O cùng lúc.
Đặc điểm của Non Blocking IO:
- Luồng thực thi không bị chặn trong thời gian chờ dữ liệu.
- Tận dụng tài nguyên CPU hiệu quả hơn so với Blocking IO.
- Có khả năng xử lý số lượng lớn kết nối đồng thời.
- Giảm nhu cầu tạo quá nhiều luồng xử lý.
- Phù hợp với các ứng dụng web có lưu lượng truy cập lớn và hệ thống thời gian thực.
- Phát triển và quản lý mã nguồn thường phức tạp hơn do phải xử lý callback, event hoặc cơ chế bất đồng bộ.

2. Cơ chế hoạt động của Non Blocking IO
Trong mô hình Non Blocking IO, luồng thực thi không phải dừng lại khi gửi yêu cầu I/O. Thay vào đó, hệ điều hành sẽ thông báo khi dữ liệu sẵn sàng hoặc ứng dụng sẽ chủ động kiểm tra trạng thái của thao tác. Quá trình hoạt động của Non Blocking IO thường diễn ra theo các bước sau:
Bước 1: Ứng dụng gửi yêu cầu I/O
Khi cần truy cập dữ liệu từ tệp tin, cơ sở dữ liệu hoặc mạng, ứng dụng gửi yêu cầu đến hệ điều hành.
Bước 2: Hệ điều hành tiếp nhận yêu cầu
Hệ điều hành bắt đầu xử lý yêu cầu truy xuất dữ liệu nhưng không yêu cầu luồng thực thi phải chờ kết quả. Nếu dữ liệu chưa sẵn sàng, hệ điều hành sẽ trả về trạng thái tạm thời thay vì giữ luồng ở trạng thái chờ.
Bước 3: Luồng thực thi tiếp tục xử lý công việc khác
Đây là điểm khác biệt lớn nhất giữa Non Blocking IO và IO Blocking. Sau khi gửi yêu cầu, luồng thực thi vẫn có thể tiếp tục xử lý các tác vụ khác như tiếp nhận yêu cầu mới, thực hiện tính toán hoặc phục vụ người dùng khác.
Ví dụ, trong khi chờ dữ liệu sản phẩm được trích xuất từ cơ sở dữ liệu, máy chủ vẫn có thể tiếp tục xử lý các yêu cầu khác từ người dùng.
Bước 4: Dữ liệu sẵn sàng
Khi quá trình truy xuất dữ liệu hoàn tất, hệ điều hành sẽ thông báo cho ứng dụng thông qua cơ chế sự kiện (event), callback hoặc các cơ chế bất đồng bộ khác. Lúc này dữ liệu đã sẵn sàng để được xử lý.
Bước 5: Hệ thống nhận và xử lý dữ liệu
Sau khi nhận được thông báo, hệ thống tiến hành lấy dữ liệu và tiếp tục thực hiện các công việc còn lại. Ví dụ, website nhận được danh sách sản phẩm từ cơ sở dữ liệu và tạo nội dung trang web để gửi về trình duyệt. Nhờ cơ chế này, một số lượng nhỏ luồng vẫn có thể phục vụ hàng nghìn hoặc hàng chục nghìn kết nối đồng thời mà không tiêu tốn quá nhiều tài nguyên hệ thống.
3. Ví dụ về Non Blocking IO
Giả sử ứng dụng cần đọc một tệp dữ liệu có dung lượng lớn:
- Chương trình gửi yêu cầu đọc file.
- Hệ điều hành bắt đầu truy xuất dữ liệu từ ổ cứng.
- Chương trình không chờ kết quả mà tiếp tục thực hiện các công việc khác.
- Khi dữ liệu được đọc xong, hệ điều hành gửi thông báo cho ứng dụng.
- Ứng dụng nhận dữ liệu và thực hiện xử lý tiếp theo.
Trong thời gian chờ đọc file, luồng thực thi vẫn có thể phục vụ các yêu cầu khác thay vì bị tạm dừng hoàn toàn.
Trong các máy chủ web hiện đại như NgINX hoặc các ứng dụng Nodejs, một số lượng nhỏ luồng có thể xử lý đồng thời hàng nghìn kết nối nhờ cơ chế Non Blocking IO. Điều này giúp giảm đáng kể mức sử dụng CPU và bộ nhớ so với mô hình Blocking IO, đồng thời cải thiện khả năng mở rộng và hiệu suất của hệ thống khi lưu lượng truy cập tăng cao.

So sánh Blocking IO và Non Blocking IO
Blocking IO và Non Blocking IO đều là các mô hình xử lý Input/Output (I/O) được sử dụng để trao đổi dữ liệu giữa ứng dụng với tệp tin, cơ sở dữ liệu, thiết bị ngoại vi hoặc mạng. Tuy nhiên, hai mô hình này có sự khác biệt đáng kể về cách quản lý luồng thực thi, hiệu suất xử lý và khả năng mở rộng hệ thống. Hiểu rõ những điểm khác nhau giữa Blocking IO và Non Blocking IO sẽ giúp lập trình viên lựa chọn mô hình phù hợp với yêu cầu của từng ứng dụng.
| Tiêu chí | Blocking IO | Non Blocking IO |
| Cách xử lý yêu cầu I/O | Luồng phải chờ thao tác I/O hoàn tất trước khi tiếp tục xử lý. | Luồng không phải chờ và có thể tiếp tục thực hiện công việc khác. |
| Trạng thái luồng khi chờ dữ liệu | Bị chặn (Blocked) | Vẫn hoạt động bình thường |
| Khả năng tận dụng CPU | Thấp hơn do nhiều luồng ở trạng thái chờ. | Cao hơn nhờ giảm thời gian nhàn rỗi của luồng. |
| Số lượng cần sử dụng | Thường cần nhiều luồng để xử lý nhiều yêu cầu đồng thời. | Có thể xử lý nhiều kết nối với số lượng luồng ít hơn. |
| Khả năng xử lý đồng thời | Hạn chế khi số lượng kết nối tăng cao. | Hỗ trợ xử lý lượng lớn kết nối đồng thời. |
| Mức tiêu thụ tài nguyên | Tốn nhiều CPU và bộ nhớ khi mở rộng hệ thống. | Tối ưu tài nguyên hơn |
| Độ phức tạp khi lập trình | Đơn giản, dễ phát triển và gỡ lỗi. | Phức tạp hơn do sử dụng cơ chế bất đồng bộ. |
| Khả năng mở rộng | Khó mở rộng đối với hệ thống lớn. | Dễ mở rộng và phù hợp với hệ thống quy mô lớn |
| Ứng dụng phù hợp | Ứng dụng desktop, hệ thống nội bộ, website có ít truy cập. | Web server, ứng dụng thời gian thực, microservices, hệ thống có lưu lượng lớn. |
| Công nghệ tiêu biểu | Java IO, PHP truyền thống, Apache Prefork | Node.js, Java NIO, Nginx, Netty, Spring WebFlux |
Nhìn chung, Blocking IO phù hợp với các ứng dụng có quy mô nhỏ hoặc yêu cầu xử lý đơn giản nhờ cơ chế hoạt động dễ triển khai và bảo trì. Trong khi đó, Non Blocking IO là lựa chọn tối ưu cho các hệ thống hiện đại cần xử lý số lượng lớn kết nối đồng thời, tận dụng tài nguyên hiệu quả và có khả năng mở rộng cao.
Ứng dụng của Blocking IO và Non Blocking IO trong phát triển web
Mỗi mô hình I/O đều có những ưu điểm và hạn chế riêng, vì vậy không có giải pháp nào phù hợp với mọi hệ thống. Trong thực tế, các nhà phát triển thường lựa chọn Blocking IO hoặc Non Blocking IO dựa trên đặc điểm nghiệp vụ, số lượng người dùng, yêu cầu hiệu năng và khả năng mở rộng của ứng dụng. Thậm chí, nhiều hệ thống hiện đại còn kết hợp cả hai mô hình để tận dụng thế mạnh của từng phương pháp.
1. Ứng dụng của IO Blocking trong phát triển web
Mặc dù Non Blocking IO ngày càng phổ biến trong các hệ thống quy mô lớn, Blocking IO vẫn đóng vai trò quan trọng trong nhiều lĩnh vực nhờ tính ổn định, dễ kiểm soát và khả năng xử lý tuần tự đáng tin cậy.
Hệ thống xử lý tài chính và ngân hàng
Trong lĩnh vực tài chính, độ chính xác và tính nhất quán của dữ liệu thường được ưu tiên hơn tốc độ xử lý. Các giao dịch như chuyển khoản, thanh toán trực tuyến hoặc cập nhật số dư tài khoản cần được thực hiện theo trình tự rõ ràng để tránh sai lệch dữ liệu.
Blocking IO giúp đảm bảo mỗi giao dịch được xử lý hoàn chỉnh trước khi chuyển sang bước tiếp theo. Điều này giúp hạn chế rủi ro phát sinh do xung đột dữ liệu hoặc lỗi đồng bộ trong quá trình xử lý.
Ví dụ:
- Hệ thống Internet Banking.
- Cổng thanh toán trực tuyến.
- Phần mềm quản lý tín dụng và khoản vay.
- Hệ thống xử lý giao dịch chứng khoán nội bộ.
Ứng dụng xử lý đồ họa, video và AI
Nhiều ứng dụng xử lý đồ họa hoặc trí tuệ nhân tạo yêu cầu hoàn thành một tác vụ trước khi chuyển sang bước tiếp theo trong quy trình xử lý dữ liệu. Ví dụ, khi chỉnh sửa video hoặc huấn luyện mô hình AI, hệ thống cần đọc dữ liệu, thực hiện tính toán và ghi kết quả theo trình tự nhất định. Trong những trường hợp này, Blocking IO giúp luồng xử lý tập trung vào một nhiệm vụ cụ thể và giảm độ phức tạp trong quá trình phát triển.
Một số ứng dụng tiêu biểu bao gồm:
- Phần mềm chỉnh sửa ảnh và video.
- Hệ thống render đồ họa 3D.
- Công cụ huấn luyện mô hình Machine Learning.
- Phần mềm xử lý dữ liệu chuyên sâu.
Hệ thống quản trị doanh nghiệp phức tạp
Các hệ thống ERP, CRM hoặc phần mềm quản lý doanh nghiệp thường có quy trình nghiệp vụ phức tạp nhưng số lượng người dùng đồng thời không quá lớn. Trong môi trường này, Blocking IO giúp xây dựng và bảo trì hệ thống trở nên đơn giản hơn. Đồng thời, các quy trình xử lý tuần tự cũng dễ dàng được kiểm soát và theo dõi hơn.
Ví dụ:
- Hệ thống quản lý nhân sự (HRM).
- Phần mềm kế toán doanh nghiệp.
- Hệ thống quản lý kho hàng.
- Hệ thống quản lý khách hàng (CRM).

2. Ứng dụng thực tế của Non Blocking IO
Nhờ khả năng xử lý đồng thời số lượng lớn kết nối và tận dụng tài nguyên hiệu quả, Non Blocking IO đang trở thành nền tảng của nhiều hệ thống web hiện đại.
Ứng dụng thời gian thực
Các ứng dụng thời gian thực yêu cầu trao đổi dữ liệu liên tục với độ trễ thấp giữa máy chủ và người dùng. Nếu sử dụng Blocking IO, số lượng kết nối tăng cao có thể khiến nhiều luồng phải chờ dữ liệu và làm giảm hiệu suất hệ thống. Trong khi đó, Non Blocking IO cho phép máy chủ xử lý đồng thời hàng nghìn kết nối mà không cần tạo quá nhiều luồng.
Một số ví dụ phổ biến:
- Ứng dụng chat trực tuyến.
- Hệ thống nhắn tin tức thời.
- Công cụ cộng tác trực tuyến.
- Trò chơi trực tuyến nhiều người chơi
Nền tảng Livestream và Streaming Media
Các nền tảng phát trực tiếp hoặc truyền phát nội dung cần duy trì lượng lớn kết nối đồng thời giữa máy chủ và người xem. Non Blocking IO giúp máy chủ xử lý nhiều luồng dữ liệu liên tục mà không tiêu tốn quá nhiều tài nguyên hệ thống. Điều này góp phần đảm bảo trải nghiệm xem mượt mà và ổn định.
Ví dụ:
- Nền tảng livestream video.
- Dịch vụ phát nhạc trực tuyến.
- Hệ thống xem phim theo yêu cầu (VOD).
- Các nền tảng hội nghị trực tuyến.
Hệ thống API Gateway và Microservices
Trong kiến trúc Microservices, một yêu cầu từ người dùng có thể cần giao tiếp với nhiều dịch vụ khác nhau trước khi trả kết quả cuối cùng. Non Blocking IO cho phép API Gateway xử lý nhiều yêu cầu đồng thời và giao tiếp với nhiều dịch vụ backend mà không bị chặn bởi từng thao tác I/O riêng lẻ.
Các hệ thống thường áp dụng mô hình này gồm:
- API Gateway.
- Hệ thống thương mại điện tử quy mô lớn.
- Nền tảng SaaS đa dịch vụ.
- Hệ thống Cloud-native.
Ứng dụng IoT và tracking thời gian thực
Các hệ thống IoT thường phải tiếp nhận dữ liệu liên tục từ hàng nghìn hoặc hàng triệu thiết bị kết nối. Nếu sử dụng Blocking IO, hệ thống sẽ cần rất nhiều luồng xử lý, gây áp lực lớn lên tài nguyên máy chủ. Non Blocking IO giúp quản lý lượng lớn kết nối đồng thời với chi phí tài nguyên thấp hơn đáng kể.
Ví dụ:
- Hệ thống giám sát thiết bị IoT.
- Nền tảng nhà thông minh.
- Hệ thống theo dõi phương tiện GPS.
- Giải pháp giám sát sản xuất theo thời gian thực.

3. Kết hợp IO Blocking và Non Blocking IO trong website hiện đại
Nhiều website và ứng dụng web hiện đại không chỉ sử dụng một mô hình I/O duy nhất mà thường kết hợp cả Blocking IO và Non Blocking IO để tối ưu hiệu suất cũng như chi phí phát triển. Thông thường:
- Non Blocking IO được sử dụng ở các thành phần cần xử lý số lượng lớn kết nối đồng thời như web server, API Gateway, WebSocket hoặc dịch vụ streaming.
- Blocking IO vẫn được áp dụng cho các tác vụ yêu cầu tính nhất quán cao hoặc xử lý nghiệp vụ phức tạp như giao dịch tài chính, xử lý báo cáo hoặc các tác vụ nền.
Ví dụ, một website thương mại điện tử có thể:
- Sử dụng Nginx hoặc Node.js với Non Blocking IO để xử lý hàng nghìn kết nối từ người dùng.
- Sử dụng các dịch vụ backend xử lý đơn hàng theo mô hình Blocking IO nhằm đảm bảo tính chính xác của dữ liệu.
- Kết hợp hàng đợi (Message Queue) để đồng bộ dữ liệu giữa các thành phần của hệ thống.
Cách tiếp cận này giúp hệ thống vừa đạt được hiệu năng cao vừa đảm bảo độ ổn định và tính chính xác cho các nghiệp vụ quan trọng. Đây cũng là xu hướng kiến trúc được áp dụng rộng rãi trong các website và nền tảng số hiện đại.

IO Blocking vs Non Blocking IO trong các ngôn ngữ lập trình
Một số ngôn ngữ được xây dựng chủ yếu dựa trên mô hình Blocking IO truyền thống, trong khi nhiều nền tảng hiện đại đã tích hợp các thư viện hoặc framework hỗ trợ Non Blocking IO nhằm đáp ứng nhu cầu xử lý đồng thời và mở rộng hệ thống. Dưới đây là cách các ngôn ngữ lập trình phổ biến áp dụng hai mô hình I/O này trong thực tế.
1. Java
Java hỗ trợ cả Blocking IO và Non Blocking IO. Cụ thể:
- Blocking IO: Được cung cấp thông qua thư viện java.io, trong đó các thao tác đọc và ghi dữ liệu sẽ chặn luồng thực thi cho đến khi hoàn thành.
- Non Blocking IO: Được hỗ trợ bởi java.nio và java.nio.2, cho phép xử lý nhiều kết nối đồng thời thông qua Channel, Buffer và Selector.
Java thường sử dụng Blocking IO trong các ứng dụng doanh nghiệp truyền thống, trong khi Non Blocking IO được áp dụng cho các hệ thống có lưu lượng truy cập lớn như API Gateway, hệ thống realtime hoặc microservices.
2. Python
Python hỗ trợ cả hai mô hình I/O. Cụ thể:
- Blocking IO: Được sử dụng mặc định trong hầu hết các thao tác đọc file, socket và truy cập cơ sở dữ liệu.
- Non Blocking IO: Có thể triển khai Non Blocking IO thông qua các thư viện như asyncio, aiohttp hoặc các framework bất đồng bộ hiện đại.
Blocking IO thường được sử dụng trong các ứng dụng đơn giản hoặc xử lý dữ liệu. Trong khi đó, Non Blocking IO phù hợp với các hệ thống web hiệu năng cao và ứng dụng thời gian thực.
3. JavaScript (Node.js)
Node.js là một trong những nền tảng tiêu biểu cho mô hình Non Blocking IO. Node.js sử dụng Event Loop để xử lý các thao tác I/O bất đồng bộ. Khi một yêu cầu đọc file hoặc truy vấn cơ sở dữ liệu được gửi đi, luồng chính không bị chặn mà tiếp tục xử lý các tác vụ khác. Nhờ cơ chế này, Node.js có thể xử lý hàng nghìn kết nối đồng thời với số lượng luồng rất nhỏ, phù hợp cho:
- API Backend.
- Chat realtime.
- Livestream.
- Hệ thống microservices.

4. PHP
PHP truyền thống chủ yếu hoạt động theo mô hình Blocking IO. Mỗi yêu cầu từ người dùng thường được xử lý độc lập bởi một tiến trình hoặc luồng riêng. Điều này giúp lập trình đơn giản nhưng có thể gây tốn tài nguyên khi lượng truy cập tăng cao. Hiện nay, PHP đã có thêm các giải pháp hỗ trợ Non Blocking IO như:
- ReactPHP.
- Swoole.
- Workerman.
Những công nghệ này giúp PHP cải thiện đáng kể khả năng xử lý đồng thời và hiệu suất hệ thống.
5. Go
Go được thiết kế với khả năng xử lý đồng thời mạnh mẽ thông qua Goroutine và Channel. Mặc dù lập trình viên có thể viết mã theo phong cách đồng bộ, Go Runtime bên dưới vẫn sử dụng các cơ chế I/O tối ưu để quản lý hàng nghìn kết nối đồng thời một cách hiệu quả. Nhờ đó, Go thường được sử dụng để xây dựng:
- API hiệu năng cao.
- Hệ thống phân tán.
- Dịch vụ Cloud-native.
- Nền tảng xử lý dữ liệu thời gian thực.
6. C#
Trong hệ sinh thái .NET, lập trình viên có thể lựa chọn giữa Blocking IO và Non Blocking IO.
- Blocking IO: Sử dụng các phương thức đồng bộ truyền thống.
- Non Blocking IO: Sử dụng mô hình async/await, Task và các API bất đồng bộ.
Các ứng dụng ASP.NET hiện đại thường ưu tiên Non Blocking IO để cải thiện khả năng phục vụ nhiều người dùng đồng thời và tối ưu tài nguyên máy chủ.

Cách tối ưu hiệu năng khi làm việc với Blocking IO và Non Blocking IO
Dù sử dụng Blocking IO hay Non Blocking IO, hiệu năng của ứng dụng không chỉ phụ thuộc vào mô hình I/O mà còn chịu ảnh hưởng bởi cách thiết kế hệ thống, quản lý tài nguyên và xử lý dữ liệu. Áp dụng các biện pháp tối ưu phù hợp sẽ giúp giảm độ trễ, cải thiện khả năng xử lý đồng thời và nâng cao trải nghiệm người dùng. Dưới đây là những phương pháp phổ biến giúp tối ưu hiệu năng khi làm việc với cả hai mô hình I/O.
1. Giảm thiểu các tác vụ Blocking không cần thiết
Một trong những nguyên nhân phổ biến làm giảm hiệu năng hệ thống là sự xuất hiện của các tác vụ Blocking không cần thiết. Những thao tác như đọc tệp tin dung lượng lớn, truy vấn cơ sở dữ liệu chậm hoặc gọi API bên thứ ba có thể khiến luồng thực thi phải chờ trong thời gian dài.
Để tối ưu hiệu năng, bạn cần:
- Rà soát và xác định các tác vụ có khả năng gây chặn luồng.
- Sau đó tìm cách thay thế bằng các giải pháp bất đồng bộ hoặc thực hiện chúng trong các tiến trình nền.
- Tối ưu truy vấn cơ sở dữ liệu và giảm thời gian phản hồi từ các dịch vụ bên ngoài cũng góp phần hạn chế tình trạng Blocking kéo dài.
2. Tận dụng bất đồng bộ (Async) đúng cách
Các cơ chế bất đồng bộ như Callback, Promise, Async/Await hay Future giúp chương trình tiếp tục thực hiện các công việc khác trong khi chờ thao tác I/O hoàn tất. Điều này giúp tận dụng tài nguyên hiệu quả hơn và cải thiện khả năng phục vụ nhiều người dùng cùng lúc.
Tuy nhiên, sử dụng Async cần được thực hiện hợp lý. Nếu lạm dụng quá nhiều tác vụ bất đồng bộ hoặc tạo ra các luồng xử lý không cần thiết, ứng dụng có thể trở nên khó kiểm soát và phát sinh lỗi phức tạp. Vì vậy, bạn chỉ nên áp dụng Async cho những tác vụ thực sự tốn thời gian như truy cập cơ sở dữ liệu, đọc ghi tệp tin hoặc giao tiếp mạng.
3. Sử dụng connection pooling cho database
Liên tục mở và đóng kết nối đến cơ sở dữ liệu là một trong những nguyên nhân làm tăng thời gian xử lý của ứng dụng. Mỗi lần tạo kết nối mới đều tiêu tốn tài nguyên và thời gian xác thực.
Để khắc phục vấn đề này, nhiều hệ thống sử dụng Connection Pooling - cơ chế tạo sẵn và quản lý một nhóm kết nối (connection pool) đến cơ sở dữ liệu để các tác vụ có thể tái sử dụng khi cần. Thay vì tạo mới một kết nối cho mỗi truy vấn, ứng dụng sẽ lấy một kết nối có sẵn từ pool, sử dụng để thực hiện truy vấn rồi trả lại pool sau khi hoàn thành.
Ví dụ, nếu một website có 100 người dùng truy cập cùng lúc, hệ thống không nhất thiết phải tạo 100 kết nối mới đến cơ sở dữ liệu. Thay vào đó, ứng dụng có thể sử dụng một pool gồm 20 - 30 kết nối và phân phối chúng cho các yêu cầu đang xử lý.

4. Giảm số lần truy cập I/O
Các thao tác I/O như đọc tệp tin, truy vấn cơ sở dữ liệu, gọi API hoặc trao đổi dữ liệu qua mạng thường có tốc độ chậm hơn đáng kể so với xử lý dữ liệu trong bộ nhớ (RAM). Vì vậy, giảm số lần truy cập I/O là một trong những cách hiệu quả để cải thiện hiệu năng ứng dụng và rút ngắn thời gian phản hồi.
Một số phương pháp phổ biến gồm:
- Sử dụng bộ nhớ cache: Lưu trữ dữ liệu thường xuyên được truy cập trong RAM hoặc các hệ thống cache như Redis, Memcached để hạn chế truy vấn lại cơ sở dữ liệu.
- Gộp nhiều thao tác đọc/ghi: Thay vì thực hiện nhiều truy vấn hoặc nhiều lần ghi dữ liệu riêng lẻ, hãy gom chúng thành một lần xử lý để giảm số lượng yêu cầu I/O.
- Chỉ tải dữ liệu cần thiết: Bạn cần tránh lấy toàn bộ dữ liệu khi ứng dụng chỉ sử dụng một phần. Ví dụ, bạn chỉ truy vấn các cột cần dùng thay vì sử dụng SELECT *.
5. Tránh bottleneck trong event loop
Đối với các hệ thống sử dụng Non Blocking IO như Node.js, Event Loop là thành phần chịu trách nhiệm tiếp nhận và phân phối các tác vụ bất đồng bộ. Nếu Event Loop bị chiếm dụng bởi các công việc nặng, toàn bộ ứng dụng có thể bị chậm lại dù vẫn đang sử dụng kiến trúc Non Blocking IO.
Để tránh tình trạng này, bạn cần:
- Tránh thực hiện các phép tính phức tạp hoặc xử lý dữ liệu lớn trên luồng chính.
- Hạn chế các vòng lặp kéo dài làm chiếm dụng CPU.
- Tách các tác vụ nặng sang Worker Threads hoặc tiến trình riêng.
- Sử dụng hàng đợi công việc (Job Queue) cho các tác vụ xử lý nền.
- Theo dõi hiệu suất Event Loop để phát hiện sớm các điểm nghẽn.
6. Xử lý lỗi hiệu quả trong I/O bất đồng bộ
Trong môi trường I/O bất đồng bộ, các tác vụ thường được thực hiện song song hoặc diễn ra ở những thời điểm khác nhau. Điều này giúp cải thiện hiệu năng nhưng cũng khiến phát hiện và xử lý lỗi trở nên phức tạp hơn so với mô hình xử lý tuần tự. Nếu không có cơ chế quản lý lỗi phù hợp, một yêu cầu thất bại có thể gây ảnh hưởng đến toàn bộ luồng xử lý hoặc làm gián đoạn trải nghiệm người dùng.
Để đảm bảo tính ổn định của hệ thống, lập trình viên cần xây dựng cơ chế xử lý lỗi rõ ràng như sử dụng try...catch, Promise Catch, Error Handler hoặc các middleware xử lý lỗi tập trung. Bên cạnh đó, ghi log chi tiết, triển khai cơ chế Retry cho các lỗi tạm thời và áp dụng các mô hình như Circuit Breaker cũng giúp hệ thống duy trì hoạt động ổn định ngay cả khi gặp sự cố từ cơ sở dữ liệu, mạng hoặc các dịch vụ bên ngoài.
7. Sử dụng streaming thay vì load toàn bộ dữ liệu
Khi xử lý các tệp tin lớn hoặc khối lượng dữ liệu lớn, tải toàn bộ dữ liệu vào bộ nhớ trước khi xử lý có thể làm tăng mức sử dụng RAM và ảnh hưởng đến hiệu năng của ứng dụng. Điều này đặc biệt dễ xảy ra trong các hệ thống truyền phát video, xử lý log hoặc tải lên và tải xuống các tệp dung lượng lớn.
Streaming là kỹ thuật cho phép ứng dụng xử lý dữ liệu theo từng phần nhỏ ngay khi dữ liệu được nhận. Nhờ đó, hệ thống không cần lưu toàn bộ dữ liệu trong bộ nhớ cùng một lúc, giúp giảm tiêu thụ tài nguyên và tăng tốc độ xử lý. Đây là giải pháp được sử dụng rộng rãi trong các nền tảng livestream, dịch vụ xem video trực tuyến và các hệ thống xử lý dữ liệu thời gian thực.
8. Tối ưu tài nguyên hệ thống
Hiệu năng của ứng dụng không chỉ phụ thuộc vào mô hình I/O mà còn chịu ảnh hưởng trực tiếp từ việc sử dụng tài nguyên hệ thống như CPU, bộ nhớ, ổ cứng và băng thông mạng. Ngay cả khi ứng dụng được xây dựng với Non Blocking IO, phân bổ tài nguyên không hợp lý vẫn có thể tạo ra các điểm nghẽn làm giảm hiệu suất tổng thể.
Để tối ưu tài nguyên hệ thống, cần thường xuyên theo dõi các chỉ số vận hành, tối ưu cấu hình máy chủ và phân bổ tài nguyên phù hợp với khối lượng công việc thực tế. Ngoài ra, các giải pháp như Load Balancing, Auto Scaling, Cache và tối ưu cơ sở dữ liệu cũng giúp giảm tải cho hệ thống và nâng cao khả năng xử lý.

Những lỗi thường gặp khi sử dụng Blocking IO và Non Blocking IO
Mặc dù Blocking IO và Non Blocking IO đều là những mô hình xử lý I/O phổ biến, triển khai không đúng cách có thể khiến hệ thống gặp phải các vấn đề về hiệu năng, khả năng mở rộng và độ ổn định. Hiểu rõ những sai lầm thường gặp sẽ giúp lập trình viên tránh được các lỗi thiết kế ngay từ đầu và xây dựng ứng dụng hiệu quả hơn.
1. Các sai lầm phổ biến trong môi trường Blocking IO
Blocking IO có cơ chế hoạt động đơn giản nhưng vẫn tiềm ẩn nhiều rủi ro nếu không được tối ưu đúng cách. Khi số lượng người dùng hoặc yêu cầu tăng lên, những sai lầm trong thiết kế có thể nhanh chóng trở thành điểm nghẽn của hệ thống. Một số lỗi thường gặp gồm:
- Tạo quá nhiều luồng xử lý: Mỗi kết nối hoặc yêu cầu được gán cho một luồng riêng sẽ làm số lượng thread tăng nhanh khi lưu lượng truy cập lớn. Điều này khiến CPU và bộ nhớ phải gánh thêm chi phí quản lý luồng, làm giảm hiệu suất tổng thể của hệ thống.
- Thực hiện các truy vấn cơ sở dữ liệu chậm: Những câu lệnh SQL chưa được tối ưu hoặc thiếu index thường khiến thời gian phản hồi kéo dài. Trong môi trường Blocking IO, luồng xử lý sẽ phải chờ cho đến khi truy vấn hoàn tất, làm giảm khả năng phục vụ các yêu cầu khác.
- Không sử dụng Connection Pooling: Liên tục mở và đóng kết nối database tiêu tốn nhiều thời gian và tài nguyên hệ thống. Khi lượng truy cập tăng cao, đây có thể trở thành nguyên nhân khiến ứng dụng phản hồi chậm.
- Đọc hoặc ghi tệp tin dung lượng lớn trên luồng chính: Các thao tác đọc ghi file lớn thường mất nhiều thời gian xử lý. Nếu thực hiện trực tiếp trên luồng chính, ứng dụng có thể bị chặn và làm chậm các tác vụ khác.
- Thiếu cơ chế cache: Hệ thống phải liên tục truy vấn cơ sở dữ liệu hoặc gọi API để lấy cùng một dữ liệu. Điều này làm tăng số lượng thao tác I/O và tạo áp lực không cần thiết lên hạ tầng.
2. Các lỗi kinh điển trong môi trường Non Blocking IO
Non Blocking IO mang lại khả năng xử lý đồng thời cao nhưng đi kèm với độ phức tạp lớn hơn. Nếu triển khai không đúng cách, hệ thống vẫn có thể gặp các vấn đề nghiêm trọng về hiệu năng và độ ổn định.
- Chặn Event Loop bằng các tác vụ nặng: Các phép tính phức tạp hoặc xử lý dữ liệu lớn có thể chiếm dụng Event Loop trong thời gian dài. Điều này khiến các yêu cầu khác phải chờ và làm giảm khả năng phản hồi của ứng dụng.
- Lạm dụng Async cho mọi tác vụ: Không phải công việc nào cũng cần xử lý bất đồng bộ. Việc sử dụng Async tràn lan có thể khiến luồng xử lý trở nên khó theo dõi và làm tăng độ phức tạp của mã nguồn.
- Không thiết lập Timeout: Các yêu cầu chờ phản hồi quá lâu sẽ tiếp tục chiếm giữ tài nguyên hệ thống. Nếu xảy ra trên diện rộng, ứng dụng có thể bị giảm hiệu năng hoặc ngừng phản hồi.
- Bỏ qua cơ chế Retry và Circuit Breaker: Khi dịch vụ bên ngoài gặp sự cố, hệ thống vẫn liên tục gửi yêu cầu thất bại. Điều này không chỉ làm lãng phí tài nguyên mà còn khiến sự cố lan rộng sang các thành phần khác.
- Tạo quá nhiều tác vụ đồng thời: Gửi hàng nghìn yêu cầu đến database hoặc API cùng lúc có thể gây quá tải cho hệ thống phía sau. Trong nhiều trường hợp, hiệu suất thực tế còn thấp hơn so với việc giới hạn số lượng tác vụ hợp lý.

Xu hướng phát triển của Non Blocking IO và Blocking IO trong tương lai
Sự phát triển của điện toán đám mây, kiến trúc microservices và các ứng dụng xử lý thời gian thực đang làm thay đổi cách các hệ thống hiện đại tiếp cận vấn đề I/O. Nếu trước đây cuộc tranh luận thường xoay quanh việc lựa chọn giữa Blocking IO và Non Blocking IO thì ngày nay xu hướng phát triển tập trung nhiều hơn vào việc tận dụng ưu điểm của cả hai mô hình để đáp ứng các yêu cầu ngày càng cao về hiệu năng, khả năng mở rộng và tối ưu tài nguyên.
1. Sự trỗi dậy của lập trình phản xạ và mô hình hướng luồng
Lập trình phản ứng (Reactive Programming) đang trở thành một trong những xu hướng quan trọng trong phát triển phần mềm hiện đại. Thay vì xử lý dữ liệu theo từng yêu cầu độc lập, mô hình này tập trung vào việc xử lý các luồng dữ liệu (Data Streams) và phản hồi các sự kiện theo thời gian thực.
Nhờ kết hợp chặt chẽ với Non Blocking IO, các framework như Spring WebFlux, Reactor hay RxJava có thể xử lý lượng lớn kết nối đồng thời với mức tiêu thụ tài nguyên thấp. Điều này đặc biệt phù hợp với các hệ thống yêu cầu khả năng mở rộng cao như nền tảng thương mại điện tử, dịch vụ streaming và ứng dụng IoT.
2. Xu hướng Virtual Threads và Project Loom
Trong nhiều năm, một trong những hạn chế lớn nhất của Blocking IO là chi phí tạo và quản lý luồng xử lý. Khi số lượng kết nối tăng cao, hệ thống phải duy trì hàng nghìn luồng, dẫn đến áp lực lớn lên CPU và bộ nhớ.
Sự xuất hiện của Project Loom và Virtual Threads trong Java đang thay đổi đáng kể cách tiếp cận này. Virtual Threads cho phép tạo số lượng rất lớn luồng nhẹ với chi phí thấp hơn nhiều so với luồng truyền thống. Nhờ đó, các ứng dụng có thể sử dụng mô hình lập trình đồng bộ quen thuộc của Blocking IO nhưng vẫn đạt khả năng mở rộng gần tương đương với nhiều giải pháp Non Blocking IO. Đây được xem là bước tiến quan trọng giúp đơn giản hóa phát triển các hệ thống hiệu năng cao trong tương lai.

3. Đòi hỏi sự thích ứng với kỷ nguyên đa nhân
Sự gia tăng số lượng lõi CPU trên các máy chủ hiện đại đang thúc đẩy các ứng dụng tận dụng tốt hơn khả năng xử lý song song. Các hệ thống không còn chỉ tập trung vào việc tối ưu từng luồng riêng lẻ mà cần khai thác hiệu quả toàn bộ tài nguyên phần cứng.
Trong bối cảnh đó, cả Blocking IO và Non Blocking IO đều đang được cải tiến để hoạt động hiệu quả hơn trên các kiến trúc đa nhân. Các kỹ thuật như Thread Pool, Worker Threads, Event Loop đa luồng và xử lý song song đang được áp dụng rộng rãi nhằm tận dụng tối đa năng lực tính toán của phần cứng hiện đại. Điều này giúp các ứng dụng có thể xử lý nhiều yêu cầu hơn mà không làm tăng đáng kể chi phí vận hành
4. Kiến trúc hướng sự kiện toàn phần trên Cloud
Sự phát triển mạnh mẽ của Cloud Computing đang thúc đẩy việc áp dụng các kiến trúc hướng sự kiện (Event-Driven Architecture) trong xây dựng hệ thống. Thay vì xử lý các yêu cầu theo mô hình đồng bộ truyền thống, các thành phần trong hệ thống sẽ giao tiếp với nhau thông qua sự kiện, hàng đợi thông điệp hoặc nền tảng streaming dữ liệu.
Trong môi trường này, Non Blocking IO ngày càng đóng vai trò quan trọng nhờ khả năng xử lý đồng thời lượng lớn sự kiện và kết nối mạng. Các công nghệ như Apache Kafka, RabbitMQ, AWS Lambda và nhiều nền tảng serverless hiện đại đều tận dụng mạnh mẽ các cơ chế bất đồng bộ và hướng sự kiện. Tuy nhiên, Blocking IO vẫn tiếp tục được sử dụng ở những nghiệp vụ yêu cầu tính nhất quán cao hoặc quy trình xử lý tuần tự.

Một số câu hỏi thường gặp về Blocking IO và Non Blocking IO
Blocking IO và Non Blocking IO là những khái niệm quan trọng trong lập trình và thiết kế hệ thống nhưng cũng là chủ đề khiến nhiều người mới học dễ nhầm lẫn. Dưới đây là những câu hỏi thường gặp giúp bạn hiểu rõ hơn về sự khác biệt, cách hoạt động và ứng dụng thực tế của hai mô hình I/O này.
1. Có phải hệ thống sử dụng Non Blocking IO luôn nhanh hơn Blocking IO?
Không phải lúc nào Non Blocking IO cũng nhanh hơn Blocking IO. Hiệu năng của hệ thống còn phụ thuộc vào đặc điểm nghiệp vụ, kiến trúc ứng dụng, cấu hình phần cứng và cách triển khai thực tế:
- Non Blocking IO thường phát huy ưu thế trong các hệ thống có số lượng lớn kết nối đồng thời hoặc phải thực hiện nhiều thao tác I/O như truy vấn cơ sở dữ liệu, gọi API và giao tiếp mạng.
- Đối với các ứng dụng quy mô nhỏ hoặc các tác vụ xử lý tuần tự đơn giản, Blocking IO vẫn có thể đáp ứng tốt nhu cầu với chi phí phát triển thấp hơn và mã nguồn dễ bảo trì hơn.
2. Async/await có phải là Non Blocking IO không?
Không hoàn toàn. Async/Await là cú pháp giúp lập trình viên viết mã bất đồng bộ theo cách dễ đọc và dễ bảo trì hơn nhưng bản thân Async/Await không phải là Non Blocking IO. Một đoạn mã có thực sự hoạt động theo cơ chế Non Blocking IO hay không còn phụ thuộc vào thư viện, framework hoặc runtime bên dưới.
Ví dụ, trong Node.js, Async/Await thường được sử dụng cùng các API bất đồng bộ nên mang lại lợi ích của Non Blocking IO. Ngược lại, nếu Async/Await được gọi đến một tác vụ Blocking, luồng xử lý vẫn có thể bị chặn.
3. Vì sao IO Blocking gây chậm hệ thống khi traffic lớn?
Trong mô hình Blocking IO, mỗi yêu cầu thường cần một luồng riêng để xử lý. Khi luồng thực hiện thao tác I/O như truy vấn cơ sở dữ liệu hoặc gọi dịch vụ bên ngoài, nó sẽ phải chờ cho đến khi nhận được kết quả.
Khi lượng truy cập tăng cao, số lượng luồng ở trạng thái chờ cũng tăng theo. Điều này làm tiêu tốn nhiều CPU, bộ nhớ và chi phí quản lý luồng của hệ điều hành. Nếu số lượng kết nối vượt quá khả năng xử lý của máy chủ, hệ thống có thể phản hồi chậm hoặc thậm chí ngừng phục vụ các yêu cầu mới.
4. Tại sao Node.js là đơn luồng nhưng lại xử lý được Non Blocking IO?
Nodejs sử dụng một luồng chính (Main Thread) để chạy Event Loop, nhưng các thao tác I/O như đọc file, truy vấn mạng hoặc truy cập cơ sở dữ liệu không được xử lý trực tiếp trên luồng này. Thay vào đó, chúng được chuyển cho hệ điều hành hoặc Thread Pool của thư viện libuv xử lý ở phía dưới.
Khi thao tác I/O hoàn tất, kết quả sẽ được đưa trở lại Event Loop để tiếp tục xử lý. Nhờ cơ chế này, luồng chính không phải chờ các tác vụ I/O hoàn thành và có thể tiếp tục phục vụ các yêu cầu khác. Đây là lý do Node.js có thể xử lý hàng nghìn kết nối đồng thời dù về mặt lập trình ứng dụng thường chỉ sử dụng một luồng chính.

Tóm lại, Blocking IO và Non Blocking IO là hai mô hình xử lý Input/Output quan trọng, đóng vai trò nền tảng trong việc xây dựng các ứng dụng và hệ thống hiện đại. Trong khi Blocking IO nổi bật nhờ cơ chế hoạt động đơn giản, dễ triển khai và phù hợp với các ứng dụng có quy mô nhỏ hoặc yêu cầu xử lý tuần tự thì Non Blocking IO lại mang đến khả năng tận dụng tài nguyên hiệu quả, hỗ trợ xử lý lượng lớn kết nối đồng thời và đáp ứng tốt nhu cầu mở rộng của các hệ thống hiện đại. Hy vọng qua bài viết của Phương Nam Vina, bạn đã hiểu rõ Blocking IO là gì, Non Blocking IO là gì, sự khác biệt giữa hai mô hình cũng như cách ứng dụng chúng trong thực tế. Từ đó, bạn có thể đưa ra lựa chọn phù hợp khi thiết kế và tối ưu hệ thống, góp phần xây dựng các ứng dụng có hiệu năng cao, khả năng mở rộng tốt và đáp ứng hiệu quả nhu cầu của người dùng.
Tham khảo thêm:
Xây dựng hệ thống web linh hoạt với event-driven architecture
Kiến trúc thông tin website và cách để người dùng không lạc lối
Hướng dẫn kiểm tra tính thân thiện của website chuẩn chuyên gia
