Reverse Ajax, Phần 4: Atmosphere và CometD

Loạt bài này cho bạn thấy cách phát triển các ứng dụng web theo hướng sự kiện bằng cách sử dụng các kỹ thuật Reverse Ajax. Phần 1 đã giới thiệu Reverse Ajax, polling, streaming, Comet và long-polling. Phần 2 đã giải thích cách thực hiện Reverse Ajax bằng cách sử dụng WebSockets và đã thảo luận về những hạn chế của các máy chủ web khi sử dụng Comet và WebSockets. Phần 3 đã cho thấy rằng việc triển khai thực hiện hệ thống truyền thông WebSockets hoặc Comet riêng của bạn có thể khó khăn nếu bạn cần hỗ trợ một số máy chủ hoặc cung cấp một ứng dụng web độc lập cho người dùng để triển khai trên máy chủ của riêng họ. Thậm chí nếu mã JavaScript trên máy khách đơn giản, thì bạn vẫn cần một số cách xử lý trường hợp ngoại lệ, các tính năng kết nối lại và tin báo. Về phía máy chủ, việc thiếu một API chung (global API) và nhiều API máy chủ web dẫn đến nhu cầu cần có các framework để mang lại một sự trừu tượng hóa. Phần 3 cũng đã thảo luận Socket.IO.

pdf10 trang | Chia sẻ: lylyngoc | Lượt xem: 1632 | Lượt tải: 1download
Bạn đang xem nội dung tài liệu Reverse Ajax, Phần 4: Atmosphere và CometD, để tải tài liệu về máy bạn click vào nút DOWNLOAD ở trên
Reverse Ajax, Phần 4: Atmosphere và CometD Giới thiệu Loạt bài này cho bạn thấy cách phát triển các ứng dụng web theo hướng sự kiện bằng cách sử dụng các kỹ thuật Reverse Ajax. Phần 1 đã giới thiệu Reverse Ajax, polling, streaming, Comet và long-polling. Phần 2 đã giải thích cách thực hiện Reverse Ajax bằng cách sử dụng WebSockets và đã thảo luận về những hạn chế của các máy chủ web khi sử dụng Comet và WebSockets. Phần 3 đã cho thấy rằng việc triển khai thực hiện hệ thống truyền thông WebSockets hoặc Comet riêng của bạn có thể khó khăn nếu bạn cần hỗ trợ một số máy chủ hoặc cung cấp một ứng dụng web độc lập cho người dùng để triển khai trên máy chủ của riêng họ. Thậm chí nếu mã JavaScript trên máy khách đơn giản, thì bạn vẫn cần một số cách xử lý trường hợp ngoại lệ, các tính năng kết nối lại và tin báo. Về phía máy chủ, việc thiếu một API chung (global API) và nhiều API máy chủ web dẫn đến nhu cầu cần có các framework để mang lại một sự trừu tượng hóa. Phần 3 cũng đã thảo luận Socket.IO. Trong bài này, hãy tìm hiểu về Atmosphere và CometD. Chúng là các thư viện Reverse Ajax nổi tiếng cho các máy chủ Java. Bạn có thể tải về mã nguồn được sử dụng trong bài này. Điều kiện tiên quyết Để nắm vững kiến thức trong bài này, tốt nhất bạn nên biết trước JavaScript và Java. Để chạy ví dụ mẫu trong bài này, bạn cũng cần có phiên bản Maven và JDK mới nhất (xem phần Tài nguyên). Về đầu trang Framework Atmosphere Atmosphere là một framework Java cung cấp API chung để sử dụng các tính năng Comet và WebSocket của nhiều máy chủ web, gồm có Tomcat, Jetty, GlassFish, WebLogic, Grizzly, JBossWeb, JBoss và Resin. Bất kỳ máy chủ web nào đang hỗ trợ Đặc tả Servlet 3.0 thì cũng sẽ hỗ trợ. Trong số các framework được trình bày trong loạt bài này, Atmosphere hỗ trợ nhiều máy chủ nhất. Atmosphere có thể phát hiện ra các API máy chủ nguyên gốc (cho Comet và WebSockets) và chuyển đổi ngược lại Servlet 3.0, nếu có, cho Comet. Hoặc, cũng với Comet, nó sẽ quay lại một chế độ không đồng bộ "có quản lý" (nhưng không có khả năng co giãn như Jetty Continuations). Atmosphere đã được dùng hơn hai năm và vẫn tiếp tục được phát triển. Nó được sử dụng trong các ứng dụng web lớn như JIRA, một trong những trình dò tìm vấn đề (issue tracker) nổi tiếng nhất. Hình 1 cho thấy kiến trúc của Atmosphere. Hình 1. Kiến trúc của Atmosphere Framework Atmosphere bao gồm Atmosphere runtime, cung cấp một API chung cho tất cả các giải pháp và tiêu chuẩn máy chủ web khác nhau. Trên hết, máy khách có thể truy cập vào các tính năng API và Reverse Ajax thông qua Google Web Toolkit (GWT – Bộ công cụ Web của Google) bằng cách thiết lập chỉ một servlet. Hoặc, bạn cũng có thể sử dụng Jersey, một framework thực hiện JSR-311 (đặc tả JAX-RS). Vì thế, Atmosphere có thể được sử dụng trong các dịch vụ tiện lợi có cung cấp các chú thích bổ sung. Sau khi cấu hình mô đun mà bạn chọn, bạn có thể truy cập Atmosphere runtime bằng cách thực thi một số lớp (được thảo luận sau trong bài này). Bạn cũng có thể tùy chọn sử dụng một số plugin được cung cấp để tăng thêm hỗ trợ cho việc phân cụm (clustering), tạo thông báo, tích hợp phụ thuộc và nhiều hơn nữa. Nếu bạn đang sử dụng một web framework (Wicket, Struts, Spring MVC), bạn có thể thêm vào sự hỗ trợ Reverse Ajax bằng cách sử dụng MeteorServlet của Atmosphere. Servlet này trưng ra một đối tượng Meteor, có thể được lấy ra trong các trình điều khiển và các dịch vụ của bạn để treo (suspend) hoặc tiếp tục (resume) lại các yêu cầu. Sức mạnh của Atmosphere vẫn còn ở phía máy chủ: nó cung cấp một API chuẩn hóa bao gồm tất cả các giải pháp khác nhau và các cách để truyền thông với WebSockets hoặc Comet. Atmosphere không sử dụng một giao thức giữa máy khách và máy chủ, như Socket.IO và CometD. Cả hai thư viện đó đều cung cấp một JavaScript phía máy khách và một servlet phía máy chủ sử dụng cách giao tiếp thông qua giao thức đặc trưng (handshaking, tạo thông báo, tin báo và nhịp hoạt động). Mục tiêu của Atmosphere là cung cấp một kênh truyền dẫn chung bên phía máy chủ. Nếu bạn cần phải sử dụng một giao thức đặc trưng, chẳng hạn như Bayeux (một giao thức được CometD sử dụng), bạn phải phát triển "trình xử lý" riêng của mình theo Atmosphere. Plugin CometD chỉ làm một việc là tận dụng API của Atmosphere để suspend và resume lại các yêu cầu và nó ủy quyền cho các lớp CometD để quản lý truyền thông CometD khi sử dụng giao thức Bayeux. Atmosphere đi kèm với một thư viện máy khách jQuery để giúp cho việc thiết lập kết nối dễ dàng, nó có thể tự động phát hiện ra kiểu truyền tải tốt nhất hiện có (WebSockets hoặc CometD). Việc sử dụng plugin jQuery của Atmosphere cũng tương tự như API WebSockets của HTML5. Đầu tiên, bạn kết nối đến máy chủ, đăng ký một cuộc phản hồi để nhận các thông báo và sau đó bạn có thể đẩy ra dữ liệu nào đó. Mã nguồn kèm theo bài này có chứa một ví dụ mẫu Atmosphere trực tiếp sử dụng một trình xử lý với servlet của Atmosphere. Mã máy khách luôn giống nhau; đó là mã tương tự như mã được sử dụng trong các Phần 1, 2 và 3 của loạt bài này (trong các ví dụ mẫu chat khi sử dụng Comet long-polling). Có thể bạn đang sử dụng plugin jQuery của Atmosphere, nhưng chưa cần thiết vì Atmosphere không thi hành bất kỳ giao thức truyền thông nào. Ngoài ra bạn có thể xem xét các ví dụ khác trong dự án của Atmosphere, nhất là những ví dụ sử dụng các chú thích JSR-311 (Jersey). Chúng thực sự đơn giản hóa việc viết các trình xử lý. Liệt kê 1 cho thấy giao diện của trình xử lý Atmosphere. Liệt kê 1. Giao diện AtmosphereHandler public interface AtmosphereHandler { void onRequest(AtmosphereResource resource) throws IOException; void onStateChange(AtmosphereResourceEvent event) throws IOException; void destroy(); } Phương thức onRequest nhận tất cả các yêu cầu từ máy khách và quyết định xem có suspend hoặc resume lại chúng (hoặc không làm gì) hay không. Mỗi lần suspend hoặc resume lại yêu cầu, một thông báo được phát đi hoặc diễn ra một thời gian chờ timeout, một sự kiện được gửi và nhận bằng phương thức onStateChange. Cách thực hiện phương thức onRequest để chat trong Comet được hiển thị như Liệt kê 2. Liệt kê 2. Giao diện AtmosphereHandler - onRequest Broadcaster broadcaster = BroadcasterFactory.getDefault().lookup( DefaultBroadcaster.class, ChatHandler.class.getName(), true); broadcaster.setScope(Broadcaster.SCOPE.APPLICATION); resource.setBroadcaster(broadcaster); HttpServletRequest req = resource.getRequest(); String user = (String) req.getSession().getAttribute("user"); if (user != null) { if ("GET".equals(req.getMethod())) { resource.suspend(-1, false); } else if ("POST".equals(req.getMethod())) { String cmd = req.getParameter("cmd"); String message = req.getParameter("message"); if ("disconnect".equals(cmd)) { close(resource); } else if (message != null && message.trim().length() > 0) { broadcaster.broadcast("[" + user + "] " + message); } } } Một quy ước điển hình là treo các yêu cầu GET và gửi các thông báo bằng phương thức POST. Khi nhận được một thông báo, nó sẽ được chuyến tiếp (broadcast) đến tất cả các nơi đã được đăng ký trong trình phát quảng bá (broadcaster). Lưu ý rằng ví dụ này không bao giờ gửi bất cứ điều gì tới luồng dữ liệu kết quả HttpServlet. Hành động broadcast và suspend chỉ là gửi các sự kiện đã nhận được khi thực thi các phương thức khác, như thể hiện trong Liệt kê 3: Liệt kê 3. Giao diện AtmosphereHandler - onStateChange Broadcaster broadcaster = BroadcasterFactory.getDefault().lookup( DefaultBroadcaster.class, ChatHandler.class.getName(), true); // Client closed the connection. if (event.isCancelled()) { close(event.getResource()); return; } try { String message = (String) event.getMessage(); if (message != null) { PrintWriter writer = event.getResource().getResponse().getWriter(); writer.write(message); writer.flush(); } } finally { if (!event.isResumedOnTimeout()) { event.getResource().resume(); } } Bây giờ bạn đã có những gì cần thiết để Comet chat hoạt động. Tóm lại, các khái niệm Atmosphere trọng tâm là: đối tượng tài nguyên đại diện cho kết nối và một broadcaster chịu trách nhiệm khởi động các sự kiện đến các tài nguyên và quyết định khi nào suspend hoặc resume lại một yêu cầu. Lưu ý rằng ví dụ này chỉ dùng cho Comet. Để có thể sử dụng WebSockets và Comet, nên sử dụng một thư viện phía máy khách và sẽ cần một trình xử lý phức tạp hơn. Bảng 1 mô tả những lợi ích và hạn chế khi sử dụng framework Atmosphere. Bảng 1. Những lợi ích và hạn chế của khung công tác Atmosphere Lợi ích Hạn chế Nếu bạn phải triển khai một ứng dụng web trong một số máy chủ web mà bạn không thể kiểm soát được. Bạn sẽ có cơ hội tốt là các tính năng Reverse Ajax trong ứng dụng của bạn sẽ hoạt động đúng do số máy chủ web được Atmosphere hỗ trợ. Khi bạn cần một API phổ biến trên một giao tiếp Reverse Ajax, mà không cần định nghĩa bất kỳ giao thức nào, vì có thể bạn muốn phát triển hay mở rộng nó. Thiếu tài liệu hướng dẫn về kiến trúc, dự án, các khái niệm và các API của Atmosphere, những thứ này sẽ rất có ích nếu bạn muốn xem mã nguồn hoặc phân tích một số ví dụ mẫu được cung cấp. API này có kỹ thuật cao và đôi khi mơ hồ, so với các API đơn giản của các framework khác, chẳng hạn như Socket.IO và CometD. Ngay cả khi có sử dụng các chú thích trong Atmosphere, thì một số tên và các thuộc tính của nó vẫn quá mang tính kỹ thuật. Mặc dù có khả năng trừu tượng hóa tốt ở phía máy chủ, nhưng không có một thư viện tốt nào ở phía máy khách. Không có giao thức nào cả, do đó, tất cả các tính năng bổ sung đều được dành cho các nhà phát triển. Nếu bạn yêu cầu một ứng dụng web lớn, có khả năng co giãn và phát hiện timeout, tin báo, back-off, liên miền, v.v... nhất là khi làm việc với các thiết bị di động thì thư viện này là quá đơn giản. Trong trường hợp này, CometD cho độ tin cậy hơn rất nhiều; nó sử dụng một giao thức truyền thông để kích hoạt một số luồng điều khiển và phát hiện lỗi, tất cả đều được cung cấp trong CometD. Việc sử dụng máy khách JavaScript của CometD với plugin CometD của Atmosphere có thể là một lựa chọn thay thế tốt nếu bạn cần các tính năng bổ sung. Về đầu trang Framework CometD Framework CometD, một giải pháp truyền thông theo sự kiện dựa trên HTTP, đã được dùng trong nhiều năm. Phiên bản 2 đã thêm sự hỗ trợ cho việc cấu hình chú thích và WebSockets. Framework CometD cung cấp một phần máy chủ Java và một phần máy khách Java, cộng với các thư viện máy khách JavaScript dựa trên jQuery và Dojo. CometD sử dụng một giao thức truyền thông chuẩn hóa được gọi là Bayeux, cho phép bạn kích hoạt một số phần mở rộng cho tin báo, kiểm soát luồng, đồng bộ hóa, phân cụm và v.v. Cách tiếp cận theo sự kiện của CometD hoàn toàn phù hợp với các khái niệm mới về phát triển web theo sự kiện. Như với các giao diện người dùng máy tính để bàn truyền thống, tất cả các thành phần đều truyền thông qua một bus để gửi các khai báo và nhận các sự kiện. Do đó tất cả cách truyền thông đều là không đồng bộ. Framework CometD:  Có đủ tài liệu cần thiết.  Cung cấp các ví dụ mẫu và các nguyên mẫu Maven giúp dễ dàng khởi động một dự án.  API được thiết kế tốt cho phép phát triển mở rộng.  Cung cấp một mô đun phân cụm (clustering), được gọi là Oort, cung cấp cho bạn khả năng chạy nhiều máy chủ web CometD như các nút trong một cụm phía sau một trình cân bằng tải để điều chỉnh co giãn theo một số lượng lớn các kết nối HTTP.  Hỗ trợ các chính sách bảo mật để cho phép thiết lập xem ai có quyền gửi thông báo qua kênh nào.  Tích hợp khá tốt với Spring và Google Guice (các dependency injection framework). Giao thức Bayeux Giao thức truyền thông Bayeux chủ yếu thông qua HTTP. Nó cung cấp không đồng bộ một cách truyền thông đáp ứng hai chiều giữa máy khách và máy chủ. Giao thức Bayeux dựa trên các kênh mà ở đó các thông báo được định tuyến và phân phối từ máy khách đến máy chủ, máy chủ đến máy khách hoặc máy khách đến máy khách (nhưng thông qua máy chủ). Bayeux là một kiểu giao thức đăng ký-xuất bản. CometD thực hiện giao thức Bayeux và do đó cung cấp một tầng trừu tượng hóa dựa trên các kiểu truyền tải Comet và WebSocket để định tuyến các yêu cầu qua Bayeux. Máy chủ và đặc tính của nó CometD được đóng gói với ba kiểu truyền tải: JSON, JSONP và WebSocket. Chúng phụ thuộc vào API Continuations và WebSocket của Jetty. Theo mặc định, có thể sử dụng CometD với Jetty 6, 7, 8, cũng như bất kỳ các máy chủ khác nào hỗ trợ Đặc tả Servlet 3.0. Có thể bổ sung và phát triển các kiểu truyền tải theo cách giống như các phần mở rộng. Bạn có thể viết các kiểu truyền tải hỗ trợ API WebSocket của Grizzly và các API khác, rồi thêm chúng vào bước cấu hình máy chủ CometD. Hình 2 cho thấy một tổng quan về các khối CometD chính. Hình 2. Kiến trúc của CometD Tầng bảo mật để truy cập các kênh thông báo không được hiển thị trong Hình 2. Mã nguồn được cung cấp cùng với bài viết này gồm có một ứng dụng web sử dụng CometD. Trình mô tả ứng dụng web có chứa định nghĩa được mô tả trong ví dụ chat ở Liệt kê 4. Liệt kê 4. web.xml cometd org.cometd.java.annotation.AnnotationCometdServlet true [...] services ChatService transports com.ovea.cometd.websocket.jetty8.Jetty8WebSocketTransport Servlet CometD hỗ trợ một số tùy chọn kiểm soát các thiết lập chung, chẳng hạn như khả năng thiết lập các kiểu truyền tải và các dịch vụ. Trong ví dụ này, giả sử bạn muốn Jetty 8 hỗ trợ WebSocket, lớp dịch vụ ChatService của CometD bên phía máy chủ sẽ kiểm soát phòng chat, nơi mọi người có thể trò chuyện, như thể hiện trong Liệt kê 5: Liệt kê 5. Lớp ChatService của CometD @Service public final class ChatService { @Inject BayeuxServer server; @PostConstruct void init() { server.addListener(new BayeuxServer.SessionListener() { @Override public void sessionAdded(ServerSession session) { [...] } @Override public void sessionRemoved(ServerSession session, boolean timedout) { [...] } }); } @Configure("/**") void any(ConfigurableServerChannel channel) { channel.addAuthorizer(GrantAuthorizer.GRANT_NONE); } @Configure("/chatroom") void configure(ConfigurableServerChannel channel) { channel.addAuthorizer(new Authorizer() { @Override public Result authorize( [..] // check that the user is in session } }); } @Listener("/chatroom") void appendUser(ServerSession remote, ServerMessage.Mutable message) { [...] } } Liệt kê 5 trình bày một số tính năng quan trọng của CometD, bao gồm:  Tích hợp phụ thuộc (Dependency injection)  Quản lý vòng đời  Cấu hình kênh chung  Quản lý bảo mật  Chuyển đổi thông báo (để thêm tên người dùng trước tất cả các thông báo)  Quản lý phiên làm việc Về phía máy khách, ví dụ này không kích hoạt bất kỳ phần mở rộng nào -- chỉ cần mã CometD thô, như trong Liệt kê 6: Liệt kê 6. Mã máy khách của CometD // First create t cometd object and configure it var cometd = new $.Cometd('CometD chat client'); cometd.configure({ url: document.location + 'cometd', logLevel: 'debug' }); cometd.websocketEnabled = 'WebSocket' in window; // Then we register some listeners. Meta channels (those with // the form /meta/ are specific reserved channels) cometd.addListener('/meta/disconnect', function(message) { [...] }); cometd.addListener('/meta/connect', function(message) { [...] }); // Then, starting a connexion can be done using: cometd.handshake(); // And subscriptions with: cometd.subscribe('/chatroom', function(event) { [...] // event.data holds the message }); // We finally send data to the chatroom like this: cometd.publish('/chatroom', msg); API phía máy khách của CometD dễ dùng và dễ hiểu, trong khi vẫn mạnh mẽ và có thể mở rộng được. Bài này chỉ trình bày các phần chính của ứng dụng web, vì vậy hãy xem ứng dụng ví dụ để có ý tưởng tốt hơn về sức mạnh của CometD. Bảng 2 vạch ra những lợi ích và hạn chế khi sử dụng khung công tác CometD. Bảng 2. Những lợi ích và hạn chế của CometD Lợi ích Hạn chế CometD đưa ra một giải pháp hoàn chỉnh, từ phía máy khách và phía máy chủ, cũng như từ một máy khách Java độc lập đến một máy chủ. Framework này có đủ tài liệu cần thiết, có một API tốt và dễ sử dụng. Trên hết, nó có cách tiếp cận theo hướng sự kiện. CometD và Bayeux là một phần của nhiều ứng dụng web theo sự kiện. Các khung công tác Reverse Ajax khác không cung cấp bất kỳ cơ chế theo sự kiện nào, buộc người dùng cuối phải phát triển giải pháp riêng của mình. CometD hỗ trợ nhiều tính năng cần thiết, chẳng hạn như kết nối lại, phát hiện thời gian chờ tin cậy, back-off, xử lý theo bó, tin báo và nhiều hơn nữa mà bạn sẽ không tìm thấy trong các framework Reverse Ajax khác. CometD cho phép bạn đạt được cách truyền thông có độ trễ thấp, tin cậy nhất có thể. CometD hiện tại không hỗ trợ bất kỳ container Servlet 2.5 nào ngoài Jetty cho Comet (Tomcat) và nó cũng không hỗ trợ WebSocket của Glassfish/Grizzly. Về đầu trang Kết luận Cả Atmosphere và CometD đều là các giải pháp Reverse Ajax nguồn mở, chắc chắn. Với Ovea, sự lựa chọn của chúng tôi là CometD vì chúng tôi phát triển các ứng dụng web theo sự kiện có khả năng co giãn với các thiết bị di động trong một môi trường có phân cụm và chúng tôi có toàn quyền kiểm soát cơ sở hạ tầng (Jetty). Tuy nhiên, do không được tiếp tục phát triển, CometD không thể là sự lựa chọn tốt nhất nếu bạn đang bán các ứng dụng web và muốn các tính năng Reverse Ajax của mình làm việc trên càng nhiều máy chủ càng tốt. Nhưng giờ đây, càng ngày càng có nhiều Web container hỗ trợ Đặc tả Servlet 3.0, nên đã giảm bớt sự hạn chế của CometD. Khi nói về tầng truyền tải, sự khác biệt chính còn lại hiện nay phụ thuộc vào sự hỗ trợ của WebSocket.
Tài liệu liên quan