Server-Sent Events là gì? Luồng, cách dùng và giới hạn
Scrapeless Agent Browser chạy tự động hóa trình duyệt với các website động có trang có thể nhận cập nhật thông qua server-sent events.
Tóm tắt
- Server-sent events mang các bản cập nhật từ server tới client. Luồng vẫn là một phản hồi HTTP chứ không phải kênh nhắn tin hai chiều.
- Ranh giới sự kiện khác với các khối (chunk) mạng. Trình tiêu thụ phải phân tích cú pháp định dạng event-stream trước khi coi văn bản là một thông điệp.
- Streaming cần một ranh giới quan sát rõ ràng. Một kết nối có thể vẫn mở sau khi thông tin mà tác vụ của bạn cần đã đến nơi.
- ID sự kiện tự thân không đảm bảo phân phối đúng-một-lần. Hành vi lưu giữ, phát lại và lưu trữ thuộc về hợp đồng ứng dụng.
Server-Sent Events là một luồng HTTP một chiều
Server-sent events, thường được viết tắt là SSE, cho phép server gửi một chuỗi sự kiện dạng văn bản qua một phản hồi HTTP tồn tại lâu. Client mở kết nối và server ghi các bản cập nhật khi chúng sẵn sàng. Một dashboard có thể nhận tiến độ job hoặc một trang có thể hiển thị kết quả tăng dần mà không phải yêu cầu lại toàn bộ tài nguyên mỗi lần có thay đổi.
Đặc tả HTML event-stream định nghĩa cả định dạng sự kiện và giao diện EventSource của trình duyệt. Kiểu media của phản hồi là text/event-stream, và luồng là văn bản UTF-8. SSE không yêu cầu JSON làm định dạng payload. Ứng dụng có thể đặt JSON đã được tuần tự hóa vào trong dữ liệu của một sự kiện, nhưng việc phân tích cú pháp JSON đó là bước riêng sau khi đã đóng khung sự kiện.
SSE là một chiều ở tầng nhắn tin của ứng dụng. Trình duyệt vẫn gửi HTTP request để mở luồng, và nó có thể gửi các request riêng cho hành động của người dùng. Bản thân luồng sự kiện mang các thông điệp từ server tới client. Sự phân tách này làm SSE hữu ích cho thông báo và hiển thị tiến độ, trong khi vẫn giữ các lệnh trên những endpoint ứng dụng thông thường với cơ chế ủy quyền và kiểm tra riêng.
Cách đóng khung sự kiện biến văn bản thành thông điệp
Một thông điệp SSE gồm các trường được phân tách bằng ký tự xuống dòng và được phát đi tại một dòng trống. Trường data chứa văn bản payload, trường event có thể đặt tên loại sự kiện, và trường id có thể cập nhật định danh sự kiện. Các dòng bắt đầu bằng dấu hai chấm là comment. Nhiều dòng data trong một sự kiện được nối với nhau bằng ký tự xuống dòng.
Một lần đọc từ mạng không tương ứng với một sự kiện. Một khối truyền tải có thể chứa một phần của một trường, vài thông điệp hoàn chỉnh, hoặc phần cuối của một thông điệp và phần đầu của một thông điệp khác. Một trình tiêu thụ tùy biến cần một bộ giải mã văn bản lâu dài và một bộ đệm đóng khung. Tách mỗi khối đến theo ký tự xuống dòng mà không giữ lại phần văn bản chưa hoàn chỉnh có thể làm hỏng cả việc giải mã ký tự lẫn ranh giới thông điệp.
Một sự kiện không có tên sẽ đi tới handler message tổng quát trong EventSource, trong khi sự kiện có tên sử dụng loại sự kiện tương ứng. Lập trình viên ứng dụng nên ghi lại các tên đó và cấu trúc payload của chúng. Một thông điệp tiến độ, một cập nhật mục, và một thông điệp hoàn tất cuối cùng không nên được diễn giải thay cho nhau. Phần truyền tải luồng chỉ phân phối sự kiện; ứng dụng định nghĩa ý nghĩa của từng sự kiện.
EventSource và Fetch cung cấp các giao diện khác nhau
EventSource là API trình duyệt được thiết kế cho luồng sự kiện, trong khi Fetch cung cấp giao diện request và response tổng quát hơn. EventSource nhận một URL và một tập tùy chọn giới hạn thay vì cấu hình request tùy ý. Nó không cung cấp tùy chọn chung để đặt header ủy quyền tùy chỉnh hoặc gửi request body. Điều đó quan trọng khi hợp đồng API yêu cầu một header cụ thể hoặc một request POST.
Một trình tiêu thụ dựa trên Fetch có thể đọc các byte phản hồi dạng streaming và tự cài đặt việc phân tích sự kiện. web Streams API cung cấp trừu tượng hóa luồng, nhưng nó không tự động biến văn bản bất kỳ thành các thông điệp SSE được đóng khung đúng. Một trình tiêu thụ dùng Fetch phải tính đến giải mã gia tăng, ranh giới thông điệp, việc hủy (cancellation), và tín hiệu hoàn tất ở tầng ứng dụng của dịch vụ.
Hãy chọn giao diện dựa trên hợp đồng endpoint. Một dịch vụ được mô tả là streaming có thể gửi JSON phân tách bằng newline, định dạng nhị phân tùy chỉnh, hoặc văn bản phản hồi thông thường thay vì SSE. Hãy kiểm tra kiểu media của phản hồi và cách đóng khung trước khi chọn bộ phân tích. Một trang trực quan cập nhật dần dần cũng không phải bằng chứng đủ: các bản cập nhật đó có thể đến qua SSE, WebSockets, polling, hoặc render phía client từ dữ liệu đã được tải xuống.
| Cơ chế | Hướng và hình dạng | Tình huống phù hợp điển hình |
|---|---|---|
| SSE | Sự kiện văn bản từ server đến client trong một phản hồi HTTP | Cập nhật tiến độ và thông báo |
| WebSockets | Thông điệp hai chiều qua một kết nối lâu dài | Phiên tương tác với nhiều thông điệp hai chiều thường xuyên |
| Polling | Lặp lại các lượt request và response | Các lần kiểm tra thỉnh thoảng khi yêu cầu về độ mới không quá cao |
| Streaming Fetch tổng quát | Các byte phản hồi được mã diễn giải bởi mã ứng dụng | Giao thức streaming tùy chỉnh hoặc yêu cầu request đặc biệt |
Nơi proxy và bộ đệm thay đổi trải nghiệm
Một luồng sự kiện có thể hợp lệ dù có vẻ chậm vì một thành phần đệm phản hồi trước khi chuyển tiếp nó. Reverse proxy, máy chủ ứng dụng, middleware và các lớp nén có thể ảnh hưởng tới thời điểm byte đến được phía client. Hãy kiểm tra toàn bộ đường đi phân phối khi các cập nhật xuất hiện theo từng nhóm lớn thay vì theo nhịp dự kiến. Việc máy chủ ghi dữ liệu nhanh không chứng minh rằng trình duyệt nhận được dữ liệu ngay lập tức.
The Hướng dẫn phân phối sự kiện SSE mô tả định dạng thông điệp và các comment có thể giữ kết nối hoạt động. Các thiết lập vận hành vẫn phụ thuộc vào stack được triển khai. Hãy xem lại timeout nhàn rỗi và cơ chế đệm phản hồi đối với cấu hình máy chủ và proxy cụ thể, và quan sát thời điểm dữ liệu đến trình duyệt thay vì chỉ dựa vào timestamp ở backend.
Quyền sở hữu tài nguyên cũng quan trọng. Mỗi luồng đang mở chiếm trạng thái kết nối ở đâu đó trong hệ thống, ngay cả khi không có sự kiện nào được gửi. Hãy đóng luồng khi người dùng rời khỏi giao diện liên quan hoặc khi một tác vụ quan sát có giới hạn đã có đủ thông tin. Việc lập kế hoạch dung lượng nên tính riêng số kết nối đồng thời và khối lượng sự kiện; một kết nối yên lặng và một kết nối bận rộn có thể có chi phí xử lý rất khác nhau.
ID sự kiện không xác định đảm bảo giao hàng
Một định danh sự kiện cung cấp cho ứng dụng một cách để mô tả vị trí trong luồng của nó. Trình duyệt có thể truyền đạt ID sự kiện cuối cùng khi thiết lập một kết nối event-stream tiếp theo, nhưng một định danh không yêu cầu máy chủ phải giữ lại dữ liệu lịch sử. Chính chính sách lưu giữ và phát lại của máy chủ quyết định liệu một sự kiện bị bỏ lỡ trước đó có thể được cung cấp hay không và cách xử lý một vị trí đã hết hạn.
Xử lý chính xác-một-lần đòi hỏi nhiều hơn là chỉ nhận một ID. Ứng dụng có thể nhận một sự kiện và đóng trước khi lưu nó, hoặc lưu một sự kiện trước khi ghi lại vị trí xử lý của nó. Để tiếp nhận bền vững, hãy xác định danh tính sự kiện và làm rõ hành vi lưu trữ. Việc phát hiện trùng lặp nên sử dụng hợp đồng sự kiện của ứng dụng thay vì giả định rằng phần văn bản nhìn thấy trong payload là định danh duy nhất cho một sự kiện.
Một bộ chỉ báo tiến độ thường không cần lịch sử sự kiện vĩnh viễn. Một sổ cái tài chính hoặc log kiểm toán có các yêu cầu khác và nên sử dụng một giao diện bền vững được tài liệu hóa. Hãy chọn nguồn dữ liệu dựa trên các đảm bảo về bản ghi mà tác vụ cần. Một luồng hình ảnh trực tiếp có thể giúp con người quan sát quy trình nhưng vẫn không phù hợp để làm nguồn duy nhất cho một bộ dữ liệu lịch sử hoàn chỉnh.
Xác thực, nguồn gốc, và payload nhạy cảm
Một endpoint SSE phải thực thi cùng cơ chế phân quyền tài nguyên như các endpoint khác. Khả năng của người dùng trong việc mở một luồng không cho phép truy cập mọi sự kiện mà backend có thể phát. Hãy lọc thông điệp cho người gọi và giữ ranh giới tenant trong logic đăng ký của máy chủ. Tránh đặt bí mật vào URL của luồng chỉ để lách các tùy chọn cấu hình hạn chế của EventSource.
Các luồng cross-origin cũng chịu các quy tắc truy cập của trình duyệt. Mô hình Fetch origin and credentials chi phối cách CORS và thông tin xác thực tương tác với các yêu cầu của trình duyệt. Một phản hồi thành công từ máy chủ là chưa đủ nếu trình duyệt không thể phơi bày nó cho trang gọi. Khi dùng thông tin xác thực, hãy cấu hình origin được phép và cách xử lý thông tin xác thực sao cho khớp với client thực tế.
Log và bản ghi bắt của trình duyệt có thể lưu payload sự kiện. Hãy giữ dữ liệu cá nhân và thông tin xác thực ra khỏi các chẩn đoán thường xuyên, và đặt thời hạn lưu trữ phù hợp cho nội dung luồng đã bắt. Trong quá trình thử nghiệm được cho phép, hãy ghi lại loại sự kiện, định danh đã được khử nhạy cảm, và thời điểm đến khi các trường đó trả lời câu hỏi chẩn đoán. Việc bắt toàn bộ lịch sử sự kiện riêng tư phải đòi hỏi một nhu cầu tác vụ thực sự và quyền cho phép.
Quan sát trạng thái ứng dụng mà bạn thực sự cần
Một tác vụ tự động hóa trình duyệt nên dừng ở một trạng thái trang có ý nghĩa thay vì chờ cho toàn bộ hoạt động mạng kết thúc. Một kết nối SSE có thể giữ mở trong suốt vòng đời của trang. Đối với việc thu thập dữ liệu có giới hạn, hãy xác định selector liên quan, nhãn hoàn tất, định danh bản ghi, hoặc cửa sổ quan sát. Điều kiện mạng-nhàn-rỗi có thể không bao giờ đại diện cho trạng thái hoàn tất đối với một trang có luồng liên tục.
Scrapeless Agent Browser cung cấp môi trường trình duyệt cho việc điều hướng và tương tác trang. Phần Tổng quan Agent Browser mô tả môi trường đó; nó không khiến mọi endpoint event-stream đều trở thành một kênh xuất bền vững được quản lý. Hãy giữ kết nối điều khiển của trình duyệt tách biệt khỏi lưu lượng SSE của trang đích khi chẩn đoán hệ thống. Chúng phục vụ các mục đích khác nhau và có thể đi theo các đường mạng khác nhau.Một tác vụ tiến độ giả định hữu ích là theo dõi một trang việc làm công khai cho đến khi nhãn hoàn tất xuất hiện, rồi đọc phần tóm tắt kết quả có thể nhìn thấy. Tác vụ tự động ghi lại liệu trạng thái hoàn tất có xuất hiện trong cửa sổ quan sát hay không. Nó không suy luận rằng mọi sự kiện tiến độ nội bộ đều đã được lưu trữ. Phần Khái niệm nhắn tin WebSocket giải thích tại sao một kênh hai chiều riêng có thể phù hợp hơn khi ứng dụng cần tương tác hai chiều thường xuyên.
Quyết định SSE có phù hợp với yêu cầu sản phẩm hay không
SSE phù hợp với các giao diện nơi máy chủ có cập nhật để gửi và client chủ yếu lắng nghe. Đây là lựa chọn thực tế cho các luồng trạng thái, thông báo và văn bản gia tăng, miễn là hành vi kết nối và đệm phù hợp với môi trường triển khai. Hãy ưu tiên giao diện khác khi ứng dụng cần xuất dữ liệu khối bền vững, nhắn tin hai chiều tùy ý, hoặc một hình dạng yêu cầu mà client SSE đã chọn không thể thể hiện.
Trước khi áp dụng SSE, hãy ghi lại các loại thông điệp, phạm vi phân quyền, hành vi hoàn tất, kỳ vọng lưu giữ, và việc dọn dẹp tài nguyên. Hãy xem lại Scrapeless pricing riêng khi lập ngân sách cho các quan sát trình duyệt. Một thiết kế vững chắc đo lường khối lượng công việc hữu ích được tạo ra bởi phiên và đóng kết nối khi công việc đó hoàn tất, thay vì xem một trang mở vô thời hạn là thu thập thành công.
Kết luận
Sử dụng SSE khi một trang cần các cập nhật văn bản xuất phát từ máy chủ và ứng dụng có thể xác định ý nghĩa và vòng đời của chúng. Xác thực cách đóng gói, quy tắc nguồn gốc, bộ đệm và kỳ vọng phân phối trước khi phụ thuộc vào luồng. Đối với các quan sát trong trình duyệt, hãy thu thập trạng thái cần thiết trong một phạm vi được xác định và đóng phiên ngay khi quan sát đó hoàn tất.
Xây dựng quy trình dữ liệu Web của bạn
Sử dụng Agent Browser để kiểm tra các trang động với điều kiện hoàn thành rõ ràng và phạm vi quan sát có giới hạn.
Đăng ký hôm nay và nhận $5 tín dụng miễn phí — không cần thẻ tín dụng.
Nhận $5 tín dụng của bạn →Câu hỏi thường gặp
Server-sent events có giống WebSockets không?
Server-sent events và WebSockets cung cấp các mô hình nhắn tin khác nhau. SSE gửi các sự kiện văn bản từ máy chủ đến máy khách qua một phản hồi HTTP. WebSockets hỗ trợ nhắn tin hai chiều. Hãy lựa chọn giữa chúng dựa trên hướng truyền, cách đóng khung, vòng đời và yêu cầu phân phối của ứng dụng thay vì dựa trên giao diện bề ngoài.
SSE có luôn chứa JSON không?
SSE không yêu cầu JSON. Trường data của nó chứa văn bản, mà ứng dụng có thể chọn mã hóa dưới dạng JSON hoặc một biểu diễn văn bản khác. Phân tách lớp đóng khung event-stream trước, sau đó diễn giải từng payload theo schema được tài liệu hóa của endpoint.
EventSource có thể đặt header Authorization không?
Constructor EventSource gốc không cung cấp tùy chọn header tùy chỉnh tổng quát. Một endpoint yêu cầu header Authorization cần một cách tiếp cận client tương thích, chẳng hạn như một bộ tiêu thụ luồng dựa trên Fetch với bộ phân tích SSE chính xác. Giữ cho phương thức xác thực phù hợp với hợp đồng dịch vụ.
ID sự kiện có đảm bảo lịch sử sự kiện đầy đủ không?
ID sự kiện không đảm bảo lịch sử đầy đủ. Khả năng truy xuất lịch sử phụ thuộc vào hợp đồng lưu giữ và phát lại của máy chủ, và việc xử lý bền vững cũng phụ thuộc vào lưu trữ phía client. Một công cụ quan sát không nên tuyên bố ghi nhận đầy đủ chỉ vì nó nhận được một định danh sự kiện.
Khi nào một trang trình duyệt được điều khiển bởi SSE được xem là hoàn tất?
Một trang được điều khiển bằng SSE được xem là hoàn tất cho một tác vụ tự động hóa khi trạng thái đã được định nghĩa của tác vụ hoặc ranh giới quan sát được đạt tới. Bản thân luồng có thể vẫn mở. Sử dụng tín hiệu hoàn thành từ ứng dụng, một kết quả hiển thị cụ thể, hoặc một cửa sổ thu thập có giới hạn và báo cáo điều kiện nào đã kết thúc quan sát.