Cách tiếp cận phổ biến, như Ozz đã đề cập , là một hàng đợi tin nhắn . Từ phối cảnh thiết kế, hàng đợi tin nhắn về cơ bản là hàng đợi FIFO , đây là kiểu dữ liệu khá cơ bản:
Điều làm cho một hàng đợi tin nhắn trở nên đặc biệt là trong khi ứng dụng của bạn chịu trách nhiệm cho việc xếp hàng, một quy trình khác sẽ chịu trách nhiệm hủy xếp hàng. Trong xếp hàng biệt ngữ, ứng dụng của bạn là người gửi tin nhắn và quá trình hủy xếp hàng là người nhận. Ưu điểm rõ ràng là toàn bộ quá trình không đồng bộ, người nhận hoạt động độc lập với người gửi, miễn là có thông điệp cần xử lý. Nhược điểm rõ ràng là bạn cần một thành phần phụ, người gửi, để toàn bộ hoạt động.
Vì kiến trúc của bạn bây giờ phụ thuộc vào hai thành phần trao đổi thông điệp, bạn có thể sử dụng thuật ngữ giao tiếp giữa các quá trình ưa thích cho nó.
Làm thế nào để giới thiệu một hàng đợi ảnh hưởng đến thiết kế ứng dụng của bạn?
Một số hành động trong ứng dụng của bạn tạo ra email. Giới thiệu hàng đợi tin nhắn có nghĩa là những hành động đó bây giờ sẽ đẩy tin nhắn đến hàng đợi thay thế (và không có gì nữa). Những thư đó sẽ mang lượng thông tin tối thiểu tuyệt đối cần thiết để tạo email khi người nhận của bạn xử lý chúng.
Định dạng và nội dung của tin nhắn
Định dạng và nội dung tin nhắn của bạn hoàn toàn phụ thuộc vào bạn, nhưng bạn nên nhớ rằng càng nhỏ càng tốt. Hàng đợi của bạn phải càng nhanh để viết và xử lý càng tốt, việc ném một lượng lớn dữ liệu vào đó có thể sẽ tạo ra một nút cổ chai.
Hơn nữa, một số dịch vụ xếp hàng dựa trên đám mây có các hạn chế về kích thước thư và có thể phân chia các thư lớn hơn. Bạn sẽ không nhận thấy, các tin nhắn chia sẽ được phục vụ như một khi bạn yêu cầu chúng, nhưng bạn sẽ bị tính phí cho nhiều tin nhắn (giả sử tất nhiên bạn đang sử dụng một dịch vụ yêu cầu phải trả phí).
Thiết kế của người nhận
Vì chúng ta đang nói về một ứng dụng web, một cách tiếp cận phổ biến cho người nhận của bạn sẽ là một tập lệnh cron đơn giản. Nó sẽ chạy mỗi x
phút (hoặc giây) và nó sẽ:
- Pop
n
lượng thông điệp từ hàng đợi,
- Xử lý các tin nhắn (tức là gửi email).
Lưu ý rằng tôi đang nói pop thay vì lấy hoặc tìm nạp, đó là vì người nhận của bạn không chỉ nhận các mục từ hàng đợi, mà còn xóa chúng (tức là xóa chúng khỏi hàng đợi hoặc đánh dấu chúng là đã xử lý). Chính xác điều đó sẽ xảy ra như thế nào tùy thuộc vào việc bạn thực hiện hàng đợi tin nhắn và nhu cầu cụ thể của ứng dụng.
Tất nhiên những gì tôi mô tả về cơ bản là một hoạt động hàng loạt , cách đơn giản nhất để xử lý hàng đợi. Tùy thuộc vào nhu cầu của bạn, bạn có thể muốn xử lý tin nhắn theo cách phức tạp hơn (điều đó cũng sẽ gọi cho một hàng đợi phức tạp hơn).
Giao thông
Người nhận của bạn có thể xem xét lưu lượng truy cập và điều chỉnh số lượng tin nhắn mà nó xử lý dựa trên lưu lượng truy cập tại thời điểm nó chạy. Một cách tiếp cận đơn giản sẽ là dự đoán số giờ lưu lượng truy cập cao của bạn dựa trên dữ liệu lưu lượng truy cập trong quá khứ và giả sử bạn đã sử dụng tập lệnh cron chạy mỗi x
phút bạn có thể làm điều gì đó như sau:
if(
now() > 2pm && now() < 7pm
) {
process(10);
} else {
process(100);
}
function process(count) {
for(i=0; i<=count; i++) {
message = dequeue();
mail(message)
}
}
Một cách tiếp cận rất ngây thơ và bẩn thỉu, nhưng nó hoạt động. Nếu không, tốt, cách tiếp cận khác sẽ là tìm ra lưu lượng truy cập hiện tại của máy chủ của bạn ở mỗi lần lặp và điều chỉnh số lượng mục xử lý cho phù hợp. Vui lòng không tối ưu hóa vi mô nếu điều đó không thực sự cần thiết, bạn sẽ lãng phí thời gian của mình.
Lưu trữ hàng đợi
Nếu ứng dụng của bạn đã sử dụng cơ sở dữ liệu, thì một bảng duy nhất trên đó sẽ là giải pháp đơn giản nhất:
CREATE TABLE message_queue (
id int(11) NOT NULL AUTO_INCREMENT,
timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
processed enum('0','1') NOT NULL DEFAULT '0',
message varchar(255) NOT NULL,
PRIMARY KEY (id),
KEY timestamp (timestamp),
KEY processed (processed)
)
Nó thực sự không phức tạp hơn thế. Tất nhiên bạn có thể làm cho nó phức tạp như bạn cần, ví dụ, bạn có thể thêm một trường ưu tiên (điều đó có nghĩa là đây không còn là hàng đợi FIFO, nhưng nếu bạn thực sự cần nó, ai quan tâm?). Bạn cũng có thể làm cho nó đơn giản hơn, bằng cách bỏ qua trường được xử lý (nhưng sau đó bạn phải xóa các hàng sau khi bạn xử lý chúng).
Một bảng cơ sở dữ liệu sẽ lý tưởng cho 2000 tin nhắn mỗi ngày, nhưng có lẽ nó sẽ không mở rộng tốt cho hàng triệu tin nhắn mỗi ngày. Có một triệu yếu tố để xem xét, mọi thứ trong cơ sở hạ tầng của bạn đóng một vai trò trong khả năng mở rộng tổng thể của ứng dụng của bạn.
Trong mọi trường hợp, giả sử bạn đã xác định hàng đợi dựa trên cơ sở dữ liệu là một nút cổ chai, bước tiếp theo sẽ là xem xét một dịch vụ dựa trên đám mây. Amazon SQS là một dịch vụ tôi đã sử dụng và đã làm những gì nó hứa hẹn. Tôi chắc chắn có khá nhiều dịch vụ tương tự ngoài kia.
Hàng đợi dựa trên bộ nhớ cũng là một cái gì đó để xem xét, đặc biệt là đối với hàng đợi ngắn. memcached là tuyệt vời như lưu trữ hàng đợi tin nhắn.
Bất cứ lưu trữ nào bạn quyết định xây dựng hàng đợi của mình, hãy thông minh và trừu tượng hóa nó. Cả người gửi và người nhận của bạn đều không nên bị ràng buộc với một bộ lưu trữ cụ thể, nếu không, việc chuyển sang một bộ lưu trữ khác sau đó sẽ là một PITA hoàn chỉnh.
Cách tiếp cận thực tế cuộc sống
Tôi đã tạo một hàng đợi tin nhắn cho các email rất giống với những gì bạn đang làm. Đó là một dự án PHP và tôi đã xây dựng nó xung quanh Zend Queue , một thành phần của Khung công tác Zend cung cấp một số bộ điều hợp cho các kho lưu trữ khác nhau. Kho của tôi đâu:
- Mảng PHP để thử nghiệm đơn vị,
- Amazon SQS đang sản xuất,
- MySQL trên dev và môi trường thử nghiệm.
Thông điệp của tôi đơn giản như có thể, ứng dụng của tôi đã tạo ra các mảng nhỏ với thông tin cần thiết ( [user_id, reason]
). Kho lưu trữ thư là phiên bản tuần tự của mảng đó (đầu tiên là định dạng tuần tự hóa nội bộ của PHP, sau đó là JSON, tôi không nhớ tại sao tôi lại chuyển đổi). Đây reason
là một hằng số và tất nhiên tôi có một bảng lớn ở đâu đó ánh xạ reason
tới các giải thích đầy đủ hơn (tôi đã quản lý để gửi khoảng 500 email cho khách hàng bằng mật mã reason
thay vì tin nhắn đầy đủ một lần).
đọc thêm
Tiêu chuẩn:
Công cụ:
Thú vị đọc: