Sunday, November 21, 2010

Quick tour CometD Bayeux Ajax Push


Share/Bookmark
Project này cũng finish được hơn tháng và chuyển giao cho các bạn CafeF nhưng giờ mới nghĩ ra phần thống kê lại xung quanh cái gọi là "CometD Bayeux Ajax Push" này để chuẩn bị cho contest ở công ty sắp tới :D

Công nghệ Comet được nhắc tới khá nhiều từ đầu những năm 2007 nhưng cho đến hiện tại nó vẫn gần như là mới ở VN, đợt rồi phải làm cái bảng mã chứng khoán trên web và mobile, yêu cầu thì rất chi là yêu cầu ( dữ liệu cập nhật gần như lập tức ngay khi có thay đổi của mã nào đó trên sàn chứng khoán - realtime )

Bài toán đặt ra : Hệ thống cần đáp ứng được ~ 15000 request/s với mỗi lần request có > 5 mã chứng khoán trả về dữ liệu thay đổi.

Giải quyết : Vào một ngày đẹp zời sếp recommend cho cái cometd này, cometd là dự án của Dojo Foundation.
Cũng phải nói thêm với bài toán bảng mã chứng khoán realtime dạng này thì LightStreamer hay được sử dụng ở VN nhưng vấn đề bản quyền là 1 vấn đề. LightStreamer cũng có bản free nhưng đến tầm 10000 request/s thì cần phải xem xét lại, hơn nữa đây là hệ thống gói nên việc maintain riêng nó về sau không hẳn dễ dàng. 0pensource lại một lần nữa lên ngôi :-"

Tóm tắt : CometD là sự kết hợp giữa client (ajax) và kỹ thuật server-push. Ajax hiện nay có 2 framework hỗ trợ CometD là jQuery và Dojo.
Điểm chính nữa cần chú ý ở đây là Bayeux Protocol (NIO: Non-Blocking IO). Đây là một giao thức truyền tải dữ liệu đáp ứng tốt yêu cầu realtime của bài toán, với đỗ trễ khá thấp(ms). Hơn nữa giao thức này thông qua HTTP nên hạn chế được tối đa trường hợp request có thể bị block bởi firewall như ở một số giao thức khác.
Mô tả chi tiết về giao thức Bayeux : http://cometd.org/documentation/bayeux/spec

Ở project này sẽ sử dụng phương thực Polling Transpot (xem mục 1.4.5.i Polling transports ở link giao thức Bayeux ở trên :-) )

BC ---------- U ---------- P ------------ O ---------- BS
| ---M0--->  |            |              |            |
|            | --- HTTP request(M0) ---> |            |
|            |            |              | ----M0---> |
~            ~            ~              ~            ~ wait
|            |            |              | <--M1(E)-- | 
|            | <--HTTP response(M1(E))-- |            | 
| <--M1(E)-- |            |              |            | 
| ---M2--->  |            |        
|            |
|            | --- HTTP request(M2) ---> |            |
|            |            |              | ----M2---> |
~            ~            ~              ~            ~ wait


Dữ liệu trả về client dạng Json nên được tối ưu ở việc nén dữ liệu cao nhất có thể.
Ngoài ra tản mạn thêm chút về performance cho project dạng này;

Với bảng chứng khoán trên website cho người dùng desktop và laptop thì việc performance đặc biệt cần được quan tâm.
Lý do dễ thấy là với trên 600 mã chứng khoán từ 2 bảng thì việc nhận về > 50 mã thay đổi cùng 1 lúc là dễ gặp, thậm chí với người dùng truy cập lần đầu thì sẽ trả về dữ liệu của ~ 300 mã trên 1 bảng.
Recommend của IExplorer là 5.000.000 values trong 1 mảng thì sẽ xảy ra trường hợp thông báo lỗi script error trên phía client do compiler javascript của browser không chịu nổi nhiệt, nhưng tôi đã test với chỉ khoảng 1000.000 array values thì đã gặp trường hợp trên (System: core i5 430, 4GB of Ram :( )
Tham khảo script long-running : http://www.nczonline.net/blog/2009/01/05/what-determines-that-a-script-is-long-running/
Ở link trên đáng chú ý nhất là IE với giới hạn <=5ms :| Profiler là bắt buộc phải làm để mần đủ mọi cách giảm tối đa thời gian script execution. Về Javascript performance (Profiler, debug, logging, scope chain, clousure...) sẽ trình bày ở 1 bài viết khác không có lại lan man quá :-p Kết quả sau khi dev xong hệ thống với 1 cu nữa mần phần server Jetty (Mình Fronteer thôi :">).

• Cấu hình máy chủ: 2CPU Quad core 2.3Ghz, 16GB RAM (Shared with other services).
• Tốc độ benchmark đạt tới gần 20000 request/s (với mỗi lần thay đổi dữ liệu 100 mã :D ), ~ 63000 established connections, sử dụng hơn 8GB RAM, dữ liệu truyền/nhận khoảng 1Kb. Thời gian đáp ứng dưới 1s.

Good(not best;)) ) choice for realtime message :)

Recommend for chat system, stock ...