นอกเหนือจากเบราว์เซอร์: การเริ่มต้นใช้งาน WebAssembly แบบไร้เซิร์ฟเวอร์

เผยแพร่แล้ว: 2022-03-10
สรุปอย่างรวดเร็ว ↬ คุณอาจเคยได้ยินเกี่ยวกับ WebAssembly และเหตุใดจึงเป็นเครื่องมือที่มีประสิทธิภาพในเบราว์เซอร์ ในบทความนี้ เราจะสำรวจว่าเหตุใด WebAssembly แบบไร้เซิร์ฟเวอร์จึงอาจมีประสิทธิภาพเท่าเทียมกันนอกเบราว์เซอร์ และวิธีการเริ่มต้นใช้งาน

ขณะนี้ WebAssembly ได้รับการสนับสนุนโดยเบราว์เซอร์หลักทั้งหมดและมากกว่า 85% ของผู้ใช้ทั่วโลก JavaScript จึงไม่ใช่ภาษาเบราว์เซอร์เพียงภาษาเดียวในเมืองอีกต่อไป หากคุณไม่เคยได้ยินมาก่อน WebAssembly คือภาษาระดับต่ำแบบใหม่ที่ทำงานในเบราว์เซอร์ นอกจากนี้ยังเป็นเป้าหมายการรวบรวม ซึ่งหมายความว่าคุณสามารถคอมไพล์โปรแกรมที่มีอยู่ซึ่งเขียนด้วยภาษาต่างๆ เช่น C, C++ และ Rust ลงใน WebAssembly และเรียกใช้โปรแกรมเหล่านั้นในเบราว์เซอร์ได้ จนถึงตอนนี้ WebAssembly ถูกใช้เพื่อพอร์ตแอปพลิเคชันทุกประเภทไปยังเว็บ รวมถึงแอปพลิเคชันเดสก์ท็อป เครื่องมือบรรทัดคำสั่ง เกม และเครื่องมือวิทยาศาสตร์ข้อมูล

หมายเหตุ: สำหรับกรณีศึกษาเชิงลึกเกี่ยวกับวิธีใช้ WebAssembly ภายในเบราว์เซอร์เพื่อเพิ่มความเร็วเว็บแอปพลิเคชัน โปรดดูบทความก่อนหน้าของฉัน

WebAssembly นอกเว็บ?

แม้ว่าแอปพลิเคชัน WebAssembly ส่วนใหญ่ในปัจจุบันจะเน้นไปที่เบราว์เซอร์เป็นหลัก แต่เดิม WebAssembly ไม่ได้ออกแบบมาสำหรับเว็บเท่านั้น แต่จริงๆ แล้วสำหรับสภาพแวดล้อมแบบแซนด์บ็อกซ์ใดๆ อันที่จริง เมื่อเร็ว ๆ นี้ มีความสนใจมากมายในการสำรวจว่า WebAssembly จะมีประโยชน์ นอก เบราว์เซอร์ได้อย่างไร เพื่อเป็นแนวทางทั่วไปในการรันไบนารีบนระบบปฏิบัติการหรือสถาปัตยกรรมคอมพิวเตอร์ใดๆ ตราบใดที่มีรันไทม์ WebAssembly ที่รองรับระบบนั้น ในบทความนี้ เราจะมาดูกันว่า WebAssembly สามารถทำงานนอกเบราว์เซอร์ได้อย่างไร ในแบบไร้เซิร์ฟเวอร์/Function-as-a-Service (FaaS)

เพิ่มเติมหลังกระโดด! อ่านต่อด้านล่าง↓

WebAssembly สำหรับแอพพลิเคชันไร้เซิร์ฟเวอร์

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

แม้ว่าฟังก์ชันเหล่านี้มักจะเขียนด้วยภาษาต่างๆ เช่น Python และ JavaScript (Node.js) แต่ก็มีสาเหตุหลายประการที่คุณอาจเลือกใช้ WebAssembly แทน:

  1. เวลาเริ่มต้นที่เร็วขึ้น
    ผู้ให้บริการแบบไร้เซิร์ฟเวอร์ที่รองรับ WebAssembly (รวมถึง Cloudflare และ Fastly รายงานว่าสามารถเรียกใช้ฟังก์ชันได้เร็วกว่าลำดับความสำคัญที่ผู้ให้บริการคลาวด์ส่วนใหญ่สามารถทำได้ด้วยภาษาอื่น ๆ พวกเขาทำได้โดยเรียกใช้โมดูล WebAssembly หลายหมื่นตัวในกระบวนการเดียวกัน ซึ่งก็คือ เป็นไปได้เนื่องจากลักษณะแบบแซนด์บ็อกซ์ของ WebAssembly ทำให้วิธีการแยกคอนเทนเนอร์แบบเดิมมีประสิทธิภาพมากขึ้น
  2. ไม่จำเป็นต้องเขียนซ้ำ
    สิ่งหนึ่งที่ดึงดูดใจหลักของ WebAssembly ในเบราว์เซอร์คือความสามารถในการพอร์ตโค้ดที่มีอยู่ไปยังเว็บโดยไม่ต้องเขียนใหม่ทั้งหมดไปยัง JavaScript ประโยชน์นี้ยังคงเป็นจริงในกรณีการใช้งานแบบไร้เซิร์ฟเวอร์ เนื่องจากผู้ให้บริการระบบคลาวด์จำกัดภาษาที่คุณสามารถเขียนฟังก์ชันแบบไร้เซิร์ฟเวอร์ได้ โดยทั่วไป พวกเขาจะรองรับ Python, Node.js และบางภาษาอื่นๆ อีกสองสามภาษา แต่ไม่ใช่ C, C++ หรือ Rust อย่างแน่นอน . ด้วยการสนับสนุน WebAssembly ผู้ให้บริการแบบไร้เซิร์ฟเวอร์สามารถรองรับภาษาต่างๆ ได้มากขึ้นโดยอ้อม
  3. เบากว่า
    เมื่อเรียกใช้ WebAssembly ในเบราว์เซอร์ เราใช้คอมพิวเตอร์ของผู้ใช้ปลายทางในการคำนวณของเรา หากการคำนวณนั้นเข้มข้นเกินไป ผู้ใช้ของเราจะไม่พอใจเมื่อพัดลมคอมพิวเตอร์เริ่มส่งเสียงหวีด การเรียกใช้ WebAssembly นอกเบราว์เซอร์ทำให้เราได้รับประโยชน์ด้านความเร็วและความสามารถในการพกพาของ WebAssembly ในขณะเดียวกันก็ทำให้แอปพลิเคชันของเรามีน้ำหนักเบา ยิ่งไปกว่านั้น เนื่องจากเรากำลังรันโค้ด WebAssembly ในสภาพแวดล้อมที่คาดเดาได้ เราจึงสามารถดำเนินการคำนวณที่เข้มข้นขึ้นได้

ตัวอย่างคอนกรีต

ในบทความก่อนหน้าของฉันใน Smashing Magazine เราได้พูดถึงวิธีที่เราเพิ่มความเร็วเว็บแอปพลิเคชันโดยแทนที่การคำนวณ JavaScript ที่ช้าด้วยโค้ด C ที่คอมไพล์เป็น WebAssembly เว็บแอปที่เป็นปัญหาคือ fastq.bio ซึ่งเป็นเครื่องมือสำหรับแสดงตัวอย่างคุณภาพของข้อมูลการจัดลำดับ DNA

เป็นตัวอย่างที่เป็นรูปธรรม เรามาเขียน fastq.bio ใหม่เป็นแอปพลิเคชันที่ใช้ WebAssembly แบบไร้เซิร์ฟเวอร์แทนการเรียกใช้ WebAssembly ภายในเบราว์เซอร์ สำหรับบทความนี้ เราจะใช้ Cloudflare Workers ผู้ให้บริการแบบไร้เซิร์ฟเวอร์ที่รองรับ WebAssembly และสร้างขึ้นจากกลไกเบราว์เซอร์ V8 Fastly ผู้ให้บริการคลาวด์รายอื่นกำลังทำงานในข้อเสนอที่คล้ายกัน แต่อิงตามรันไทม์ของ Lucet

ขั้นแรก มาเขียนโค้ด Rust เพื่อวิเคราะห์คุณภาพข้อมูลของข้อมูลการจัดลำดับ DNA เพื่อความสะดวก เราสามารถใช้ประโยชน์จากห้องสมุดชีวสารสนเทศของ Rust-Bio เพื่อจัดการการแยกวิเคราะห์ข้อมูลที่ป้อนเข้า และไลบรารี wasm-bindgen เพื่อช่วยเรารวบรวมโค้ด Rust ของเราไปยัง WebAssembly

นี่คือตัวอย่างโค้ดที่อ่านในข้อมูลการจัดลำดับดีเอ็นเอและส่งออก JSON พร้อมสรุปเมตริกคุณภาพ:

 // Import packages extern crate wasm_bindgen; use bio::seq_analysis::gc; use bio::io::fastq; ... // This "wasm_bindgen" tag lets us denote the functions // we want to expose in our WebAssembly module #[wasm_bindgen] pub fn fastq_metrics(seq: String) -> String { ... // Loop through lines in the file let reader = fastq::Reader::new(seq.as_bytes()); for result in reader.records() { let record = result.unwrap(); let sequence = record.seq(); // Calculate simple statistics on each record n_reads += 1.0; let read_length = sequence.len(); let read_gc = gc::gc_content(sequence); // We want to draw histograms of these values // so we store their values for later plotting hist_gc.push(read_gc * 100.0); hist_len.push(read_length); ... } // Return statistics as a JSON blob json!({ "n": n_reads, "hist": { "gc": hist_gc, "len": hist_len }, ... }).to_string() }

จากนั้นเราใช้เครื่องมือบรรทัดคำสั่ง wrangler ของ Cloudflare เพื่อทำการคอมไพล์ไปยัง WebAssembly และปรับใช้กับคลาวด์อย่างหนัก เมื่อเสร็จแล้ว เราได้รับปลายทาง API ที่รับข้อมูลการจัดลำดับเป็นอินพุตและส่งคืน JSON พร้อมตัววัดคุณภาพข้อมูล ตอนนี้เราสามารถรวม API นั้นเข้ากับแอปพลิเคชันของเราได้แล้ว

นี่คือ GIF ของแอปพลิเคชันที่ใช้งานจริง:

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

รหัสเต็มมีอยู่ใน GitHub (โอเพ่นซอร์ส)

ใส่ทุกอย่างในบริบท

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

รูปนี้แสดงสี่วิธีที่เราสามารถจัดโครงสร้างการประมวลผลข้อมูลในเว็บแอป: บนเซิร์ฟเวอร์ (ไม่มี WebAssembly) ในเบราว์เซอร์โดยใช้ JavaScript ในเบราว์เซอร์โดยใช้ WebAssembly และ WebAssembly แบบไร้เซิร์ฟเวอร์
ตัวเลือกสถาปัตยกรรมที่แตกต่างกันสี่แบบที่เราสามารถทำได้สำหรับแอปที่ประมวลผลข้อมูล (ตัวอย่างขนาดใหญ่)

ดังที่แสดงไว้ข้างต้น การประมวลผลข้อมูลสามารถทำได้ในหลายที่:

  1. ฝั่งเซิร์ฟเวอร์
    นี่คือแนวทางปฏิบัติของเว็บแอปพลิเคชันส่วนใหญ่ โดยที่การเรียก API ดำเนินการในการประมวลผลข้อมูลการเปิดใช้ส่วนหน้าบนส่วนหลัง
  2. JavaScript ฝั่งไคลเอ็นต์
    ในแนวทางนี้ โค้ดประมวลผลข้อมูลเขียนด้วย JavaScript และทำงานในเบราว์เซอร์ ข้อเสียคือประสิทธิภาพของคุณจะถูกโจมตี และหากโค้ดต้นฉบับของคุณไม่อยู่ใน JavaScript คุณจะต้องเขียนใหม่ตั้งแต่ต้น!
  3. WebAssembly ฝั่งไคลเอ็นต์
    ซึ่งเกี่ยวข้องกับการรวบรวมโค้ดการวิเคราะห์ข้อมูลไปยัง WebAssembly และเรียกใช้ในเบราว์เซอร์ หากโค้ดการวิเคราะห์เขียนขึ้นในภาษาเช่น C, C++ หรือ Rust (ซึ่งมักจะเป็นกรณีในด้านจีโนมของฉัน) สิ่งนี้จะขจัดความจำเป็นในการเขียนอัลกอริธึมที่ซับซ้อนใน JavaScript ใหม่ นอกจากนี้ยังให้ศักยภาพในการเร่งความเร็วของแอปพลิเคชันของเรา (เช่นตามที่กล่าวไว้ในบทความก่อนหน้านี้)
  4. WebAssembly แบบไร้เซิร์ฟเวอร์
    สิ่งนี้เกี่ยวข้องกับการรัน WebAssembly ที่คอมไพล์บนคลาวด์ โดยใช้แบบจำลองประเภท FaaS (เช่น บทความนี้)

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

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

บทสรุป

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