Friday, May 05, 2006

Server Push

ช่วงนี้กำลังหา solution เพื่อที่จะทำ Server Push อยู่
โจทย์ตั้งไว้ว่า user จะใช้ browser ในการ monitor เหตุการณ์
ซึ่งต้องการ respone time ที่เร็วพอสมควร

วิธี polling, refresh browser ทุก x วินาที นี่ตัดทิ้งไปก่อนเลย
คราวนี้ก็เลยต้องชั่งน้ำหนักอยู่ว่าจะใช้วิธีไหนดี

วิธีที่ implement ได้ทันทีเลย ก็คือใช้พวก Applet
เปิด socket ไปยัง server
ถ้าให้หรูหน่อย ก็ใช้ applet ต่อเป็น JMS Client
ง่ายขึ้นอีกหน่อย ก็ใช้ Jabber protocol

แต่ผมดันเกิดอยากลองใช้ javascript client ล้วนๆดูบ้าง
ก็เลยต้องลำบากเพิ่มขึ้นหน่อย

เริ่มด้วยวิธี primitive สุด ก็คือ เมื่อ browser
request มาขอข้อมูลแล้ว เมื่อส่งข้อมูลเสร็จ แทนที่ server จะสั่งปิด connection เลย
ก็ให้ server วน loop รอ
เมื่อไรที่เกิด event ที่ server, ก็ค่อย write stream สั่ง flush
จากนั้นก็เข้า loop wait รอต่อไป
โดยวิธีนี้ implement ได้ 2 วิธี ก็คือ
implement ตรงๆ ตอน browser get เลย
กับอีกวิธีหนึ่งก็เอาไปฝากผ่านทาง iframe
แต่ไม่ว่าใช้ทางใด ข้อเสียที่เห็นได้ชัดก็คือ
browser จะแสดง icon หมุนๆๆๆ แสดง status ว่ายังได้รับข้อมูลจาก server ไม่หมด
ซึ่งการแสดง status อย่างนี้ น่าจะสร้างความสับสนให้ user

วิธีถัดไปก็คือให้ XMLHttpRequest
แน่นอนว่าช่วยแก้ปัญหา icon หมุนๆๆๆ ได้
แต่ประเด็นปัญหาของวิธีนี้ ก็คือ จะต้องหาทางทำให้ XMLHttpRequest
รับ response เป็นส่วนๆ(chunk) ให้ได้
ซึ่งในกรณีของ Firefox เราสามารถใช้ multipart/x-mixed-replace
เข้ามาช่วยได้
แน่นอนว่าวิธีนี้ IE ไม่ support
แต่ใน IE ก็มี component หนึ่งที่ช่วย support วิธีนี้เหมือนกัน
เรียกว่า ondataavailable - MSXML 4.0

ดูแล้วถ้าต้องทำให้ support หลายๆ browser
วิธี chunk ก็ดูเป็นการทรมานจิตใจเกินไป

เมื่อ chunk ไม่ได้ ก็เลยมีคนคิดวิธีว่า
ก็ให้เปิด XMLHttpRequest ไปที่ server
โดยกรณีที่ server มี event ที่จะ push อยู่แล้วก็จะตอบกลับมาเลย
แต่ถ้ายังไม่มี server ก็จะ loop รอก่อน
ถ้าครบเวลาที่กำหนดแล้วยังไม่มี event มา
server ก็จะ return กลับมา
ในส่วนของ client เมื่อได้รับ return message จาก server (ไม่ว่าจะมี event หรือไม่มี event มา)
client ก็จะ request เปิด XMLHttpRequest ซ้ำกลับไปอีกทันที
เนื่องจาก request เกิดอย่างต่อเนื่อง
socket connection ก็เลยถูกเปิดแช่ไว้ เป็น persistent connection
บางคนเรียกวิธีนี้ว่า waiting poll mechanism
วิธีนี้ ค่อนข้างมีคนนิยมกันมาก ไม่ว่าจะเป็นใน
DWR 2.0, ActiveMQ Ajax, ฯลฯ

วิธีถัดไปก็คือ ใช้ AFLAX
วิธีนี้แอบใช้ feature ใน Flash 8
มีข้อเสียนิดหน่อยตรงที่
browser ต้อง install flash 8 ด้วย
กับเอกสารที่อธิบายน้อยไปหน่อย

ตอนนี้ทดลองทดสอบ ไป 2 วิธีแล้ว
ก็คือ primitive กับ DWR
ส่วน multipart ยังติดปัญหาที่ servlet มัน overwrite content-type ที่ผม set ไว้
ก็เลยขี้เกียจดูต่อ
เหลือวิธี aflax กับ ActiveMQ Ajax ที่จะลองทำพรุ่งนี้

Related link from Roti

2 comments:

pittaya said...

ที่จริงแล้วฟีเจอร์ที่ใช้ทำ AFLAX มีมาตั้งแต่ Flash5 นะครับ
แต่มันต้องเขียน ActionScript ให้ใช้งานออบเจกต์ XMLSocket ของ Flash
จะเป็นการเปิด persistent connection ไปที่ server เลย แล้วเขียน callback จัดการกับ event ให้ไปเรียก javascript อีกทีนึง

polawat phetra said...

เห็น FAQ ของ AFLAX เขาพูดเหมือนกันว่า
version ก่อนหน้า v8 การคุยกันระหว่าง javascript
กับ flash จะทำผ่าน javascript gateway? (ไม่เคยใช้ flash ก็เลยไม่รู้ว่าคำอ้างนี้ถูกหรือเปล่า) ส่วนใน library version ปัจจุบันของ AFLAX เขา
implement ด้วย ExternalInterface ซึ่งเป็น feature ใหม่ใน flash8
ซึ่งเขาอ้างว่า ด้วยการใช้ ExternalInterface
ทำให้เราสามารถใช้ javascript สร้าง flash content,
โดยไม่ต้องไปยุ่งกับ flash IDE หรือ actionscript เลย