การใช้ WebTransport

WebTransport เป็น API ที่รับส่งข้อความแบบไคลเอ็นต์-เซิร์ฟเวอร์ที่มีเวลาในการตอบสนองต่ำแบบ 2 ทิศทาง ดูข้อมูลเพิ่มเติมเกี่ยวกับกรณีการใช้งานและวิธีแสดงความคิดเห็นเกี่ยวกับอนาคตของการติดตั้งใช้งาน

เจฟ พอสนิก
เจฟฟ์ พอสนิก

ที่มา

WebTransport คืออะไร

WebTransport คือเว็บ API ที่ใช้โปรโตคอล HTTP/3 เป็นการส่งแบบ 2 ทิศทาง แต่มีไว้เพื่อการสื่อสารแบบ 2 ทางระหว่างเว็บไคลเอ็นต์กับเซิร์ฟเวอร์ HTTP/3 โดยรองรับการส่งข้อมูลทั้งผ่าน datagram API อย่างไม่น่าไว้วางใจและส่งข้อมูลผ่าน Streams API อย่างน่าเชื่อถือ

Datagrams เหมาะสำหรับการส่งและรับข้อมูลที่ไม่จำเป็นต้องมีการรับประกันการนำส่งที่แข็งแกร่ง แพ็กเก็ตข้อมูลแต่ละรายการจะมีขนาดจำกัดโดยหน่วยการส่งข้อมูลสูงสุด (MTU) ของการเชื่อมต่อที่ใช้อยู่ และอาจส่งได้สำเร็จหรือไม่ และหากได้รับการโอน ก็อาจส่งตามลำดับได้ตามต้องการ ลักษณะเหล่านี้ทำให้ Datagram API เหมาะสำหรับการส่งข้อมูลที่มีเวลาในการตอบสนองต่ำและความพยายามอย่างดีที่สุด คุณอาจคิดว่า Datagram คือข้อความ user datagram Protocol (UDP) แต่มีการเข้ารหัสและควบคุมความคับคั่งได้

ในทางกลับกัน API ของสตรีมให้การโอนข้อมูลตามลำดับที่เชื่อถือได้ ซึ่งเหมาะสมกับสถานการณ์ที่จำเป็นต้องส่งหรือรับสตรีมข้อมูลที่เรียงลำดับอย่างน้อย 1 รายการ การใช้สตรีม WebTransport หลายรายการเทียบเคียงกับการสร้างการเชื่อมต่อ TCP หลายรายการ แต่เนื่องจาก HTTP/3 ใช้โปรโตคอล QUIC ที่มีน้ำหนักน้อยกว่าในระบบ จึงสามารถเปิดและปิดได้โดยไม่มีค่าใช้จ่ายมากนัก

Use Case

นี่เป็นตัวอย่างเล็กๆ น้อยๆ ที่นักพัฒนาซอฟต์แวร์อาจใช้ WebTransport ได้

  • การส่งสถานะของเกมในช่วงเวลาที่สม่ำเสมอโดยมีเวลาในการตอบสนองน้อยที่สุดไปยังเซิร์ฟเวอร์ผ่านข้อความขนาดเล็กที่ไม่น่าเชื่อถือและเรียงลำดับไม่ได้
  • การรับสตรีมสื่อที่พุชจากเซิร์ฟเวอร์ที่มีเวลาในการตอบสนองน้อยที่สุด โดยไม่ขึ้นอยู่กับสตรีมข้อมูลอื่นๆ
  • การรับการแจ้งเตือนแบบพุชจากเซิร์ฟเวอร์ในขณะที่หน้าเว็บเปิดอยู่

เราต้องการรับฟังข้อมูลเพิ่มเติมเกี่ยวกับแผนการใช้งาน WebTransport ของคุณ

การสนับสนุนเบราว์เซอร์

การสนับสนุนเบราว์เซอร์

  • 97
  • 97
  • 114
  • x

แหล่งที่มา

การเขียนโค้ดด้วยการป้องกันด้วยการตรวจหาฟีเจอร์ถือเป็นแนวทางปฏิบัติที่ดีที่สุด เช่นเดียวกับฟีเจอร์ทั้งหมดที่ไม่รองรับเบราว์เซอร์แบบสากล

สถานะปัจจุบัน

ขั้นตอน สถานะ
1. สร้างข้อความอธิบาย เสร็จสมบูรณ์
2. สร้างฉบับร่างเริ่มต้นของข้อกำหนด เสร็จสมบูรณ์
3. รวบรวมความคิดเห็นและทำซ้ำการออกแบบ เสร็จสมบูรณ์
4. ช่วงทดลองใช้จากต้นทาง เสร็จสมบูรณ์
5. เปิดตัว Chromium 97

ความสัมพันธ์ของ WebTransport กับเทคโนโลยีอื่นๆ

WebTransport มาแทนที่ WebSocket หรือไม่

อาจจะได้ มีกรณีการใช้งานที่ WebSockets หรือ WebTransport อาจเป็นโปรโตคอลการสื่อสารที่ถูกต้อง

การสื่อสารของ WebSockets มาจากสตรีมข้อความแบบเรียงลำดับตามที่เชื่อถือได้เพียงชุดเดียว ซึ่งเหมาะสมสำหรับความต้องการในการสื่อสารบางประเภท หากคุณต้องการลักษณะเฉพาะเหล่านั้น API ของสตรีม WebTransport ก็สามารถให้ข้อมูลดังกล่าวได้เช่นกัน เมื่อเทียบกันแล้ว Datagram API ของ WebTransport ทำให้การส่งล่าช้าโดยไม่ให้การรับประกันความน่าเชื่อถือหรือการสั่งซื้อ จึงไม่ใช่สิ่งที่มาแทนที่ WebSockets โดยตรง

การใช้ WebTransport, ผ่าน Datagram API หรือผ่านอินสแตนซ์ API ของ Streams ที่เกิดขึ้นพร้อมกันหลายอินสแตนซ์ทำให้คุณไม่ต้องกังวลเกี่ยวกับการบล็อกบรรทัดแรก ซึ่งอาจเป็นปัญหากับ WebSockets นอกจากนี้ ยังมีประโยชน์ด้านประสิทธิภาพเมื่อสร้างการเชื่อมต่อใหม่ เนื่องจากแฮนด์เชค QUIC ที่เกี่ยวข้องรวดเร็วกว่าการเริ่ม TCP ผ่าน TLS

WebTransport เป็นส่วนหนึ่งของข้อกำหนดฉบับร่างใหม่ ด้วยเหตุนี้ ระบบนิเวศของ WebSocket สำหรับไลบรารีของไคลเอ็นต์และเซิร์ฟเวอร์ในปัจจุบันจึงมีประสิทธิภาพมากกว่าเป็นอย่างมาก หากต้องการเครื่องมือที่ทำงานได้แบบ "แกะกล่อง" สำหรับการตั้งค่าทั่วไปของเซิร์ฟเวอร์และรองรับไคลเอ็นต์เว็บในวงกว้าง WebSockets คือตัวเลือกที่ดีกว่าในปัจจุบัน

WebTransport เหมือนกับ UDP Socket API ไหม

ไม่ WebTransport ไม่ใช่ UDP Socket API ในขณะที่ WebTransport ใช้ HTTP/3 ซึ่งต่างใช้ UDP "ภายใน" WebTransport มีข้อกำหนดด้านการเข้ารหัสและการควบคุมความคับคั่งที่ทำให้เป็นมากกว่า UDP Socket API พื้นฐาน

WebTransport เป็นทางเลือกนอกเหนือจากช่องข้อมูล WebRTC หรือไม่

ใช่ สำหรับการเชื่อมต่อแบบไคลเอ็นต์-เซิร์ฟเวอร์ WebTransport ใช้พร็อพเพอร์ตี้เดียวกันกับช่องทางข้อมูล WebRTC แต่โปรโตคอลที่สำคัญจะต่างกัน

โดยทั่วไปแล้ว การเรียกใช้เซิร์ฟเวอร์ที่เข้ากันได้กับ HTTP/3 ต้องมีการตั้งค่าและกำหนดค่าน้อยกว่าการดูแลรักษาเซิร์ฟเวอร์ WebRTC และต้องทำความเข้าใจโปรโตคอลหลายรายการ (ICE, DTLS และ SCTP) เพื่อรับการรับส่งที่ใช้งานได้ WebRTC ต้องมีการย้ายข้อมูลอีกมากมายที่อาจทำให้การเจรจาเกี่ยวกับไคลเอ็นต์/เซิร์ฟเวอร์ล้มเหลว

WebTransport API ออกแบบมาโดยคำนึงถึง Use Case ของนักพัฒนาเว็บ และควรให้ความรู้สึกเหมือนการเขียนโค้ดแพลตฟอร์มเว็บที่ทันสมัยมากกว่าการใช้อินเทอร์เฟซช่องข้อมูลของ WebRTC ไม่เหมือน WebRTC WebTransport มีการสนับสนุนภายใน Web Workers ซึ่งทำให้คุณสามารถสื่อสารแบบไคลเอ็นต์-เซิร์ฟเวอร์โดยไม่ขึ้นอยู่กับหน้าเว็บ HTML ที่กำหนด เนื่องจาก WebTransport แสดงอินเทอร์เฟซที่สอดคล้องกับสตรีม จึงรองรับการเพิ่มประสิทธิภาพในช่วงBackpressure

อย่างไรก็ตาม หากคุณมีการตั้งค่าไคลเอ็นต์/เซิร์ฟเวอร์ WebRTC ที่ใช้งานได้และพอใจอยู่แล้ว การเปลี่ยนไปใช้ WebTransport อาจไม่ก่อให้เกิดประโยชน์มากนัก

ลองเลย

วิธีที่ดีที่สุดในการทดสอบด้วย WebTransport คือเริ่มต้นเซิร์ฟเวอร์ HTTP/3 ที่ใช้งานร่วมกันได้ จากนั้นคุณสามารถใช้หน้านี้กับไคลเอ็นต์ JavaScript พื้นฐานเพื่อลองใช้การสื่อสารแบบไคลเอ็นต์/เซิร์ฟเวอร์

นอกจากนี้ เซิร์ฟเวอร์เสียงสะท้อนที่ได้รับการดูแลโดยชุมชนก็พร้อมให้ใช้งานที่ webtransport.day

การใช้ API

WebTransport ออกแบบมาโดยคำนึงถึงแพลตฟอร์มเว็บพื้นฐานสมัยใหม่ เช่น Streams API เนื่องจากอาศัยคำสัญญาเป็นหลัก รวมถึงทำงานได้ดีกับ async และ await

การใช้งาน WebTransport ในปัจจุบันใน Chromium รองรับการเข้าชมที่แตกต่างกัน 3 ประเภท ได้แก่ Datagram และสตรีมทั้ง 2 ทิศทางและทั้ง 2 ทิศทาง

กำลังเชื่อมต่อกับเซิร์ฟเวอร์

คุณเชื่อมต่อกับเซิร์ฟเวอร์ HTTP/3 ได้โดยการสร้างอินสแตนซ์ WebTransport รูปแบบของ URL ควรเป็น https คุณต้องระบุหมายเลขพอร์ตให้ชัดเจน

คุณควรใช้สัญญา ready เพื่อรอให้การเชื่อมต่อเริ่มขึ้น สัญญานี้จะไม่มีผลจนกว่าการตั้งค่าจะเสร็จสมบูรณ์ และจะปฏิเสธหากเชื่อมต่อไม่สำเร็จในขั้นตอน QUIC/TLS

สัญญา closed จะดำเนินการต่อเมื่อการเชื่อมต่อปิดตามปกติ และปฏิเสธหากการปิดนั้นเกิดขึ้นโดยไม่คาดคิด

หากเซิร์ฟเวอร์ปฏิเสธการเชื่อมต่อเนื่องจากข้อผิดพลาดเกี่ยวกับตัวบ่งชี้ของไคลเอ็นต์ (เช่น เส้นทางของ URL ไม่ถูกต้อง) จะทำให้ closed ถูกปฏิเสธ ขณะที่ ready ยังไม่ได้รับการแก้ไข

const url = 'https://example.com:4999/foo/bar';
const transport = new WebTransport(url);

// Optionally, set up functions to respond to
// the connection closing:
transport.closed.then(() => {
  console.log(`The HTTP/3 connection to ${url} closed gracefully.`);
}).catch((error) => {
  console.error(`The HTTP/3 connection to ${url} closed due to ${error}.`);
});

// Once .ready fulfills, the connection can be used.
await transport.ready;

Datagram API

เมื่อมีอินสแตนซ์ WebTransport ที่เชื่อมต่อกับเซิร์ฟเวอร์แล้ว คุณจะใช้อินสแตนซ์ดังกล่าวเพื่อรับส่งบิตข้อมูลแยกกันหรือที่เรียกว่า datagrams ได้

Getter writeable จะแสดงผล WritableStream ซึ่งเว็บไคลเอ็นต์สามารถใช้เพื่อส่งข้อมูลไปยังเซิร์ฟเวอร์ Getter readable จะแสดงผล ReadableStream ซึ่งจะช่วยให้คุณรับข้อมูลจากเซิร์ฟเวอร์ได้ การที่สตรีมทั้งสองมีความเสถียรในตัวเอง ดังนั้นจึงเป็นไปได้ว่าเซิร์ฟเวอร์จะไม่ได้รับข้อมูลที่เขียน และในทางกลับกันด้วย

สตรีมทั้ง 2 ประเภทใช้อินสแตนซ์ Uint8Array ในการโอนข้อมูล

// Send two datagrams to the server.
const writer = transport.datagrams.writable.getWriter();
const data1 = new Uint8Array([65, 66, 67]);
const data2 = new Uint8Array([68, 69, 70]);
writer.write(data1);
writer.write(data2);

// Read datagrams from the server.
const reader = transport.datagrams.readable.getReader();
while (true) {
  const {value, done} = await reader.read();
  if (done) {
    break;
  }
  // value is a Uint8Array.
  console.log(value);
}

API ของสตรีม

เมื่อเชื่อมต่อเซิร์ฟเวอร์แล้ว คุณจะใช้ WebTransport เพื่อส่งและรับข้อมูลผ่าน Streams API ได้ด้วย

สตรีมทั้งหมดแต่ละรายการจะเป็น Uint8Array สตรีมเหล่านี้มีความเสถียร ซึ่งแตกต่างจาก Datagram API แต่สตรีมแต่ละรายการจะแยกเป็นอิสระ จึงไม่รับประกันการจัดลำดับข้อมูลในสตรีม

WebTransportSendStream

เว็บไคลเอ็นต์สร้าง WebTransportSendStream โดยใช้เมธอด createUnidirectionalStream() ของอินสแตนซ์ WebTransport ซึ่งแสดงผลสัญญาสำหรับ WebTransportSendStream

ใช้เมธอด close() ของ WritableStreamDefaultWriter เพื่อปิดการเชื่อมต่อ HTTP/3 ที่เกี่ยวข้อง เบราว์เซอร์จะพยายามส่งข้อมูลที่รอดำเนินการทั้งหมดก่อนที่จะปิดการเชื่อมต่อที่เกี่ยวข้องจริง

// Send two Uint8Arrays to the server.
const stream = await transport.createUnidirectionalStream();
const writer = stream.writable.getWriter();
const data1 = new Uint8Array([65, 66, 67]);
const data2 = new Uint8Array([68, 69, 70]);
writer.write(data1);
writer.write(data2);
try {
  await writer.close();
  console.log('All data has been sent.');
} catch (error) {
  console.error(`An error occurred: ${error}`);
}

ในทํานองเดียวกัน ให้ใช้เมธอด abort() ของ WritableStreamDefaultWriter เพื่อส่ง RESET\_STREAM ไปยังเซิร์ฟเวอร์ เมื่อใช้ abort() เบราว์เซอร์อาจทิ้งข้อมูลที่รอดำเนินการที่ยังไม่ได้ส่ง

const ws = await transport.createUnidirectionalStream();
const writer = ws.getWriter();
writer.write(...);
writer.write(...);
await writer.abort();
// Not all the data may have been written.

WebTransportReceiveStream

เซิร์ฟเวอร์จะเป็นผู้เริ่มการทำงาน WebTransportReceiveStream การรับ WebTransportReceiveStream เป็นกระบวนการแบบ 2 ขั้นตอนสำหรับเว็บไคลเอ็นต์ ประการแรก แท็กจะเรียกแอตทริบิวต์ incomingUnidirectionalStreams ของอินสแตนซ์ WebTransport ซึ่งแสดงผล ReadableStream ส่วน ReadableStream แต่ละส่วนจะเป็น WebTransportReceiveStream ที่ใช้อ่านอินสแตนซ์ Uint8Array รายการที่เซิร์ฟเวอร์ส่งได้

async function readFrom(receiveStream) {
  const reader = receiveStream.readable.getReader();
  while (true) {
    const {done, value} = await reader.read();
    if (done) {
      break;
    }
    // value is a Uint8Array
    console.log(value);
  }
}

const rs = transport.incomingUnidirectionalStreams;
const reader = rs.getReader();
while (true) {
  const {done, value} = await reader.read();
  if (done) {
    break;
  }
  // value is an instance of WebTransportReceiveStream
  await readFrom(value);
}

คุณสามารถตรวจหาการปิดสตรีมโดยใช้คำมั่นสัญญา closed ของ ReadableStreamDefaultReader เมื่อการเชื่อมต่อ HTTP/3 ที่สำคัญปิดด้วยบิต FIN อยู่ สัญญา closed จะบรรลุผลหลังจากอ่านข้อมูลทั้งหมดแล้ว เมื่อปิดการเชื่อมต่อ HTTP/3 อย่างกะทันหัน (เช่น โดย RESET\_STREAM) สัญญา closed จะปฏิเสธ

// Assume an active receiveStream
const reader = receiveStream.readable.getReader();
reader.closed.then(() => {
  console.log('The receiveStream closed gracefully.');
}).catch(() => {
  console.error('The receiveStream closed abruptly.');
});

WebTransportBidirectionalStream

WebTransportBidirectionalStream อาจสร้างขึ้นโดยเซิร์ฟเวอร์หรือไคลเอ็นต์

เว็บไคลเอ็นต์สามารถสร้างได้โดยใช้เมธอด createBidirectionalStream() ของอินสแตนซ์ WebTransport ซึ่งจะแสดงผลสัญญาสำหรับ WebTransportBidirectionalStream

const stream = await transport.createBidirectionalStream();
// stream is a WebTransportBidirectionalStream
// stream.readable is a ReadableStream
// stream.writable is a WritableStream

คุณสามารถฟัง WebTransportBidirectionalStream ที่เซิร์ฟเวอร์สร้างขึ้นด้วยแอตทริบิวต์ incomingBidirectionalStreams ของอินสแตนซ์ WebTransport ซึ่งแสดงผล ReadableStream แต่ละส่วนของ ReadableStream จะกลายเป็น WebTransportBidirectionalStream

const rs = transport.incomingBidirectionalStreams;
const reader = rs.getReader();
while (true) {
  const {done, value} = await reader.read();
  if (done) {
    break;
  }
  // value is a WebTransportBidirectionalStream
  // value.readable is a ReadableStream
  // value.writable is a WritableStream
}

WebTransportBidirectionalStream เป็นเพียงชุดค่าผสมของ WebTransportSendStream และ WebTransportReceiveStream ตัวอย่างจาก 2 ส่วนก่อนหน้านี้จะอธิบายวิธีใช้แต่ละหัวข้อ

ตัวอย่างอื่นๆ

ข้อกำหนดฉบับร่างของ WebTransport มีตัวอย่างแบบอินไลน์เพิ่มเติมอีกจำนวนหนึ่ง พร้อมเอกสารฉบับเต็มสำหรับเมธอดและพร็อพเพอร์ตี้ทั้งหมด

WebTransport ในเครื่องมือสำหรับนักพัฒนาเว็บของ Chrome

ขออภัย เครื่องมือสำหรับนักพัฒนาเว็บของ Chrome ยังไม่รองรับ WebTransport คุณสามารถ "ติดดาว" ปัญหา Chrome นี้เพื่อรับการแจ้งเตือนเกี่ยวกับการอัปเดตในอินเทอร์เฟซเครื่องมือสำหรับนักพัฒนาเว็บ

ใยโพลีเอสเตอร์

Polyfill (หรือ Polyfill ที่มีฟังก์ชันเป็นโมดูลแบบสแตนด์อโลนซึ่งคุณนำมาใช้ได้) ที่เรียกว่า webtransport-ponyfill-websocket ซึ่งใช้ฟีเจอร์บางอย่างของ WebTransport มีให้บริการ อ่านข้อจำกัดใน README ของโปรเจ็กต์อย่างละเอียดเพื่อดูว่าโซลูชันนี้เหมาะกับ Use Case ของคุณไหม

ข้อควรพิจารณาเกี่ยวกับความเป็นส่วนตัวและความปลอดภัย

โปรดดูส่วนที่เกี่ยวข้องของข้อกำหนดฉบับร่างสำหรับคำแนะนำที่เชื่อถือได้

ความคิดเห็น

ทีม Chrome ต้องการทราบความคิดเห็นและประสบการณ์การใช้งาน API นี้ของคุณ

ความคิดเห็นเกี่ยวกับการออกแบบ API

มีบางอย่างเกี่ยวกับ API ที่ผิดปกติหรือไม่ทำงานตามที่คาดไว้ไหม หรือมีส่วนที่ขาดหายไปที่คุณจำเป็นต้องใช้กับแนวคิดของคุณไหม

รายงานปัญหาในที่เก็บ GitHub สำหรับ Web Transport หรือแสดงความคิดเห็นเกี่ยวกับปัญหาที่มีอยู่

พบปัญหาในการติดตั้งใช้งานใช่ไหม

คุณพบข้อบกพร่องในการใช้งาน Chrome หรือไม่

รายงานข้อบกพร่องที่ https://new.crbug.com โดยระบุรายละเอียดให้มากที่สุดพร้อมวิธีการง่ายๆ ในการสร้างซ้ำ

หากวางแผนจะใช้ API

การสนับสนุนแบบสาธารณะของคุณช่วยให้ Chrome จัดลำดับความสำคัญของฟีเจอร์ และแสดงให้ผู้ให้บริการเบราว์เซอร์อื่นๆ เห็นว่าการสนับสนุนฟีเจอร์ดังกล่าวสำคัญเพียงใด

  • ส่งทวีตไปที่ @ChromiumDev โดยใช้แฮชแท็ก #WebTransport รวมถึงรายละเอียดเกี่ยวกับตำแหน่งและวิธีการใช้งานของคุณ

การสนทนาทั่วไป

คุณใช้ Google Group สำหรับนักพัฒนาซอฟต์แวร์ Web-transport-dev เพื่อดูคำถามทั่วไปหรือปัญหาที่แสดงไม่ตรงกับหมวดหมู่อื่นๆ ได้

ข้อความแสดงการยอมรับ

บทความนี้ประกอบด้วยข้อมูลจาก WebTransport Explainer, ข้อกำหนดฉบับร่าง และเอกสารการออกแบบที่เกี่ยวข้อง ขอขอบคุณผู้แต่งรายนั้นๆ ที่ให้รากฐานดังกล่าว

รูปภาพหลักของโพสต์นี้เขียนโดย Robin Pierre ใน Unsplash