2011-09-18 47 views
12

Tôi cần phát triển nguồn cấp dữ liệu hoạt động gần đây theo thời gian thực trong django (với AJAX long-polling), và tôi tự hỏi chiến lược tốt nhất cho phía máy chủ là gì.Kỹ thuật thông báo nhẹ

Mã giả:

def recent_activity_post_save(): 
    notify_view() 

[in the view] 
while not new_activity(): 
    sleep(1) 
return HttpResponse(new_activity()) 

Điều đầu tiên mà đến trong tâm trí được truy vấn DB mỗi giây. Không khả thi. Các lựa chọn khác:

  1. sử dụng bộ nhớ cache như một dịch vụ thông báo
  2. sử dụng một công cụ chuyên dụng, như cần tây (Tôi không muốn làm điều đó, bởi vì nó có vẻ như quá mức cần thiết)

gì là tốt nhất đường đến đây?

Trả lời

5

tôi sẽ đề nghị giữ nó đơn giản ...

Tạo một bảng cơ sở dữ liệu để lưu trữ các sự kiện của bạn, chèn vào bảng mà khi thích hợp, sau đó chỉ cần thực hiện một kỹ thuật ajax bỏ phiếu đơn giản để đạt server mỗi x giây ở phía khách hàng.

Tôi có mối quan tâm với các giải pháp khác xem xét sử dụng phương pháp tiếp cận thông báo đẩy hoặc sử dụng kho lưu trữ dữ liệu noSql. Nó phức tạp hơn rất nhiều so với một hệ thống thông báo kéo truyền thống bằng cách sử dụng các công cụ được xây dựng trong khung công tác Django, và ngoại trừ các trường hợp ngoại lệ rất hiếm, là quá mức cần thiết. Trừ khi bạn yêu cầu một giải pháp thời gian thực nghiêm ngặt, hãy đơn giản và sử dụng các công cụ đã tồn tại trong khung công tác, và đối với những người phản đối dựa trên cơ sở dữ liệu hoặc hiệu suất mạng, tất cả những gì tôi phải nói là tối ưu hóa sớm là gốc của Tất cả đều xấu xa.

Xây dựng mô hình có chứa dữ liệu hoạt động gần đây cụ thể cho ứng dụng của bạn, bất cứ khi nào ứng dụng của bạn thực hiện hoạt động mới bạn có thể chèn vào bảng này.

Chế độ xem của bạn sẽ đơn giản giống như bất kỳ chế độ xem nào khác, kéo các hàng x hàng từ bảng RecentActivity này (tùy chọn dựa trên tham số truy vấn và bất kỳ thứ gì).

Sau đó, ở phía khách hàng, bạn chỉ cần có một con chó ajax đơn giản đánh vào chế độ xem của bạn sau mỗi x giây. Không thiếu các plugin phức tạp và công nghệ, bạn có thể sử dụng, nhưng văn bản của riêng bạn mà không phải là phức tạp hoặc là:

function simplePoll() { 
    $.get("your-url", {query-parameters}, function(data){ 
    //do stuff with the data, replacing a div or updating json or whatever 
    setTimeout(simplePoll, delay); 
    }); 
} 

Ý kiến ​​của tôi là vấn đề hiệu suất không thực sự vấn đề cho đến khi trang web của bạn là thành công đủ cho họ là một vấn đề. Cơ sở dữ liệu quan hệ truyền thống có thể mở rộng khá tốt cho đến khi bạn bắt đầu đạt tới mức thành công như Twitter, Google, v.v. Hầu hết chúng ta không ở cấp độ đó :)

0

Bạn có thể sử dụng trình kích hoạt (được kích hoạt bất cứ khi nào một bài đăng mới được tạo). Trình kích hoạt này có thể viết, ví dụ, một tập tin mới trong một thư mục bỏ phiếu với các dữ liệu cần thiết trong nó (nói khóa chính). Con trăn của bạn sau đó có thể chỉ xem thư mục đó để tạo các tệp mới mà không cần phải chạm vào cơ sở dữ liệu cho đến khi một tệp mới xuất hiện.

1

Bạn có thể sử dụng giải pháp sao chổi, như Ape project. Loại dự án này được thiết kế để gửi dữ liệu thời gian thực đến trình duyệt và có thể sử dụng tính năng web socket của trình duyệt hiện đại.

0

Nếu bạn đang theo sau giải pháp sao chổi thì you could use orbited. Hãy để tôi cảnh báo bạn rằng mặc dù đó là một giải pháp khá thích hợp nhưng rất khó để tìm tài liệu tốt về cách triển khai và sử dụng orbited trong môi trường sản xuất.

0

Đây là một cuộc thảo luận tương tự, trả lời từ góc độ phía máy chủ: Making moves w/ websockets and python/django (/ twisted?) , câu trả lời quan trọng nhất là this one.

Ngoài ra còn có this answer, trỏ đến một thay thế rất chắc chắn để tìm cách này từ Django.

Nếu bạn thực sự muốn điều này được cung cấp từ ứng dụng Django hiện tại của bạn, không thực hiện phía máy chủ này. Việc giữ con tin HTTP socket đó vào kết nối của một trình duyệt duy nhất là một cách nhanh chóng để phá vỡ ứng dụng của bạn. Hai lựa chọn hợp lý là: khám phá các tùy chọn ổ cắm web khác nhau (như trên sử dụng Kim tự tháp để lưu trữ dịch vụ) hoặc xem trình duyệt gửi yêu cầu thăm dò định kỳ tới máy chủ tìm kiếm các bản cập nhật.

+1

Đây là lời khuyên tốt, nhưng câu hỏi đã nói cụ thể "trong django (với AJAX bỏ phiếu dài)". – dkamins

2

Bạn đã cân nhắc sử dụng Tín hiệu chưa? Bạn có thể gửi một tín hiệu trong recent_activity_post_save() và có thể có một trình lắng nghe lưu trữ thông tin trong bộ nhớ cache.

Chế độ xem sẽ chỉ đề cập đến bộ nhớ cache để xem có thông báo mới hay không. Tất nhiên bạn không cần tín hiệu, nhưng IMHO nó sẽ là một chút sạch hơn theo cách đó, vì bạn có thể thêm nhiều "trình xử lý thông báo".

Điều này có vẻ tối ưu vì bạn không cần thăm dò ý kiến ​​của DB (tải nhân tạo), thông báo "hiển thị" gần như ngay lập tức (chỉ sau thời gian cần thiết để xử lý tín hiệu và tương tác với bộ đệm).

Vì vậy, các giả sẽ trông như thế này:

# model 
def recent_activity_post_save(): 
    post_save_signal.send() 

# listener 
def my_handler(...): 
    cache.set('notification', ....) 

post_save_signal.connect(my_handler) 

# view 
def my_view(request): 
    new_notification = None 
    while not new_notification: 
     sleep(1) 
     new_notification = cache.get('notification') 
    return HttpResponse(...) 
+0

đây chính xác là những gì tôi đang sử dụng ngay bây giờ; nó có vẻ tối ưu với tôi nữa, nhưng tôi đang tìm ý kiến ​​khác về chủ đề này. +1 –

+0

Tôi thích giải pháp này cho đến khi tôi nhìn thấy dòng 'while not new_notification' ... về mặt lý thuyết có thể treo vô thời hạn theo yêu cầu - có lẽ là yêu cầu bỏ phiếu ajax của một số loại - trong khi chờ đợi thông báo mới đến? Sẽ không tốt hơn nếu chỉ trả lại một tập dữ liệu trống từ chế độ xem nếu bộ nhớ cache trống? –

+0

@DMactheDestroyer là một số loại giả mã, tất nhiên nó chỉ trả lại kết quả trống sau 30 giây hoặc lâu hơn nếu không có hoạt động mới. –

0

Bạn nên quyết định nếu bạn thà đi với một "kéo" hoặc "đẩy" kiến ​​trúc để cung cấp tin nhắn của bạn, xem post on quora này! Nếu bạn muốn đi cho một giải pháp mà "đẩy" các thông báo cho người nhận bộ nhớ đệm của họ/hệ thống dựa trên nosql là thích hợp hơn vì họ không sản xuất như một tải cao cho rất nhiều hành động viết.

Làm lại ví dụ với cấu trúc danh sách tập hợp/danh sách được sắp xếp cung cấp cho bạn rất nhiều ví dụ. Xem ví dụ. this post (mặc dù không phải python của nó) để có được một ý tưởng. Bạn cũng có thể xem xét các hàng đợi tin nhắn "thực" như ví dụ RabbitMQ!

Đối với kết nối máy khách, các bài đăng khác ở đây đã cho bạn một số ý tưởng về cách sử dụng các khuôn khổ xoắn và tương tự.

Và cần tây luôn có thể là một công cụ tốt, bạn có thể. có tất cả các văn bản để hoạt động của người dùng ity suối trong một công việc không đồng bộ!

+0

cảm ơn vì sự thấu hiểu; Tôi đã tìm kiếm một giải pháp _lightweight_ mặc dù, bởi vì không có điểm trong việc cài đặt một cơ sở dữ liệu NoSQL cho một trang duy nhất trong một trang web, phải không? –

0

Tôi không thấy cần phải giới hạn bản thân khi sử dụng phiếu bầu dài nếu điều đó không thực sự cần thiết. Có các thư viện được viết để tận dụng lợi thế của tùy chọn tốt nhất có thể (có thể là bỏ phiếu ngắn, bỏ phiếu dài, websockets hoặc thậm chí là plugin flash nhỏ nếu không có tùy chọn nào trước đó). Node.js có một trong những thư viện tốt nhất hiện có cho một công việc như vậy gọi là Socket.IO, nhưng may mắn cũng có hai triển khai Python, gevent-socketiotornadio, nhưng sau đó được xây dựng trên khuôn khổ lốc xoáy, vì vậy có thể ra khỏi câu hỏi.

Nếu phù hợp với bạn, bạn có thể kết hợp chúng với một số cơ sở dữ liệu NoSQL (tài liệu), được chứng minh nhanh hơn và nhẹ hơn so với cơ sở dữ liệu quan hệ. Có rất nhiều tùy chọn, bao gồm CouchDB, MongoDB, Redis, ... Sự kết hợp của Socket.IO và DB dựa trên tài liệu đã được chứng minh là nhanh, nhẹ và đáng tin cậy.

Mặc dù tôi thấy bạn đã xem NoSQL trong nhận xét, ý kiến ​​cá nhân của tôi là, nếu bạn cần một giải pháp nhanh chóng và dễ dàng, và các tùy chọn ở trên phù hợp với bạn, đây là cơ hội tốt nhất bạn có thể thực hiện.

Các vấn đề liên quan