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

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

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