Reverse Ajax, Phần 5: Phát triển web theo hướng sự kiện

Loạt bài này tìm hiểu 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 các cách khác nhau để thực hiện truyền thông Reverse Ajax. 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 đã tìm hiểu những khó khăn trong việc thực hiện hệ thống truyền thông Comet hoặc WebSockets riêng của bạn và phần này cũng đã giới thiệu Socket.IO. Phần 4 trình bày Atmosphere và CometD. Trong phần cuối cùng của loạt bài này, chúng ta sẽ tìm hiểu về phát triển theo hướng sự kiện. Hãy cùng xây dựng một ứng dụng mẫu bằng cách sử dụng mã nguồn kèm theo.

Mathieu Carbou, Kiến trúc sư Java Web, Ovea

Ảnh của Mathieu CarbouMathieu Carbou là nhà tư vấn và kiến trúc web Java ở Ovea, cung cấp các dịch vụ và các giải pháp phát triển. Ông là người đứng dầu và điều hành một số dự án nguồn mở, là người phát ngôn và lãnh đạo của Nhóm người dùng Java (Java User Group) của Montreal. Mathieu có nền tảng vững chắc về thiết kế mã và có kinh nghiệm tốt, ông còn là một chuyên gia phát triển web theo hướng sự kiện (event-driven web) từ phía máy khách đến các tầng bên dưới. Ông tập trung vào việc cung cấp các giải pháp thông tin và theo hướng sự kiện của các ứng dụng web có khả năng co giãn cao. Hãy ghé thăm blog của ông.



25 01 2013

Giới thiệu

Loạt bài này giới thiệu cho bạn 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 đã chỉ ra những khó khăn khi triển khai các hệ thống truyền thông WebSockets hoặc Comet nếu bạn muốn hỗ trợ các máy chủ hoặc cung cấp ứng dụng web độc lập cho người dùng để tự họ có thể triển khai được, phần này cũng đã thảo luận về Socket.IO. Phần 4 trình bày Atmosphere và CometD—các thư viện Reverse Ajax nguồn mở nổi tiếng nhất cho các máy chủ Java.

Như vậy, đến giờ bạn đã học được các phương pháp tạo các thành phần giao tiếp thông qua sự kiện. Trong phần cuối cùng của loạt bài này, hãy áp dụng các nguyên tắc phát triển theo hướng sự kiện và xây dựng một ứng dụng web theo ví dụ mẫu.

Bạn có thể tải về mã nguồn dành cho bài viết 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, Java và có một số kinh nghiệm phát triển web. Để chạy ví dụ mẫu trong bài này, bạn cũng cần phải có phiên bản Maven và JDK mới nhất (xem phần Tài nguyên).


Các thuật ngữ

Bạn có thể đã quen với kiến trúc hướng sự kiện (Event-Driven Architecture - EDA), các hệ thống EventBus, hệ thống thông báo, xử lý sự kiện phức tạp (CEP) và các kênh (channel). Các thuật ngữ và khái niệm này đã tồn tại trong nhiều năm nay. Có thể bạn sẽ nghe thấy chúng nhiều hơn một khi công nghệ này hoàn thiện. Phần này cung cấp các giải thích ngắn gọn về các thuật ngữ này.

Event (Sự kiện)
Một sự kiện xảy ra trong một hệ thống. Nó thường có các thông số kèm theo, chẳng hạn như thời điểm xảy ra (timestamp), nguồn hoặc địa điểm (thành phần được click vào) và một số thông tin mô tả sự kiện. Một sự kiện có thể có nhiều thông số tùy theo hệ thống.
Event-processing architecture (EDA - Kiến trúc xử lý sự kiện)
Cũng được gọi là lập trình dựa trên sự kiện, đây là một thiết kế kiến trúc, nơi ứng dụng của bạn có chứa các thành phần truyền thông và thực hiện bằng cách gửi và nhận sự kiện. Giao diện người dùng đồ họa (GUI) Swing của Java là một ví dụ về EDA. Mỗi thành phần của Swing có thể lắng nghe các sự kiện, tác động lại chúng, gửi các sự kiện khác và v.v.... EDA được tạo nên bởi những phần nhỏ: nơi xuất phát sự kiên, nơi tiếp nhận sự kiện, các sự kiện và phần mềm xử lý xự kiện.
  • Event producer (Nơi xuất phát sự kiện) - Thành phần này ban hành các sự kiện. Trong ví dụ trong bài này, một button dùng để gửi đi các biểu mẫu chính là nơi xuất phát sự kiện.
  • Event consumer (Nơi tiếp nhận sự kiện) - Là một thành phần lắng nghe các sự kiện cụ thể được gửi đi. Ví dụ, trong trường hợp gửi biểu mẫu, trình duyệt sẽ lắng nghe các lần nhấn chuột trên button để gửi dữ liệu biểu mẫu đến máy chủ.
  • Event-processing software (Phần mềm xử lý sự kiện) - Chính là lõi của hệ thống, nơi các Event producer gửi đi các sự kiện và Event consumer đăng ký để tiếp nhận sự kiện. Tùy thuộc vào phần mềm mà việc xử lý có thể đơn giản (như chỉ cần chuyển tiếp các sự kiện tới nơi tiếp nhận) hoặc phức tạp (CEP). Với CEP, phần mềm hỗ trợ một loạt các phương tiện xử lý, chẳng hạn như tổng hợp, lọc và biến đổi sự kiện.

    Esper là một ví dụ về phần mềm như vậy. Phần mềm xử lý sự kiện không chỉ đại diện cho một ứng dụng chạy độc lập, mà nó còn có thể là một thư viện được tích hợp trong ứng dụng của bạn.

Messaging systems (Các hệ thống Messaging)
Một loại ứng dụng theo hướng sự kiện, nơi mà các Event producer gửi đi các thông điệp tới các kênh và tới những Event consumer đã đăng ký với kênh đó. Event producer và Event consumer không có mối liên kết mà hoàn toàn độc lập. Đối với loại ứng dụng này, bạn thường sử dụng thuật ngữ message (thông điệp) thay cho event (sự kiện).
Channels (Các kênh)
Là một cách để phân loại sự kiện trong một hệ thống Messaging. Chúng đại diện cho điểm đến, nơi các Event producer muốn gửi sự kiện tới. Ví dụ, trong một ứng dụng phòng chat, một kênh sẽ là /chatapplication/chatrooms/asdrt678. Kênh này sẽ xác định một phòng chat cụ thể, nơi các Event producer có thể gửi thông báo tới và là nơi mà thành phần đồ họa sẽ hiển thị thông báo mới đến đó.

Một số hệ thống Messaging cung cấp hai loại kênh: queue (hàng đợi) và topic (chủ đề).

  • Các Queue (hàng đợi) - Khi một thông điệp được chuyển đến một hàng đợi thì chỉ có một Event consumer nhận được và xử lý nó. Những Event consumer khác sẽ không nhìn thấy nó. Các hàng đợi có thể được tạo ra liên tục để đảm bảo phân phối thông tin. Ví dụ ta có một yêu cầu gửi email. Một ứng dụng web sẽ gửi một thông điệp tới hàng đợi /myapp/mail/user-registration khi người dùng đăng ký. Có thể sẽ có một số ứng dụng gửi email tiếp tục được đăng ký vào hàng đợi này. Nếu không thì thông điệp sẽ không mất đi.
  • Các Topic (chủ đề) - Khi một thông điệp được chuyển đến một topic thì tất cả những người đăng ký đều nhận được được thông điệp. Một topic thường không liên tục. Ví dụ về một topic: /event/system/cpu/usage, nơi một trình sản xuất thường xuyên gửi đi các thông số sử dụng CPU. Ở phía bên kia, nếu như ai quan tâm thì họ có thể đăng ký để nhận thông tin này.
Publish/Subcribe (Xuất bản/đăng ký)
Các giải pháp theo hướng sự kiện được thực hiện mẫu xuất bản/đăng ký. Các Event producer xuất bản các sự kiện bằng phần mềm xử lý và Event consumer đăng ký để nhận chúng. Cách mà Event consumer đăng ký phụ thuộc vào phần mềm. Trong các ứng dụng gửi thông điệp, họ đăng ký theo các kênh (ví dụ, theo tùy chọn cũng áp dụng các quy tắc lọc dựa vào kiểu sự kiện). Với một CEP như Esper, việc đăng ký có thể được thực hiện thông qua một yêu cầu giống như SQL để xác định những sự kiện mà bạn đang quan tâm.

Vì sao chúng ta sử dụng các giải pháp hướng sự kiện?

Theo các cách giao tiếp truyền thống, nếu hệ thống A yêu cầu thông tin từ hệ thống B, thì yêu cầu sẽ được gửi đến B. Hệ thống B sẽ xử lý yêu cầu đó và hệ thống A sẽ chờ phản hồi. Khi xử lý xong, phản hồi sẽ được gửi trở lại hệ thống A. Trong cơ chế giao tiếp đồng bộ, việc tiêu thụ tài nguyên không hiệu quả do mất thời gian xử lý trong khi chờ phản hồi.

Trong chế độ không đồng bộ, hệ thống A sẽ đăng ký thông tin mà họ muốn từ hệ thống B. Sau đó, theo tùy chọn hệ thống A sẽ gửi một thông báo tới hệ thống B, rồi ngay lập tức quay trở lại và hệ thống A có thể xử lý những việc khác. Bước này là tùy chọn. Thông thường, trong các ứng dụng hướng sự kiện, bạn không phải yêu cầu hệ thống khác gửi các sự kiện bởi vì bạn không biết chúng đang có những gì. Khi hệ thống B gửi phản hồi, hệ thống A ngay lập tức nhận được nó.

Một lợi thế của kiến trúc hướng sự kiện là ở chỗ nó cho phép khả năng co giãn tốt hơn. Khả năng co giãn là khả năng mà hệ thống có thể thích ứng với một sự thay đổi theo yêu cầu, khối lượng hoặc cường độ trong khi vẫn đáp ứng được các mục tiêu của nó. Bằng cách loại bỏ các lần tạm dừng, các kiến trúc hướng sự kiện thường hoạt động tốt hơn và có tốc độ xử lý cao hơn.

Một lợi thế khác nằm trong việc phát triển và bảo trì ứng dụng. Với các giải pháp hướng sự kiện, mỗi thành phần trong ứng dụng của bạn có thể hoàn toàn được cô lập riêng biệt.

Các giải pháp hướng sự kiện cho phép thời gian đáp ứng tốt nhất do có độ trễ truyền thông thấp hơn.


Áp dụng các giải pháp hướng sự kiện cho web

Các web framework được sử dụng dựa trên mẫu yêu cầu-đáp ứng truyền thống là nguyên nhân của việc refresh trang web liên tục. Với sự xuất hiện của Ajax, Reverse Ajax và các framework mạnh mẽ khác như CometD và Atmosphere, giờ đây chúng ta dễ dàng áp dụng các khái niệm về kiến trúc hướng sự kiện cho trang web để có được những lợi ích trong việc tách rời các thành phần, khả năng co giãn và khả năng đáp ứng.

Về phía máy khách

Kiến trúc hướng sự kiện có thể được áp dụng bên phía máy khách để phát triển GUI. Thay vì tạo ra một trang web truyền thống, bạn có thể có một trang web riêng đóng vai trò như một container. Mỗi thành phần (từng phần trong trang) có thể được cách ly. Bạn có thể có một GUI Swing của Java trên trang web, giống như một trang Google có chứa các tiện ích nhỏ (xem phần Tài nguyên để biết thêm chi tiết).

Bạn sẽ cần một event bus (bus sự kiện). Ví dụ, bạn có thể phát triển event bus JavaScript, để cho phép mỗi thành phần của trang đăng ký và xuất bản các kênh. Các sự kiện này cũng có thể được đồng bộ hóa để kích hoạt các hành động sau khi nhận được hai hoặc nhiều sự kiện hơn. Có thể sử dụng event bus cho các sự kiện cục bộ trong một trang, nhưng bạn cũng có thể thêm vào các plugin để hỗ trợ các sự kiện từ xa bằng cách sử dụng CometD hoặc Socket.IO.

Về phía máy chủ

Ở phía máy chủ, bạn sẽ cần thiết lập một framework Reverse Ajax hỗ trợ kiến trúc hướng sự kiện. Trong số những framework đã xem xét trong các phần trước của loạt bài này, chỉ có CometD có cách tiếp cận theo hướng sự kiện. Đối với các framework khác, bạn sẽ cần phải thêm các tùy chỉnh hỗ trợ, điều này rất quan trọng. Bạn cũng có thể thêm vào một hệ thống thông báo của bên thứ ba như JMS (ví dụ, ActiveMQ của Apache) hoặc một CEP như Esper. Một giải pháp đơn giản hơn là Redis, hỗ trợ các công việc xuất bản/đăng ký cơ bản.

Loạt bài này nói về web theo hướng sự kiện và Reverse Ajax, vì vậy chúng tôi sẽ tập trung vào phần máy khách và sẽ không thiết lập một hệ thống thông báo phức tạp.


Ví dụ web theo hướng sự kiện

Ví dụ mà bạn sẽ tạo ra cùng với bài này là một ứng dụng phòng chat trên nền web, có một khung cửa sổ người dùng chứa danh sách những người bạn đã kết nối. Tên bạn bè của bạn sẽ được in đậm, những người đang hoạt động (sau 20 giây) sẽ có màu xanh lá cây còn những người không hoạt động sẽ có màu cam. Nếu một người dùng kết nối hoặc ngắt kết nối, danh sách sẽ được làm mới.

Đối với các mục đích bảo mật, người ta cấu hình một thời gian chờ hai phút của phiên làm việc trong tệp web.xml. Nếu sau hai phút không hoạt động, sẽ có một cửa sổ thông báo xuất hiện và bạn sẽ được chuyển hướng đến trang đăng nhập.

Bạn được chuyển hướng lại đến trang đăng nhập ngay khi bạn không có thêm phiên làm việc nào hoặc nếu bạn vẫn chưa được kết nối. Trang đăng nhập yêu cầu thông tin của bạn và kiểm tra xem liệu bạn đã sẵn sàng đăng nhập vào phòng chat chưa.

Sau khi đăng nhập, bạn có thể gửi một tin nhắn trong phòng chat cho tất cả bạn bè. Một giao diện điều khiển cũng có mặt và ghi lại tất cả các sự kiện nhận được.

Ứng dụng web được dựa trên sự kiện. Với thông tin trên, bạn có thể dễ dàng định nghĩa một số sự kiện:

  • Một người dùng được kết nối.
  • Một người dùng được ngắt kết nối.
  • Phiên làm việc đã kết thúc.
  • Một tin nhắn nhận được.
  • Một bộ lọc bảo mật để chặn các yêu cầu nếu bạn chưa đăng nhập.
  • Một người dùng chuyển sang trạng thái không hoạt động.
  • Một người dùng chuyển sang trạng thái hoạt động.
  • Tất cả các sự kiện khác liên quan đến phối hợp giao diện người dùng.

Một số sự kiện chỉ là cục bộ trong ứng dụng web. Chúng được xác định bởi một bus cục bộ, như thể hiện trong Liệt kê 1:

Liệt kê 1. Thiết lập bus
bus = { 
 
    local: new EventBus({ 
        name: 'EventBus Local' 
    }), 
 
    remote: EventBus.cometd({ 
        name: 'EventBus Remote', 
        logLevel: 'warn', 
        url: document.location.href.substring(0, 
            document.location.href.length - 
            document.location.pathname.length) + '/async', 
        onConnect: function() { 
            bus.local.topic('/event/bus/remote/connected').publish(); 
        }, 
        onDisconnect: function() { 
            bus.local.topic('/event/bus/remote/disconnected').publish(); 
        } 
    }) 
 
};

Đối với các sự kiện từ xa khác, chúng cần một hệ thống Reverse Ajax, như CometD, được xuất bản giữa tất cả các máy khách. Hình 1 cho thấy ứng dụng ví dụ.

Hình 1. Ứng dụng ví dụ
Ảnh chụp màn hình ứng dụng ví dụ mẫu

Bạn có thể tải về ứng dụng ví dụ. Nhiều lớp đại diện cho các lớp bảo mật hoặc dùng để quản lý phiên làm việc người dùng. Bài này chỉ ra những phần quan trọng nhất của mã này, bạn nên tải về và chạy thử ví dụ để thấy cách nó làm việc.

Ứng dụng web được tạo nên bằng các thành phần khác nhau: một phòng chat, danh sách người dùng và giao diện điều khiển. Mỗi thành phần hoàn toàn độc lập và có thể bị loại bỏ mà không ảnh hưởng đến những thành phần khác.

Để thiết lập hệ thống theo hướng sự kiện, cục bộ và từ xa, ví dụ này sử dụng hệ thống EventBus của Ovea. Nó cung cấp một event bus cục bộ, một cầu nối cho CometD để có các sự kiện từ xa và là một cách để phối hợp các sự kiện (để kích hoạt các hành động sau khi đã hoàn thành một số sự kiện). Tất nhiên, bạn có thể thay một hệ thống khác, nếu bạn chọn. Ví dụ này được viết bằng JavaScript, như thể hiện trong Liệt kê 1.

Một khi những bus này đã sẵn sàng sử dụng, ứng dụng và các thành phần là dựa vào sự kiện. Trong ví dụ này, hệ thống phát hiện IDLE được thiết lập như trong Liệt kê 2:

Liệt kê 2. Hệ thống phát hiện IDLE
bus.local.topic('/event/dom/loaded').subscribe(function() { 
    $.idleTimer(20000); 
    $(document).bind('idle.idleTimer', function() { 
        bus.local.topic('/event/idle').publish('inactive'); 
    }); 
    $(document).bind('active.idleTimer', function() { 
        bus.local.topic('/event/idle').publish('active'); 
    }); 
})

Với mã trong Liệt kê 2, hệ thống IDLE gửi các sự kiện khi nó phát hiện ra một hành động. Có thể sử dụng mã này trong bất kỳ ứng dụng nào đòi hỏi một hệ thống IDLE. Trong trường hợp này, bạn cần chuyển dịch nó theo các sự kiện từ xa cho hoạt động của người dùng. Nó cũng được thực hiện bằng JavaScript, như thể hiện trong Liệt kê 3:

Liệt kê 3. Quản lý hoạt động người dùng
bus.local.topic('/event/idle').subscribe(function(status) { 
    bus.remote.topic('/event/user/status/changed').publish({ 
        status: status == 'active' ? 'online' : 'away' 
    }); 
}); 
 
bus.remote.topic('/event/user/status/changed').subscribe(function(evt) { 
    if(evt.user != me.name) { 
        $('#users li').filter(function() { 
            return evt.user == $(this).data('user').name; 
        }).removeClass('online')
          .removeClass('away')
          .addClass(evt.status); 
    } 
});

Việc đăng ký đầu tiên nhận được các sự kiện từ hệ thống IDLE và gửi trạng thái người dùng đến máy chủ. Việc đăng ký khác đã nhận được các sự kiện trạng thái người dùng từ máy chủ. Vì vậy, ngay khi một trạng thái người dùng thay đổi, màu sắc của danh sách người dùng thay đổi sang màu xanh hoặc màu cam.

Khi một người dùng kết nối hoặc ngắt kết nối, một sự kiện được gửi đi, như thể hiện trong Liệt kê 4:

Liệt kê 4. Quản lý danh sách người dùng
bus.remote.topic('/event/user/connected').subscribe(function(user) { 
    $('#users ul').append(row(user)); 
}); 
 
bus.remote.topic('/event/user/disconnected').subscribe(function(evt) { 
    $('#users li').filter(function() { 
        return evt.user == $(this).data('user').name; 
    }).remove(); 
});

Những đoạn mã trong ứng dụng rất đơn giản, được tách riêng và được cô lập. Bằng cách sử dụng lại nhiều công nghệ Ovea bạn có thể nhanh chóng tạo ra các ứng dụng web theo hướng sự kiện. Tuy nhiên, điều đó không cần thiết do hệ thống khác có thể được theo cách của nó. Ví dụ này chỉ mất một ngày phát triển và một nửa của nó là những đoạn mã thiết yếu, bao gồm:

  • Maven, để xây dựng dự án.
  • Các tính năng bảo mật (đăng nhập, đăng xuất, thời gian chờ phiên làm việc).
  • Các dịch vụ RES khi sử dụng Jersey.

Kết luận

Loạt bài này đã chỉ ra cách xây dựng các ứng dụng có thể đáp ứng và có thể co giãn linh động, cung cấp một trải nghiệm người dùng tốt. Các ứng dụng web dựa trên sự kiện là một khái niệm khá mới. Một số web framework sử dụng chúng trong nội bộ, nhưng bài này đã cho thấy rằng bạn không cần một web framework để xây dựng một ứng dụng như vậy. Việc sử dụng thư viện tốt chuyên biệt thì phù hợp hơn so với việc phân định trách nhiệm giữa các nhà phát triển Java và thiết kế web. Hy vọng rằng giờ đây bạn đã có hiểu biết nhất định về cách phát triển theo hướng sự kiện và biến nó trở thành thói quen của mình. Nó có sức hút mạnh mẽ và khi bạn quyết định áp dụng, có thể bạn sẽ không muốn quay trở về với các framework truyền thống nữa.


Tải về

Mô tảTênKích thước
Article source codereverse_ajaxpt5_source.zip925KB

Tài nguyên

Học tập

Lấy sản phẩm và công nghệ

Thảo luận

Bình luận

developerWorks: Đăng nhập

Các trường được đánh dấu hoa thị là bắt buộc (*).


Bạn cần một ID của IBM?
Bạn quên định danh?


Bạn quên mật khẩu?
Đổi mật khẩu

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Ở lần bạn đăng nhập đầu tiên vào trang developerWorks, một hồ sơ cá nhân của bạn được tạo ra. Thông tin trong bản hồ sơ này (tên bạn, nước/vùng lãnh thổ, và tên cơ quan) sẽ được trưng ra cho mọi người và sẽ đi cùng các nội dung mà bạn đăng, trừ khi bạn chọn việc ẩn tên cơ quan của bạn. Bạn có thể cập nhật tài khoản trên trang IBM bất cứ khi nào.

Thông tin gửi đi được đảm bảo an toàn.

Chọn tên hiển thị của bạn



Lần đầu tiên bạn đăng nhập vào trang developerWorks, một bản trích ngang được tạo ra cho bạn, bạn cần phải chọn một tên để hiển thị. Tên hiển thị của bạn sẽ đi kèm theo các nội dung mà bạn đăng tải trên developerWorks.

Tên hiển thị cần có từ 3 đến 30 ký tự. Tên xuất hiện của bạn phải là duy nhất trên trang Cộng đồng developerWorks và vì lí do an ninh nó không phải là địa chỉ email của bạn.

Các trường được đánh dấu hoa thị là bắt buộc (*).

(Tên hiển thị cần có từ 3 đến 30 ký tự)

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Thông tin gửi đi được đảm bảo an toàn.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=70
Zone=Nguồn mở
ArticleID=856174
ArticleTitle=Reverse Ajax, Phần 5: Phát triển web theo hướng sự kiện
publish-date=01252013