Long Polling เป็นเทคนิคการโต้ตอบระหว่างไคลเอ็นต์และเซิร์ฟเวอร์ โดยเซิร์ฟเวอร์จะคงคำขอ HTTP ไว้จนกว่าจะมีข้อมูลใหม่ปรากฏขึ้นหรือหมดเวลารอ ต่างจากการสอบถามแบบเป็นระยะ เซิร์ฟเวอร์จะไม่ส่งคำตอบว่างทันที แต่รอให้เกิดเหตุการณ์เพื่อส่งข้อมูลไปยังไคลเอ็นต์ ตาม MDN Web Docs, 2024 Long Polling ยังคงเป็นโซลูชันที่เป็นที่ต้องการสำหรับแอปพลิเคชันแบบเรียลไทม์ที่ WebSocket ไม่พร้อมใช้งานหรือมากเกินความจำเป็น
ประเด็นสำคัญ
Long Polling เป็นรูปแบบการโต้ตอบในสถาปัตยกรรมไคลเอ็นต์-เซิร์ฟเวอร์ โดยไคลเอ็นต์เริ่มต้นคำขอ HTTP และเซิร์ฟเวอร์เลื่อนการส่งคำตอบออกไปจนกว่าข้อมูลใหม่จะปรากฏหรือหมดเวลาที่กำหนด หลังจากได้รับคำตอบ ไคลเอ็นต์จะส่งคำขอถัดไปทันที สร้างผลของการเชื่อมต่ออย่างต่อเนื่อง
เทคนิค Long Polling เกิดขึ้นจากการพัฒนาของ Short Polling เพื่อลดจำนวนคำขอ HTTP ที่ว่างเปล่า ในการสอบถามแบบดั้งเดิม ไคลเอ็นต์ส่งคำขอทุก N วินาที และเซิร์ฟเวอร์ตอบสนองแม้ไม่มีข้อมูลใหม่ ใน Long Polling เซิร์ฟเวอร์ใช้ กลไกการคงการเชื่อมต่อ ซึ่งช่วยลดปริมาณทราฟฟิกที่ไม่จำเป็นลงอย่างมาก
ก่อนที่ WebSocket จะปรากฏในปี 2011 Long Polling เป็นวิธีหลักในการจัดระเบียบการสื่อสารแบบเรียลไทม์บนเว็บ บริษัทอย่าง Facebook และ Gmail ใช้เทคนิคนี้สำหรับแชทและการแจ้งเตือนในช่วงต้นปี 2010 ตามการวิจัยของ High Performance Browser Networking (Grigorik, 2013) Long Polling จัดการการเชื่อมต่อแบบเรียลไทม์สูงถึง 95% ในแอปพลิเคชันเว็บขนาดใหญ่ในยุคนั้น
ไคลเอ็นต์ส่งคำขอ HTTP มาตรฐานไปยังเซิร์ฟเวอร์ เมื่อได้รับคำขอ เซิร์ฟเวอร์ไม่ส่งคำตอบทันที แต่ใส่คำขอไว้ในคิวรอ เมื่อเกิดเหตุการณ์บนเซิร์ฟเวอร์ (ข้อความใหม่ การเปลี่ยนแปลงข้อมูล) เซิร์ฟเวอร์จะสร้างคำตอบและส่งไปยังไคลเอ็นต์ เมื่อได้รับคำตอบ ไคลเอ็นต์จะสร้าง คำขอ Long Polling ใหม่ทันที และวงจรจะทำซ้ำ
Long Polling ทำงานตามลำดับขั้นตอนดังนี้ ไคลเอ็นต์ส่งคำขอ HTTP GET ไปยังเอนด์พอยต์ของเซิร์ฟเวอร์ เมื่อได้รับคำขอ เซิร์ฟเวอร์ตรวจสอบว่ามีข้อมูลใหม่ในคิวเหตุการณ์หรือไม่ หากไม่มีข้อมูล เซิร์ฟเวอร์คงคำขอไว้ในสถานะรอ โดยไม่ส่งคำตอบทันที กลไกการคงคำขอขึ้นอยู่กับการใช้งานของเซิร์ฟเวอร์ — ส่วนใหญ่มักใช้การประมวลผลแบบอะซิงโครนัสด้วยคอลแบ็กหรือสถาปัตยกรรมแบบขับเคลื่อนด้วยเหตุการณ์
เมื่อเกิดเหตุการณ์บนฝั่งเซิร์ฟเวอร์ (เช่น ผู้ใช้ส่งข้อความในแชท) เซิร์ฟเวอร์จะสร้างคำตอบ HTTP ที่มีข้อมูลดังกล่าวและสิ้นสุดการเชื่อมต่อ ไคลเอ็นต์ได้รับคำตอบ ประมวลผลข้อมูล และ เริ่มคำขอใหม่ทันที หากไม่มีข้อมูลปรากฏในช่วงรอ เซิร์ฟเวอร์จะส่งคำตอบว่างเมื่อหมดเวลา และไคลเอ็นต์จะสร้างการเชื่อมต่อใหม่เช่นกัน โดยทั่วไปหมดเวลาจะอยู่ที่ 30-60 วินาทีเพื่อความสมดุลระหว่างโหลดและความหน่วง
พารามิเตอร์สำคัญของการกำหนดค่า Long Polling คือ เวลารอก่อนหมดเวลา การหมดเวลาที่สั้นเกินไป (น้อยกว่า 10 วินาที) ทำให้จำนวนคำขอเพิ่มขึ้น ทำให้เทคนิคใกล้เคียงกับ Short Polling การหมดเวลาที่ยาวเกินไป (มากกว่า 120 วินาที) อาจทำให้พร็อกซีและตัวปรับสมดุลโหลดตัวกลางตัดการเชื่อมต่อ ค่าที่แนะนำสำหรับสถานการณ์ส่วนใหญ่คือ 30-45 วินาที
หากมีเหตุการณ์หลายรายการเกิดขึ้นบนเซิร์ฟเวอร์ระหว่างคำขอ Long Polling หนึ่งครั้ง เซิร์ฟเวอร์ควรส่งทั้งหมดในคำตอบเดียวหรือจัด คิวเหตุการณ์ บนฝั่งไคลเอ็นต์ เพื่อการนี้ จะใช้การบัฟเฟอร์เหตุการณ์: เซิร์ฟเวอร์สะสมเหตุการณ์ที่เกิดขึ้นระหว่างการคงคำขอ และส่งเป็นอาร์เรย์ข้อมูลในเนื้อหาของคำตอบ
มาดูการใช้งาน Long Polling อย่างง่ายบนฝั่งไคลเอ็นต์ด้วย Fetch API ที่ทันสมัย ฟังก์ชันไคลเอ็นต์ส่งคำขอและเรียกตัวเองซ้ำหลังจากได้รับคำตอบ
async function longPoll(url) {
try {
const response = await fetch(url);
const data = await response.json();
handleData(data);
longPoll(url);
} catch (error) {
console.error("ข้อผิดพลาด Long Polling", error);
setTimeout(() => longPoll(url), 3000);
}
}
function handleData(data) {
if (data.events && data.events.length > 0) {
data.events.forEach(event => {
console.log("เหตุการณ์ใหม่:", event);
});
}
}
longPoll("/api/events");
โค้ดนี้สร้างลูป Long Polling ไม่มีที่สิ้นสุด: หลังจากได้รับคำตอบ ฟังก์ชันจะส่งคำขอใหม่ทันที ในกรณีที่เกิดข้อผิดพลาดในการเชื่อมต่อ จะตั้ง หน่วงเวลาสามวินาที ก่อนลองใหม่ เพื่อหลีกเลี่ยงโหลดท่วมเซิร์ฟเวอร์
บนฝั่งเซิร์ฟเวอร์ จำเป็นต้องคงคำขอไว้จนกว่าเหตุการณ์จะปรากฏหรือหมดเวลา ตัวอย่างการใช้งานด้วย EventEmitter ใน Node.js แสดงให้เห็นกลไกนี้
const express = require("express");
const EventEmitter = require("events");
const app = express();
const eventBus = new EventEmitter();
app.get("/api/events", (req, res) => {
const timeout = setTimeout(() => {
res.json({ events: [] });
}, 30000);
eventBus.once("new-event", (data) => {
clearTimeout(timeout);
res.json({ events: [data] });
});
});
app.post("/api/events", (req, res) => {
eventBus.emit("new-event", req.body);
res.send({ status: "ok" });
});
app.listen(3000);
ส่วนเซิร์ฟเวอร์ใช้ EventEmitter เพื่อแจ้งการเชื่อมต่อ Long Polling ที่รออยู่เมื่อมีข้อมูลใหม่ปรากฏ เมื่อถึงหมดเวลา 30 วินาที เซิร์ฟเวอร์จะส่ง อาร์เรย์เหตุการณ์ว่าง และไคลเอ็นต์สร้างคำขอใหม่
Long Polling ใช้ในสถานการณ์ที่ต้องการส่งข้อมูลแบบเรียลไทม์ แต่ไม่สามารถใช้ WebSocket ได้เนื่องจากเหตุผลทางเทคนิคหรือโครงสร้างพื้นฐาน กรณีที่พบบ่อยที่สุดคือพร็อกซีองค์กรและไฟร์วอลล์ที่บล็อกการเชื่อมต่อ WebSocket รวมถึงสภาพแวดล้อมที่มีการสนับสนุนโปรโตคอลบนฝั่งเซิร์ฟเวอร์อย่างจำกัด
ปัจจัยสำคัญในการเลือก Long Polling คือความเข้ากันได้ย้อนหลัง ไคลเอ็นต์และเซิร์ฟเวอร์ HTTP ทั้งหมดรองรับวิธีนี้ ทำให้เป็นโซลูชันสากลสำหรับ เรียลไทม์ โดยไม่ต้องพึ่งพาเพิ่มเติม ตาม HTTP Archive (2024) ประมาณ 8% ของเว็บไซต์ทั้งหมดยังคงใช้ Long Polling สำหรับฟังก์ชันพื้นฐานแบบเรียลไทม์
Long Polling และ Short Polling แก้ปัญหาเดียวกัน — การส่งข้อมูลจากเซิร์ฟเวอร์ไปยังไคลเอ็นต์ — แต่แตกต่างกันโดยพื้นฐานในกลไกและประสิทธิภาพ Short Polling ใช้ช่วงเวลาการสอบถามคงที่ โดยไคลเอ็นต์ส่งคำขอ HTTP ในช่วงเวลาที่เท่ากันโดยไม่ขึ้นกับว่าเซิร์ฟเวอร์มีข้อมูลใหม่หรือไม่
| คุณลักษณะ | Long Polling | Short Polling |
|---|---|---|
| การเริ่มตอบสนอง | เซิร์ฟเวอร์ส่งข้อมูลเมื่อเกิดเหตุการณ์ | เซิร์ฟเวอร์ตอบสนองต่อทุกคำขอของไคลเอ็นต์ |
| ความหน่วงในการส่ง | น้อยที่สุด สูงสุด 1 วินาที | ขึ้นอยู่กับช่วงเวลาการสอบถาม 3-60 วินาที |
| จำนวนคำขอ | 1 คำขอต่อเหตุการณ์หรือหมดเวลา | N คำขอต่อหน่วยเวลา (คงที่) |
| ทราฟฟิกขณะว่าง | ต่ำ (หนึ่งคำขอที่เปิดอยู่) | สูง (คำขอทุก N วินาที) |
| โหลดบนเซิร์ฟเวอร์ | การคงการเชื่อมต่อ | การประมวลผลคำขอบ่อยครั้ง |
| ความซับซ้อนในการใช้งาน | ปานกลาง (การประมวลผลแบบอะซิงโครนัส) | ต่ำ (คำขอ HTTP ทั่วไป) |
Short Polling ใช้งานง่ายกว่า แต่สร้างโหลดบนเซิร์ฟเวอร์และเครือข่ายมากกว่าอย่างมีนัยสำคัญที่ความถี่การอัปเดตข้อมูลเท่ากัน หากต้องการความหน่วงน้อยกว่า 5 วินาที Short Polling จะสร้างคำขอนับสิบต่อนาที ในขณะที่ Long Polling ใช้หนึ่งคำขอต่อเหตุการณ์หรือหมดเวลา สำหรับแอปพลิเคชันที่มีเหตุการณ์ไม่บ่อย Long Polling มีประสิทธิภาพมากกว่าหลายเท่าในแง่ของทราฟฟิก
WebSocket เป็นโปรโตคอลเรียลไทม์แบบสองทิศทางเต็มรูปแบบที่ทำงานบน TCP หลังจากการจับมือ HTTP เริ่มต้น แตกต่างจาก Long Polling ตรงที่ WebSocket สร้างการเชื่อมต่อถาวรหนึ่งรายการและอนุญาตให้เซิร์ฟเวอร์ส่งข้อมูลไปยังไคลเอ็นต์ได้ทุกเมื่อโดยไม่ต้องสร้างคำขอ HTTP ใหม่
การเลือกระหว่าง Long Polling และ WebSocket ขึ้นอยู่กับหลายปัจจัย ความเข้ากันได้: Long Polling ทำงานผ่านพร็อกซีและไฟร์วอลล์ใดก็ได้ ในขณะที่ WebSocket อาจถูกบล็อกโดยเครือข่ายองค์กร ประสิทธิภาพ: WebSocket มีโอเวอร์เฮดน้อยกว่า (2 ไบต์ต่อเฟรม เทียบกับส่วนหัว HTTP เต็ม) ซึ่งสำคัญเมื่อมีความถี่ข้อความสูง ความสามารถในการปรับขนาด: Long Polling ต้องการทรัพยากรบนฝั่งเซิร์ฟเวอร์มากขึ้นเนื่องจากการคงการเชื่อมต่อจำนวนมาก ในขณะที่ WebSocket ใช้การเชื่อมต่อคงที่ต่อเซสชัน
ตาม Mozilla Developer Network (2024) WebSocket รองรับ โดยเบราว์เซอร์สมัยใหม่ทั้งหมดตั้งแต่เวอร์ชัน 2011-2015 แต่พร็อกซีองค์กร (เช่น Symantec Blue Coat) ยังคงบล็อกใน 15-20% ของเครือข่ายองค์กร ซึ่งทำให้ Long Polling ยังคงมีความสำคัญในฐานะโซลูชันสำรอง
คำถามที่พบบ่อย
Long Polling คือเมื่อไคลเอ็นต์ขอให้เซิร์ฟเวอร์ “ตอบเมื่อมีข้อมูลใหม่ปรากฏ” และเซิร์ฟเวอร์คงการเชื่อมต่อไว้เพื่อรอเหตุการณ์ ทันทีที่มีข้อมูลปรากฏ เซิร์ฟเวอร์ตอบกลับ และไคลเอ็นต์ส่งคำถามใหม่เดียวกันทันที
ใน Short Polling ไคลเอ็นต์ถามเซิร์ฟเวอร์ทุก N วินาทีว่ามีข้อมูลหรือไม่ แม้ไม่มีข้อมูลก็ตาม ใน Long Polling ไคลเอ็นต์ถามครั้งเดียว และเซิร์ฟเวอร์ตอบเมื่อข้อมูลปรากฏจริงเท่านั้น Long Polling สร้าง คำขอว่างน้อยกว่า และลดโหลดเครือข่าย
ควรใช้ Long Polling เมื่อ WebSocket ไม่พร้อมใช้งาน: ในเครือข่ายองค์กรที่บล็อกโปรโตคอลที่ไม่ใช่ HTTP เมื่อต้องการ ความเข้ากันได้ย้อนหลังกับเบราว์เซอร์รุ่นเก่าหรือข้อจำกัดด้านโฮสติ้ง WebSocket มีประสิทธิภาพมากกว่าสำหรับการแลกเปลี่ยนข้อมูลความถี่สูง
เวลาหมดของ Long Polling ที่แนะนำคือ 30-45 วินาที ค่าที่น้อยกว่า (10-15 วินาที) เพิ่มจำนวนคำขอ ค่าที่มากกว่า (60+ วินาที) เสี่ยงต่อการตัดการเชื่อมต่อโดยตัวปรับสมดุลโหลดตัวกลาง ค่าหมดเวลาขึ้นอยู่กับสถาปัตยกรรมเครือข่ายและข้อกำหนดด้านความหน่วง
ข้อเสียหลักของ Long Polling — การใช้หน่วยความจำสูงบนเซิร์ฟเวอร์เมื่อคงการเชื่อมต่อนับพัน ความซับซ้อนในการปรับขนาดแนวนอน (ต้องใช้คิวเหตุการณ์แบบรวมศูนย์) และขาดการสื่อสารสองทิศทางที่แท้จริง — ต้องใช้คำขอ POST แยกต่างหากเพื่อส่งข้อมูลไปยังเซิร์ฟเวอร์
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ