การใช้ฟังก์ชัน Serverless Node.js โดยใช้ Google Cloud
เผยแพร่แล้ว: 2022-03-11การสร้างซอฟต์แวร์ไม่ได้จบลงด้วยการเขียนโค้ดที่ดี จะเสร็จสมบูรณ์เมื่อมีการปรับใช้ซอฟต์แวร์และสามารถจัดการคำขอได้อย่างเหมาะสม และเมื่อเราสามารถปรับขนาดได้โดยไม่ขัดขวางประสิทธิภาพและค่าใช้จ่ายในการเรียกใช้
คุณอาจกำลังคิดว่าคุณมีคลาวด์คอมพิวติ้งเพื่อดูแลสิ่งเหล่านี้อย่างไร “แล้วสิ่งที่ ไร้เซิร์ฟเวอร์ ใหม่นี้คืออะไร Vignes?”
การประมวลผลแบบไร้เซิร์ฟเวอร์เป็นรูปแบบสถาปัตยกรรมที่โค้ดทำงานบนแพลตฟอร์มคลาวด์ โดยที่เราไม่ต้องกังวลเกี่ยวกับการตั้งค่าฮาร์ดแวร์และซอฟต์แวร์ ความปลอดภัย ประสิทธิภาพ และต้นทุนเวลาที่ไม่ได้ใช้งานของ CPU เป็นความก้าวหน้าของคลาวด์คอมพิวติ้งที่ก้าวไปไกลกว่าโครงสร้างพื้นฐานที่ทำให้สภาพแวดล้อมซอฟต์แวร์เป็นนามธรรมเช่นกัน หมายความว่าไม่จำเป็นต้องมีการกำหนดค่าเพื่อเรียกใช้โค้ด
เมื่อใช้แบบไร้เซิร์ฟเวอร์ สิ่งต่อไปนี้จะเป็นรูปแบบการทำงานของคุณ:
พัฒนารหัส
อัปโหลดรหัสไปยังผู้ให้บริการ
กำหนดค่าทริกเกอร์ (คำขอ HTTP ในกรณีของเรา)
งานของเราเสร็จแล้ว! ตอนนี้ผู้ให้บริการแพลตฟอร์มจะดูแลคำขอที่เข้ามาและการปรับขนาด
บทนำสู่ไมโครเซอร์วิสแบบไร้เซิร์ฟเวอร์
สถาปัตยกรรมแบบไร้เซิร์ฟเวอร์มักใช้ร่วมกับการออกแบบสไตล์ไมโครเซอร์วิส ไมโครเซอร์วิสเป็นส่วนสแตนด์อโลนของซอฟต์แวร์ขนาดใหญ่ที่จัดการคำขอสำหรับโมดูลเฉพาะ ด้วยการสร้างไมโครเซอร์วิสที่สามารถทำงานได้ในสภาพแวดล้อมแบบไร้เซิร์ฟเวอร์ ทำให้ง่ายต่อการบำรุงรักษาโค้ดและเร่งความเร็วในการปรับใช้
บทนำสู่ AWS Lambda & GCF การเปรียบเทียบ
คุณลักษณะแบบไร้เซิร์ฟเวอร์มักเรียกว่า "ส่วนหลังเป็นบริการ" หรือ "ทำหน้าที่เป็นบริการ" จำนวนผู้ให้บริการประมวลผลแบบไร้เซิร์ฟเวอร์เริ่มเพิ่มขึ้น อย่างไรก็ตาม ผู้เล่นรายใหญ่บางรายยังมีตัวเลือกแบบไร้เซิร์ฟเวอร์ เช่น AWS Lambda Functions ของ Amazon Web Services และ Google Cloud Functions (GCF) ของ Google Cloud ซึ่งฉันใช้อย่างหลังในขณะที่อยู่ในเวอร์ชันเบต้า แม้ว่าพวกเขาจะทำงานคล้ายกัน แต่ก็มีความแตกต่างที่สำคัญเล็กน้อยระหว่างพวกเขา
AWS Lambda | ฟังก์ชั่น Google Cloud | |
---|---|---|
รองรับภาษา | Node.js, Python, C#, Java | Node.js |
ทริกเกอร์ | DynamoDB, Kinesis, S3, SNS, API เกตเวย์ (HTTP), CloudFront และอื่นๆ | HTTP, Cloud PubSub, ที่เก็บข้อมูลบนคลาวด์ |
เวลาดำเนินการสูงสุด | 300 วินาที | 540 วินาที |
ในบทความนี้ เราจะพูดถึงกระบวนการปรับใช้โค้ดแบบไร้เซิร์ฟเวอร์โดยใช้ GCF Google Cloud Functions เป็นโซลูชันการประมวลผลแบบอะซิงโครนัสขนาดเล็กที่อิงตามเหตุการณ์ ซึ่งช่วยให้คุณสามารถสร้างฟังก์ชันขนาดเล็กวัตถุประสงค์เดียวที่ตอบสนองต่อเหตุการณ์บนระบบคลาวด์โดยไม่จำเป็นต้องจัดการเซิร์ฟเวอร์หรือสภาพแวดล้อมรันไทม์
GCF มีการใช้งานที่เป็นไปได้สามแบบแยกจากกันตามทริกเกอร์
ทริกเกอร์ HTTP กำหนดเส้นทางคำขอ HTTP ไปยังฟังก์ชันคลาวด์
ทริกเกอร์ผับ/ย่อยของ Google เผยแพร่เส้นทางและคำขอสมัครรับข้อมูลฟังก์ชันคลาวด์
ทริกเกอร์ที่เก็บข้อมูลบนคลาวด์ กำหนดเส้นทางการเปลี่ยนแปลงใดๆ ที่ทำกับที่เก็บข้อมูลที่เก็บข้อมูลไปยังฟังก์ชันคลาวด์
มาสร้างการตั้งค่าตามทริกเกอร์ HTTP โดยใช้ Google Cloud Functions
Google Cloud Functions ไม่ต้องการการตั้งค่าหรือการติดตั้งพิเศษใดๆ เพิ่มเติม GCF ช่วยให้แน่ใจว่าสภาพแวดล้อมโหนดเริ่มต้นได้รับการตั้งค่าและพร้อมสำหรับการดำเนินการ เมื่อมีการสร้างฟังก์ชันระบบคลาวด์โดยใช้ HTTP เป็นตัวกระตุ้น จะมี URL เพื่อทริกเกอร์ฟังก์ชัน เมื่อเปรียบเทียบกับ AWS Lambda ซึ่งใช้เกตเวย์ API เป็นสื่อกลางในการสื่อสารด้วย Google Cloud Functions จะจัดเตรียม URL ตาม projectID
และภูมิภาคทันที
การสร้างแอปพลิเคชัน Node.js แบบไร้เซิร์ฟเวอร์
ในการทำให้โค้ดของเราสามารถเรียกใช้งานได้ใน GCF เราควรใส่โค้ดไว้ในฟังก์ชันเดียว GCF จะเรียกใช้ฟังก์ชันนั้นเมื่อไรก็ตามที่ทริกเกอร์เกิดขึ้น วิธีที่เป็นไปได้ในการทำเช่นนี้คือการอัปโหลด
ไฟล์เดียว: ส่งออกฟังก์ชันเริ่มต้นที่จะเรียกใช้ฟังก์ชันอื่นตามคำขอ
หลายไฟล์: มีไฟล์
index.js
ที่ต้องการไฟล์อื่นๆ ทั้งหมด และส่งออกฟังก์ชันเริ่มต้นเป็นจุดเริ่มต้นหลายไฟล์: กำหนดค่าไฟล์หลักหนึ่งไฟล์ใน
package.json
โดยใช้"main": "main.js"
เป็นจุดเริ่มต้น
วิธีใดวิธีหนึ่งข้างต้นจะได้ผล
GCF รองรับเวอร์ชันรันไทม์ของโหนดเฉพาะ ตรวจสอบให้แน่ใจว่าได้เขียนโค้ดเพื่อรองรับเวอร์ชันนั้นโดยเฉพาะ ในขณะที่สร้างโพสต์นี้ GCF รองรับโหนดเวอร์ชัน v6.11.1
ในการสร้างฟังก์ชัน มีตัวเลือกน้อยที่ต้องพิจารณา
หน่วยความจำ คำสั่งนี้บอกจำนวนหน่วยความจำที่จำเป็นในการประมวลผลคำขอสำหรับรันไทม์ครั้งเดียว กำหนดเป็น MB สำหรับแอปพลิเคชันขนาดเล็ก 128MB น่าจะเพียงพอ แต่สามารถเพิ่มได้ถึง 2GB
การ หมดเวลา การหมดเวลา ตามชื่อหมายถึง การหมดเวลาการเรียกใช้โค้ดที่คาดไว้ หลังจากนี้ รหัสจะถูกฆ่าและหยุดทำงาน การดำเนินการใดๆ หลังจากจุดนี้จะหยุดกะทันหัน หมดเวลาสูงสุดคือ 540 วินาที
ฟังก์ชันที่จะดำเนินการ แม้ว่าจะสามารถส่งออกฟังก์ชันได้มากกว่าหนึ่งฟังก์ชันจากไฟล์ตัวจัดการหลัก แต่เราจำเป็นต้องกำหนดค่าฟังก์ชันหนึ่งฟังก์ชันที่ควรทริกเกอร์สำหรับการประมวลผลคำขอ ซึ่งช่วยให้นักพัฒนามีจุดเข้าใช้งานหลายจุดตามวิธี HTTP/URL
ในการอัปโหลดโค้ด เพียงแค่คัดลอกและวางโค้ดเพื่อสร้างพอร์ทัลฟังก์ชัน สำหรับไฟล์มากกว่าหนึ่งไฟล์ ให้บีบอัดเนื้อหาและอัปโหลดไฟล์ ตรวจสอบให้แน่ใจว่า ในกรณีของไฟล์ ZIP ควรมีไฟล์ index.js
หรือไฟล์ package.json
ที่มีไฟล์หลักที่กล่าวถึง
ควรกล่าวถึงการพึ่งพาโมดูล NPM ใน package.json
GCF พยายามติดตั้งโมดูลที่กล่าวถึงในไฟล์ package.json
ระหว่างการตั้งค่าครั้งแรก
ให้สร้างตัวจัดการอย่างง่ายเพื่อส่งคืนสถานะ 200 และข้อความบางส่วน สร้างฟังก์ชันและเพิ่มโค้ดต่อไปนี้ในซอร์ส
exports.httpServer = function httpServer(req, res) { console.log(req); res.status(200).send('Server is working'); }
เมื่อสร้างฟังก์ชันแล้ว ให้เปิด URL ที่ให้ไว้เพื่อทริกเกอร์ฟังก์ชัน ควรตอบสนองดังนี้
ตอนนี้ มาตรวจสอบวัตถุ req
ในบันทึกกัน หากต้องการดูบันทึก GCF จะมีตัวเลือกจากคอนโซลโดยตรง คลิกจุดแนวตั้งและเปิดตัวเลือกบันทึก
ตอนนี้ มาอัปเดตโค้ดเพื่อจัดการเส้นทางง่ายๆ สำหรับ /users
รหัสต่อไปนี้ใช้เพื่อจัดการคำขอ GET
& POST
อย่างง่ายสำหรับเส้นทาง /users
:
exports.httpServer = function httpServer(req, res) { const path = req.path; switch(path) { case '/users': handleUsers(req, res); break; default: res.status(200).send('Server is working'); } }; const handleUsers = (req, res) => { if (req.method === 'GET') { res.status(200).send('Listing users...'); } else if (req.method === 'POST') { res.status(201).send('Creating User...') } else { res.status(404); } }
หลังจากอัปเดตแล้ว เรามาทดสอบในเบราว์เซอร์กัน แต่คราวนี้ /users
ต่อท้าย
ที่เย็น เราสร้างเซิร์ฟเวอร์ HTTP พื้นฐานพร้อมการกำหนดเส้นทาง
การดำเนินงานและการดีบัก
หากโค้ดอยู่ที่จุดสิ้นสุดของเรื่องราว คุณจะไม่ต้องค้นคว้าตัวเลือกโครงสร้างพื้นฐาน เช่น แอปพลิเคชัน Node.js แบบไร้เซิร์ฟเวอร์ ต่อไปนี้คือข้อมูลสรุปโดยย่อเกี่ยวกับวิธีดูแลงานทั่วไป เช่น การปรับใช้และการดีบัก สิ่งที่นักพัฒนา Node.js ทำกับแอปพลิเคชันอื่นอยู่แล้ว
การปรับใช้:
รหัสสำหรับฟังก์ชันสามารถนำไปใช้ได้สี่วิธี
คัดลอกการวางรหัสในคอนโซล
การอัพโหลดไฟล์ ZIP
การปรับใช้จากที่เก็บข้อมูลบนคลาวด์เป็นไฟล์ ZIP
การปรับใช้จากแหล่งเก็บข้อมูลบนคลาวด์
แน่นอนว่าตัวเลือกที่สะดวกที่สุดคือการปรับใช้จากที่เก็บต้นทาง
คำขอ:
ขณะสร้างฟังก์ชัน Console จัดเตรียม HTTP URL เพื่อทริกเกอร์ฟังก์ชันซึ่งอยู่ในรูปแบบ: https://<region>-<project-id>.cloudfunctions.net/<function-name>
ฟังก์ชันของ AWS Lambda มีปัญหาการเริ่มเย็นซึ่งทำให้การเรียกใช้ฟังก์ชันต้องใช้เวลาเพิ่มเติมในการเริ่มต้น เมื่อเริ่มต้น การดำเนินการต่อไปนี้จะตอบสนองตามปกติ เวลาเริ่มต้นเพิ่มเติมในเบื้องต้นนี้เรียกว่าการเริ่มเย็น แม้ว่าเราจะไม่มีเอกสารอย่างเป็นทางการสำหรับ GCF ที่เกี่ยวข้องกับหัวข้อนี้ แต่ปัญหาการเริ่มระบบเย็นไม่ปรากฏขึ้นในระหว่างการทดสอบของเรา
การดีบัก:
GCF ผสานรวมกับบริการ Stackdriver Logging ใน Google Cloud บันทึกและข้อผิดพลาดของคอนโซลทั้งหมดจะถูกบันทึกไว้ที่นี่ และช่วยดีบักโค้ดที่ปรับใช้แล้ว
การทดสอบ:
คอนโซลมีตัวเลือกในการทดสอบฟังก์ชันโดยส่ง JSON เป็นอินพุต ฟังก์ชันนี้จะถูกเรียกโดย JSON เป็นอินพุตและเอาต์พุตจะแสดงในคอนโซล คำขอ (อินพุต) และการตอบสนองคล้ายกับเฟรมเวิร์ก Express.js และสามารถทดสอบหน่วยได้ในระหว่างกระบวนการพัฒนา หากคุณต้องการทบทวนการทดสอบ Node.js ให้ดู A Node.js Guide to really Doing Integration Tests
ข้อจำกัดและขั้นตอนต่อไป
การใช้ฟังก์ชันแบบไร้เซิร์ฟเวอร์มีข้อดีในตัวเอง และยังมีข้อจำกัดต่างๆ อีกด้วย
การล็อคอินของผู้จำหน่าย: มันจำกัดรหัสที่เราเขียนถึงผู้ให้บริการรายใดรายหนึ่งโดยเฉพาะ การย้ายรหัสไปยังผู้ให้บริการรายอื่นจำเป็นต้องเขียนรหัสใหม่ด้วยความพยายามอย่างมากในการย้ายข้อมูล เนื่องจากอาจเป็นปัญหาใหญ่ได้ เราจึงควรระมัดระวังในการเลือกผู้ให้บริการ
ข้อจำกัดของจำนวนคำขอและทรัพยากรฮาร์ดแวร์: ผู้ให้บริการมักจำกัดจำนวนคำขอแบบขนานที่ฟังก์ชันจะจัดการในแต่ละครั้ง มีข้อ จำกัด ด้านหน่วยความจำเช่นกัน ข้อจำกัดประเภทนี้สามารถเพิ่มขึ้นได้โดยการพูดคุยกับผู้ให้บริการ แต่จะยังคงมีอยู่
Google Cloud Functions กำลังเติบโตและปรับปรุงอย่างมาก ยังคงได้รับการปรับปรุงและปรับปรุงอยู่บ่อยครั้ง โดยเฉพาะอย่างยิ่งในภาษาที่สามารถรองรับได้ หากคุณกำลังวางแผนที่จะใช้ฟังก์ชัน Google Cloud ให้จับตาดูบันทึกการเปลี่ยนแปลงเพื่อหลีกเลี่ยงการเปลี่ยนแปลงที่แตกหักในการใช้งาน
อ่านเพิ่มเติมในบล็อก Toptal Engineering:
- การทำงานกับ TypeScript และ Jest Support: บทช่วยสอน AWS SAM