การใช้ฟังก์ชัน Serverless Node.js โดยใช้ Google Cloud

เผยแพร่แล้ว: 2022-03-11

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

คุณอาจกำลังคิดว่าคุณมีคลาวด์คอมพิวติ้งเพื่อดูแลสิ่งเหล่านี้อย่างไร “แล้วสิ่งที่ ไร้เซิร์ฟเวอร์ ใหม่นี้คืออะไร Vignes?”

ฟังก์ชัน Node.js แบบไร้เซิร์ฟเวอร์โดยใช้ Google Cloud

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

เมื่อใช้แบบไร้เซิร์ฟเวอร์ สิ่งต่อไปนี้จะเป็นรูปแบบการทำงานของคุณ:

  1. พัฒนารหัส

  2. อัปโหลดรหัสไปยังผู้ให้บริการ

  3. กำหนดค่าทริกเกอร์ (คำขอ 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 มีการใช้งานที่เป็นไปได้สามแบบแยกจากกันตามทริกเกอร์

  1. ทริกเกอร์ HTTP กำหนดเส้นทางคำขอ HTTP ไปยังฟังก์ชันคลาวด์

  2. ทริกเกอร์ผับ/ย่อยของ Google เผยแพร่เส้นทางและคำขอสมัครรับข้อมูลฟังก์ชันคลาวด์

  3. ทริกเกอร์ที่เก็บข้อมูลบนคลาวด์ กำหนดเส้นทางการเปลี่ยนแปลงใดๆ ที่ทำกับที่เก็บข้อมูลที่เก็บข้อมูลไปยังฟังก์ชันคลาวด์

มาสร้างการตั้งค่าตามทริกเกอร์ HTTP โดยใช้ Google Cloud Functions

Google Cloud Functions ไม่ต้องการการตั้งค่าหรือการติดตั้งพิเศษใดๆ เพิ่มเติม GCF ช่วยให้แน่ใจว่าสภาพแวดล้อมโหนดเริ่มต้นได้รับการตั้งค่าและพร้อมสำหรับการดำเนินการ เมื่อมีการสร้างฟังก์ชันระบบคลาวด์โดยใช้ HTTP เป็นตัวกระตุ้น จะมี URL เพื่อทริกเกอร์ฟังก์ชัน เมื่อเปรียบเทียบกับ AWS Lambda ซึ่งใช้เกตเวย์ API เป็นสื่อกลางในการสื่อสารด้วย Google Cloud Functions จะจัดเตรียม URL ตาม projectID และภูมิภาคทันที

ไดอะแกรมของแพลตฟอร์ม Google Cloud - ฟังก์ชันระบบคลาวด์ & AWS Lambda

การสร้างแอปพลิเคชัน Node.js แบบไร้เซิร์ฟเวอร์

ในการทำให้โค้ดของเราสามารถเรียกใช้งานได้ใน GCF เราควรใส่โค้ดไว้ในฟังก์ชันเดียว GCF จะเรียกใช้ฟังก์ชันนั้นเมื่อไรก็ตามที่ทริกเกอร์เกิดขึ้น วิธีที่เป็นไปได้ในการทำเช่นนี้คือการอัปโหลด

  1. ไฟล์เดียว: ส่งออกฟังก์ชันเริ่มต้นที่จะเรียกใช้ฟังก์ชันอื่นตามคำขอ

  2. หลายไฟล์: มีไฟล์ index.js ที่ต้องการไฟล์อื่นๆ ทั้งหมด และส่งออกฟังก์ชันเริ่มต้นเป็นจุดเริ่มต้น

  3. หลายไฟล์: กำหนดค่าไฟล์หลักหนึ่งไฟล์ใน package.json โดยใช้ "main": "main.js" เป็นจุดเริ่มต้น

วิธีใดวิธีหนึ่งข้างต้นจะได้ผล

GCF รองรับเวอร์ชันรันไทม์ของโหนดเฉพาะ ตรวจสอบให้แน่ใจว่าได้เขียนโค้ดเพื่อรองรับเวอร์ชันนั้นโดยเฉพาะ ในขณะที่สร้างโพสต์นี้ GCF รองรับโหนดเวอร์ชัน v6.11.1

ในการสร้างฟังก์ชัน มีตัวเลือกน้อยที่ต้องพิจารณา

  1. หน่วยความจำ คำสั่งนี้บอกจำนวนหน่วยความจำที่จำเป็นในการประมวลผลคำขอสำหรับรันไทม์ครั้งเดียว กำหนดเป็น MB สำหรับแอปพลิเคชันขนาดเล็ก 128MB น่าจะเพียงพอ แต่สามารถเพิ่มได้ถึง 2GB

  2. การ หมดเวลา การหมดเวลา ตามชื่อหมายถึง การหมดเวลาการเรียกใช้โค้ดที่คาดไว้ หลังจากนี้ รหัสจะถูกฆ่าและหยุดทำงาน การดำเนินการใดๆ หลังจากจุดนี้จะหยุดกะทันหัน หมดเวลาสูงสุดคือ 540 วินาที

  3. ฟังก์ชันที่จะดำเนินการ แม้ว่าจะสามารถส่งออกฟังก์ชันได้มากกว่าหนึ่งฟังก์ชันจากไฟล์ตัวจัดการหลัก แต่เราจำเป็นต้องกำหนดค่าฟังก์ชันหนึ่งฟังก์ชันที่ควรทริกเกอร์สำหรับการประมวลผลคำขอ ซึ่งช่วยให้นักพัฒนามีจุดเข้าใช้งานหลายจุดตามวิธี 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