2011-10-03 43 views
25

Vì vậy, tôi hiểu khái niệm về sự kiện máy chủ gửi (EventSource):Sự kiện máy chủ gửi thực sự hoạt động như thế nào?

  • Một khách hàng kết nối với một thiết bị đầu cuối thông qua EventSource
  • Khách hàng chỉ lắng nghe các thông điệp được gửi từ thiết bị đầu cuối

Điều Tôi đang bối rối về cách nó hoạt động trên máy chủ. Tôi đã xem xét các ví dụ khác nhau, nhưng cái mà tôi nghĩ đến là của Mozilla: http://hacks.mozilla.org/2011/06/a-wall-powered-by-eventsource-and-server-sent-events/

Đây có thể là một ví dụ tồi, nhưng nó có ý nghĩa như thế nào về phía máy chủ sẽ hoạt động, như tôi hiểu :

  • Something thay đổi trong một kho dữ liệu, chẳng hạn như một cơ sở dữ liệu
  • một server-side các cuộc thăm dò script kho dữ liệu mỗi thứ N thứ hai
  • Nếu kịch bản bỏ phiếu thông báo một sự thay đổi, một sự kiện máy chủ gửi là bắn tới khách hàng

Điều đó có hợp lý không? Đó thực sự là cách nó hoạt động từ góc độ barebones?

Trả lời

40

Trang web bác sĩ HTML5 có great write-up về các sự kiện do máy chủ gửi, nhưng tôi cũng sẽ cố gắng cung cấp tóm tắt ngắn (hợp lý) tại đây.

Sự kiện do máy chủ gửi là cốt lõi, kết nối http chạy dài, loại mime đặc biệt (text/event-stream) và tác nhân người dùng cung cấp API EventSource. Cùng nhau, chúng tạo nền móng cho một kết nối một chiều giữa máy chủ và máy khách, nơi các tin nhắn có thể được gửi từ máy chủ đến máy khách.

Về phía máy chủ, nó khá đơn giản. Tất cả các bạn thực sự cần phải làm là thiết lập các tiêu đề sau http:

Content-Type: text/event-stream 
Cache-Control: no-cache 
Connection: keep-alive 

Hãy chắc chắn để đáp ứng với mã 200 và không 204 hoặc bất kỳ mã khác, vì điều này sẽ gây ra đại lý người dùng phù hợp để ngắt kết nối. Ngoài ra, hãy đảm bảo không kết thúc kết nối ở phía máy chủ. Bây giờ bạn được tự do bắt đầu đẩy tin nhắn xuống kết nối đó. Trong nodejs (sử dụng nhanh), điều này có thể trông giống như sau:

app.get("/my-stream", function(req, res) { 
    res.status(200) 
     .set({ "content-type" : "text/event-stream" 
      , "cache-control" : "no-cache" 
      , "connection" : "keep-alive" 
      }) 

    res.write("data: Hello, world!\n\n") 
}) 

Trên máy khách, bạn chỉ cần sử dụng EventSource API, như bạn lưu ý:

var source = new EventSource("/my-stream") 
source.addEventListener("message", function(message) { 
    console.log(message.data) 
}) 

Và đó là nó, về cơ bản.

Bây giờ, trên thực tế, điều thực sự xảy ra ở đây là kết nối được máy chủ và khách hàng giữ lại bằng phương tiện của một hợp đồng tương hỗ. Máy chủ sẽ giữ kết nối còn sống miễn là nó phù hợp. Nếu nó muốn, nó có thể chấm dứt kết nối và đáp ứng với một 204 No Content thời gian tới khách hàng cố gắng kết nối. Điều này sẽ khiến khách hàng ngừng tìm cách kết nối lại. Tôi không chắc chắn nếu có một cách để kết thúc kết nối trong một cách mà khách hàng được nói không kết nối lại ở tất cả, do đó bỏ qua các khách hàng cố gắng kết nối lại một lần.

Như đã đề cập, khách hàng cũng sẽ giữ kết nối luôn hoạt động và cố gắng kết nối lại nếu bị ngắt. Thuật toán để kết nối lại được xác định trong spec và khá thẳng về phía trước.

Một bit cực kỳ quan trọng mà tôi cho đến nay hầu như không chạm vào tuy nhiên là loại mime. Loại mime xác định định dạng của thông báo sắp kết nối. Tuy nhiên, lưu ý rằng nó không đọc định dạng của các nội dung của thư, chỉ cấu trúc của thư. Loại mime là cực kỳ thẳng về phía trước. Thông điệp chủ yếu là các cặp thông tin/khóa/giá trị. Chìa khóa phải là một trong một bộ được xác định trước:

  • id - id của thông điệp
  • dữ liệu - dữ liệu thực tế
  • sự kiện - loại sự kiện
  • retry - milleseconds user agent nên chờ đợi trước khi thử lại kết nối không thành công

Cần bỏ qua bất kỳ phím nào khác. Những lời nói được thì giới hạn bởi việc sử dụng hai ký tự newline: \n\n

Sau đây là một thông điệp hợp lệ: (ký tự dòng mới nhất bổ sung cho tính cách rườm rà)

data: Hello, world! 
\n 

Các khách hàng sẽ thấy điều này như: Hello, world!.

Như là thế này:

data: Hello, 
data: world! 
\n 

Các khách hàng sẽ thấy điều này như: Hello,\nworld!.

Điều đó khá nhiều tổng kết những gì mà máy chủ gửi sự kiện là: kết nối http không chạy bộ trong thời gian dài, loại mime và API javascript đơn giản.

Để biết thêm thông tin, tôi khuyên bạn nên đọc specification. Nó nhỏ và mô tả mọi thứ rất tốt (mặc dù các yêu cầu của phía máy chủ có thể được tóm tắt tốt hơn một chút). Tôi khuyên bạn nên đọc nó cho hành vi mong đợi với một số mã trạng thái http nhất định.

+3

Điều này là tuyệt vời để biết chi tiết về khách hàng và cách kết nối hoạt động, nhưng nếu sự kiện cần được gửi cho một thay đổi cơ sở dữ liệu, tôi cho rằng không có tùy chọn nào khác ngoài liên tục thăm dò cơ sở dữ liệu trên máy chủ? Tôi nghĩ rằng đây là những gì op đã yêu cầu? Có một giải pháp hiệu quả hơn phía máy chủ - rõ ràng nó sẽ không mất nhiều kết nối trên một máy chủ doanh nghiệp nhỏ để bắt đầu làm chậm mọi thứ xuống nếu có vòng liên tục kiểm tra các thay đổi db. –

+1

Máy khách chỉ nhận được tin nhắn bất cứ khi nào máy chủ quyết định gửi tin nhắn, nó không bao giờ thăm dò ý kiến ​​bất cứ điều gì. Máy chủ được tự do tìm ra khi nào và tại sao gửi tin nhắn. Điều đó có thể được thực hiện phía máy chủ bằng cách sử dụng bỏ phiếu hoặc bất kỳ kỹ thuật nào phù hợp với hóa đơn. Các kết nối trên máy chủ có thể được gộp lại và một tin nhắn có thể được gửi xuống mỗi kết nối, cung cấp cho bạn một loại chức năng phát sóng. Do đó, máy chủ có thể là kết nối duy nhất với một DB, nhưng phát sóng tới tấn khách hàng được kết nối với máy chủ. Tôi nghĩ rằng câu hỏi là chung chung hơn mặc dù. –

+2

Thử lại: bit mili giây - thiên tài! Đã lưu da của tôi! –

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