phát triển các ứng dụng web hướng sự kiện bằng các kỹ thuật Reverse Ajax

Giới thiệu

Phát triển ứng dụng Web đã có nhiều tiến bộ trong vài năm qua. Chúng ta đang bỏ lại đằng sau các trang web tĩnh với những đường link liên kết khiến cho ta phải liên tục refresh (làm mới) và chờ cho trang web được hiển thị lại. Thay vào đó, nhu cầu hiện nay chính là những trang web động với tốc độ đáp ứng thời gian thực càng nhanh càng tốt.

Bài viết dưới đây sẽ tìm hiểu về Reverse Ajax, polling, streaming, Cometlong polling., cách thực hiện các kỹ thuậttruyền thông Reverse Ajax khác nhau và khám phá những ưu nhược điểm của từng phương pháp này.

Trước hết ta cần biết web traffic của các loại giao thức cơ bản và so sánh sự khác nhau giữa chúng

Regular http, Ajax và WebSockets

Regular http:

  1. A client requests a webpage from a server.
  2. The server calculates the response
  3. The server sends the response to the client.

Image

AJAX Polling:

  1. A client requests a webpage from a server using regular http (see http above).
  2. The requested webpage executes javascript which requests a file from the server at regular intervals (e.g. 0.5 seconds).
  3. The server calculates each response and sends it back, just like normal http traffic.

Image

Ajax (Asynchronous JavaScript và XML), một kỹ thuật dành cho trình duyệt dựa trên JavaScript, cho phép sử dụng một đoạn mã lệnh để đáp ứng các yêu cầu HTTP cho từng thành phần mà không cần phải refresh lại toàn bộ trang web. Ajax đã được ứng dụng hơn 10 năm nay. Mặc dù tên của nó có kèm theo XML, nhưng bạn có thể truyền tải bất cứ thứ gì trong một yêu cầu Ajax. Dữ liệu được sử dụng phổ biến nhất là JSON, nó có cú pháp gần với cú pháp của JavaScript và tiêu thụ ít băng thông hơn.

AJAX Long-Polling:

  1. A client requests a webpage from a server using regular http (see http above).
  2. The requested webpage executes javascript which requests a file from the server.
  3. The server does not immediately respond with the requested information but waits until there's new information available.
  4. When there's new information available, the server responds with the new information.
  5. The client receives the new information and immediately sends another request to the server, re-starting the process.

Image

HTML5 Server Sent Events (SSE) / EventSource

  1. A client requests a webpage from a server using regular http (see http above).
  2. The requested webpage executes javascript which opens a connection to the server.
  3. The server sends an event to the client when there's new information available.
  • Real-time traffic from server to client, mostly that's what you'll need
  • You'll want to use a server that has an event loop
  • Not possible to connect with a server from another domain

Image

HTML5 Websockets

  1. A client requests a webpage from a server using regular http (see http above).
  2. The requested webpage executes javascript which opens a connection with the server.
  3. The server and the client can now send each other messages when new data (on either side) is available.
  • Real-time traffic from the server to the client and from the client to the server
  • You'll want to use a server that has an event loop
  • With WebSockets it is possible to connect with a server from another domain.

Image

WebSockets, có kèm theo HTML5, là một kỹ thuật mới. Nhiều trình duyệt đã hỗ trợ nó (Firefox, Google Chrome, Safari và những trình duyệt khác). WebSockets tạo nên các kênh truyền thông song song, hai chiều. Kết nối này được mở ra thông qua một yêu cầu HTTP được gọi là WebSockets handshake với một số header đặc biệt. Kết nối này được duy trì và bạn có thể viết và nhận dữ liệu bằng JavaScript, như thể bạn đang sử dụng một TCP socket nguyên bản.

Các kỹ thuật Reverse Ajax

Mục tiêu của kỹ thuật Reverse Ajax là giúp server đẩy thông tin đến client. Theo mặc định các yêu cầu Ajax là không chính thống và chỉ có thể được bắt đầu từ client đến server. Bạn có thể vượt qua hạn chế này bằng cách sử dụng các kỹ thuật để mô phỏng truyền thông đáp ứng giữa server và client

HTTP polling và JSONP polling

Polling bao gồm việc gửi một thông điệp từ phía máy khách đến máy chủ để yêu cầu một thông tin dữ liệu nào đó. Thực ra đây chỉ là một yêu cầu HTTP của Ajax. Để có được các sự kiện từ máy chủ càng sớm thì khoảng thời gian polling (thời gian giữa các yêu cầu) phải càng ngắn càng tốt. Có một nhược điểm là: nếu khoảng thời gian này càng ngắn, trình duyệt của máy khách sẽ đưa ra nhiều yêu cầu hơn, trong đó có những yêu cầu sẽ không trả về bất kỳ dữ liệu có ích nào khiến cho băng thông bị hao tốn và xử lý tài nguyên vô ích.

Bảng thời gian cho thấy cách mà máy khách gửi các yêu cầu polling nhưng chẳng có thông tin nào được trả về cả. Máy khách phải chờ đến lần polling tiếp theo để có được hai sự kiện do máy chủ thu nhận được.

Image

Về bản chất, polling của JSONP giống như polling của HTTP. Tuy nhiên, có sự khác biệt ở chỗ với JSONP bạn có thể đưa ra yêu cầu giữa các domain (các yêu cầu không có trong domain của bạn).Thường thì có thể nhận ra một yêu cầu JSONP bằng cách xem tham số gọi lại và nội dung trả về của nó, đó chính là mã JavaScript có thể chạy được.Để thực hiện polling trong JavaScript, bạn có thể sử dụng hàm setInterval để định thời gian gửi các yêu cầu Ajax.

Polling trong JavaScript có các ưu và nhược điểm.

  • Ưu điểm: Nó thực sự dễ thực hiện và không đòi hỏi bất kỳ tính năng đặc biệt nào ở phía máy chủ. Nó cũng làm việc trong tất cả các trình duyệt.

  • Nhược điểm: Phương pháp này hiếm khi được sử dụng vì nó không hề linh động. Hãy tưởng tượng, giả sử có 100 máy khách, trong đó mỗi máy gửi các yêu cầu polling trong 2 giây thì số lượng băng thông và tài nguyên bị hao tốn như thế nào, ở đây 30% yêu cầu được trả về không hề có chút dữ liệu. Piggyback

Piggyback polling là một phương pháp thông minh hơn nhiều so với polling đơn thuần vì nó có xu hướng loại bỏ tất cả các yêu cầu không cần thiết (các yêu cầu không trả về dữ liệu nào). Không cần định sẵn một khoảng thời gian interval nào cả; yêu cầu sẽ được gửi đi khi client cần gửi một yêu cầu đến server. Sự khác biệt nằm ở cách phản hồi được chia thành hai phần: phản hồi với dữ liệu được yêu cầu và các sự kiện từ server

Image

Khi thực hiện kỹ thuật Piggyback, thông thường tất cả các yêu cầu Ajax gửi đến máy chủ có thể được trả về một phản hồi hỗn hợp. Ví dụ về Piggyback

Image

Kết quả trả về

Image

Có thể thấy kết quả của việc kiểm tra hợp lệ một khuôn mẫu (form validation) và các sự kiện được thêm vào phản hồi. Một lần nữa, phương pháp này có những ưu và nhược điểm.

  • Ưu điểm: Không có các yêu cầu nào trả về mà không có dữ liệu, vì client kiểm soát khi nó gửi các yêu cầu, nên bạn tiêu thụ ít tài nguyên hơn. Nó cũng làm việc trong tất cả các trình duyệt và không yêu cầu các tính năng đặc biệt ở phía serverserver.
  • Nhược điểm: Bạn sẽ không biết khi nào mà các sự kiện ở phía server được gửi tới client vì nó đòi hỏi phải có một hành động từ phía client để yêu cầu chúng. Comet

Reverse Ajax với kỹ thuật polling hay piggyback cũng còn rất hạn chế: vì nó không co giãn và không cung cấp khả năng giao tiếp với độ trễ thấp (tức là các sự kiện phải được gửi đến trình duyệt ngay khi chúng đến server). Comet là một mô hình ứng dụng web, ở đây một yêu cầu được gửi đến server và vẫn tiếp tục trong một thời gian dài cho đến khi hết giờ hoặc xuất hiện một sự kiện từ server. Khi yêu cầu này được hoàn thành thì sẽ có một yêu cầu Ajax khác được gửi đi để chờ các sự kiện khác từ server. Với Comet, các serve có thể gửi dữ liệu cho client mà cần phải có một yêu cầu cụ thể nào.

Ưu điểm lớn của Comet ở chỗ mỗi máy khách luôn có một liên kết giao tiếp đến máy chủ. Máy chủ có thể đẩy các sự kiện vào các máy khách bằng cách thực hiện commit (hay hoàn thành) ngay lập tức các phản hồi ngay khi chúng đến hoặc thậm chí nó có thể tích lũy và gửi một lần. Vì một yêu cầu được mở trong một thời gian dài, nên cần có các tính năng đặc biệt ở phía máy chủ để xử lý tất cả những long-lived này (long-lived requets - các yêu cầu có thời gian sống lâu)

Image

Các cách thực hiện của Comet có thể được chia thành hai loại: một loại sử dụng chế độ streaming và một loại khác sử dụng long polling

Comet sử dụng kỹ thuật HTTP Streaming

Trong chế độ streaming, một kết nối được mở liên tục. Sẽ chỉ có một yêu cầu long-lived do mỗi sự kiện đến phía server được gửi đi thông qua cùng một kết nối. Do đó, nó đòi hỏi ở phía client phải có cơ chế phân chia các phản hồi đến từ cùng một nguồn kết nối đó. Về mặt kỹ thuật, hai kỹ thuật phổ biến về streaming là Forever Iframes (Các IFrame ẩn) và tính năng đa-phần (multi-part) của đối tượng XMLHttpRequest được sử dụng để tạo ra các yêu cầu Ajax trong JavaScript.

Forever Iframes

Kỹ thuật Forever Iframes sử dụng một thẻ Iframe ẩn đặt trong trang với thuộc tính src trỏ đến đường dẫn servlet nhằm trả về các sự kiện máy chủ. Mỗi khi nhận được một sự kiện, servlet sẽ viết và đổ vào một thẻ script với mã JavaScript bên trong. Nội dung của iframe sẽ được thêm vào thẻ script này và được thực thi.

  • Ưu điểm: Dễ thực hiện và nó hoạt động trong tất cả các trình duyệt hỗ trợ các iframe.
  • Nhược điểm: Không có cách nào để thực hiện xử lý lỗi hoặc theo dõi trạng thái của kết nối, bởi vì tất cả các kết nối và dữ liệu đều được trình duyệt xử lý thông qua các thẻ HTML. Do đó bạn không biết khi nào thì kết nối bị ngắt ở cả hai phía

Tính năng multi-part của XMLHttpRequest

Kỹ thuật thứ hai đáng tin cậy hơn là sử dụng cờ multi-part được hỗ trợ bởi một số trình duyệt (như Firefox) trên đối tượng XMLHttpRequest. Một yêu cầu Ajax được gửi và được mở ở phía máy chủ. Mỗi lần một sự kiện đến, một phản hồi multi-part được viết thông qua cùng một kết nối.

Image

Về phía máy chủ, mọi thứ phức tạp hơn một chút. Trước tiên,phải thiết lập yêu cầu multi-part, rồi treo (suspend) kết nối.

Image

mỗi khi một sự kiện xảy ra, bạn có thể lặp qua tất cả các kết nối đang bị treo và viết dữ liệu tới chúng

Image

kỹ thuật này cũng có những ưu và nhược điểm sau.

  • Ưu điểm: Chỉ có một kết nối liên tục được mở. Đây là kỹ thuật Comet, tiết kiệm việc sử dụng băng thông nhất.

  • Nhược điểm: Không phải tất cả các trình duyệt đều hỗ trợ cờ multi-part. Một số thư viện được sử dụng rộng rãi, chẳng hạn như CometD trong Java, đã cho thấy nhiều vấn đề về bộ nhớ đệm (buffer). Ví dụ, các khối dữ liệu (multi-part) có thể được lưu giữ trong một buffer và chỉ được gửi đi chỉ khi kết nối hoàn thành hoặc khi buffer đầy, điều này có thể tạo ra độ trễ cao hơn dự kiến.

Comet sử dụng kỹ thuật HTTP long-polling

Chế độ long-polling liên quan đến các kỹ thuật để mở một kết nối. Kết nối được mở bởi server và ngay khi sự kiện xảy ra thì phản hồi được commit và kết nối được đóng lại. Sau đó, một kết nối long-polling mới lại ngay lập tức được client mở để đón các sự kiện gửi đến.

Có thể thực hiện HTTP long-polling bằng cách sử dụng các thẻ script hoặc đơn giản chỉ thông qua một đối tượng XMLHttpRequest.

Các thẻ script

Với các iframe, mục tiêu là nối thêm một thẻ script vào trang của bạn để chạy kịch bản lệnh này. Máy chủ sẽ: treo kết nối cho đến khi một sự kiện xảy ra, gửi nội dung kịch bản lệnh lại cho trình duyệt và sau đó mở lại một thẻ script để nhận những sự kiện tiếp theo.

  • Ưu điểm: Vì dựa trên các thẻ HTML, nên kỹ thuật này rất dễ thực hiện và làm việc trên các domain (theo mặc định, XMLHttpRequest không cho phép thực hiện yêu cầu trên domain hoặc các domain con khác).
  • Nhược điểm: Tương tự như kỹ thuật iframe, thiếu xử lý lỗi và không thể biết trạng thái hay khả năng để ngắt một kết nối.

Long-polling của XMLHttpRequest

Phương pháp Comet thứ hai được khuyên dùng là mở một yêu cầu Ajax đến server và chờ phản hồi. Đòi hỏi server phải có tính năng đặc thù cho phép treo các yêu cầu. Ngay khi sự kiện xảy ra, server sẽ gửi lại phản hồi theo yêu cầu bị treo và đóng nó lại, giống như khi đóng luồng dữ liệu kết quả của một phản hồi servlet. Sau đó client sẽ sử dụng phản hồi đó và mở một yêu cầu Ajax long-lived mới đến server

Image

Ở tầng sau, mã này cũng sử dụng API Servlet 3 để treo yêu cầu, cũng như HTTP streaming, nhưng không cần tất cả mã xử lý multi-part

Image

Khi nhận một sự kiện, chỉ cần thực hiện tất cả các yêu cầu bị treo và hoàn thành chúng

Image

  • Ưu điểm: Dễ thực hiện bên phía client với một hệ thống xử lý lỗi và quản lý thời gian chờ tốt. Kỹ thuật này cũng cho phép khứ hồi giữa các kết nối ở phía server, do kết nối không liên tục (đây là một tin mừng khi bạn có rất nhiều client trên ứng dụng của mình). Nó cũng làm việc trên tất cả các trình duyệt; bạn chỉ cần sử dụng đối tượng XMLHttpRequest bằng cách gửi một yêu cầu Ajax đơn giản.
  • Nhược điểm: Không có nhược điểm đáng kể nào so với các kỹ thuật khác. Tuy nhiên, giống như tất cả các kỹ thuật mà chúng ta đã thảo luận, vẫn có một nhược điểm là dựa vào một kết nối HTTP không trạng thái, mà nó yêu cầu các tính năng đặc biệt bên phía server để có thể treo nó tạm thời.

Khuyến cáo

Vì tất cả các trình duyệt hiện đại đều hỗ trợ đặc tả CORS (Cross-Origin Resource Sharing - Chia sẻ giữa các nguồn tài nguyên gốc), cho phép XHR thực hiện yêu cầu qua các domain, nên nhu cầu về các kỹ thuật dựa trên kịch bản lệnh và dựa trên khung nội tuyến không được ủng hộ.

Cách tốt nhất để thực hiện và sử dụng Comet với Reverse Ajax là thông qua đối tượng XMLHttpRequest, cung cấp một xử lý kết nối thực và xử lý lỗi. Nếu cho rằng không phải tất cả các trình duyệt đều hỗ trợ cờ multi-part và multi-part streaming có thể là một vấn đề về buffer thì điều quan trọng là bạn sử dụng Comet thông qua kỹ thuật HTTP long-polling với đối tượng XMLHttpRequest (một yêu cầu Ajax đơn giản bị treo bên phía máy chủ). Tất cả các trình duyệt hỗ trợ Ajax cũng sẽ hỗ trợ phương pháp này.

Kết luận

Bài viết đã giới thiệu về các kỹ thuật Reverse Ajax. Đã chỉ ra các cách khác nhau để thực hiện giao tiếp Reverse Ajax và cũng giải thích những ưu và nhược điểm của mỗi cách. Tùy vào tình huống cụ thể và các yêu cầu trong ứng dụng của bạn sẽ dẫn đến việc lựa chọn phương pháp nào là tốt nhất. Dù vậy, phương pháp Comet với kỹ thuật Ajax long-polling là cách hay có thể lựa chọn nếu như bạn muốn các tính năng: giao tiếp với độ trễ thấp; phát hiện lỗi và thời gian chờ; tính đơn giản; và hỗ trợ tốt từ tất cả các trình duyệt và nền tảng

Tài liệu tham khảo

http://www.ibm.com

http://stackoverflow.com


All Rights Reserved