สถาปัตยกรรมเชิงบริการด้วย AWS Lambda: บทช่วยสอนทีละขั้นตอน
เผยแพร่แล้ว: 2022-03-11เมื่อสร้างเว็บแอปพลิเคชัน มีตัวเลือกมากมายที่จะสามารถช่วยหรือขัดขวางแอปพลิเคชันของคุณในอนาคตเมื่อคุณตกลงกับพวกเขา ตัวเลือกต่างๆ เช่น ภาษา เฟรมเวิร์ก โฮสติ้ง และฐานข้อมูลมีความสำคัญ
ทางเลือกหนึ่งคือจะสร้างแอปพลิเคชันตามบริการโดยใช้ Service Oriented Architecture (SOA) หรือแอปพลิเคชันแบบเสาหินแบบดั้งเดิม นี่เป็นการตัดสินใจทางสถาปัตยกรรมทั่วไปที่ส่งผลต่อสตาร์ทอัพ การขยายขนาด และบริษัทระดับองค์กร
สถาปัตยกรรมเชิงบริการถูกใช้โดยบริษัทยูนิคอร์นและบริษัทเทคโนโลยีชั้นนำจำนวนมาก เช่น Google, Facebook, Twitter, Instagram และ Uber ดูเหมือนว่ารูปแบบสถาปัตยกรรมนี้ใช้ได้กับบริษัทขนาดใหญ่ แต่จะใช้ได้กับคุณไหม
ในบทความนี้ เราจะแนะนำหัวข้อของสถาปัตยกรรมเชิงบริการ และวิธีที่สามารถใช้ AWS Lambda ร่วมกับ Python เพื่อสร้างบริการที่ปรับขนาดได้และประหยัดต้นทุนได้อย่างง่ายดาย เพื่อแสดงแนวคิดเหล่านี้ เราจะสร้างบริการอัปโหลดและปรับขนาดรูปภาพอย่างง่ายโดยใช้ Python, AWS Lambda, Amazon S3 และเครื่องมือและบริการอื่นๆ ที่เกี่ยวข้องอีกสองสามรายการ
สถาปัตยกรรมเชิงบริการคืออะไร?
สถาปัตยกรรมเชิงบริการ (SOA) ไม่ใช่เรื่องใหม่ มีรากฐานมาจากหลายทศวรรษที่ผ่านมา ในช่วงไม่กี่ปีที่ผ่านมาความนิยมในรูปแบบนี้เติบโตขึ้นเนื่องจากมีข้อดีหลายประการสำหรับแอปพลิเคชันที่เชื่อมต่อกับเว็บ
โดยพื้นฐานแล้ว SOA เป็นนามธรรมของแอปพลิเคชันขนาดใหญ่หนึ่งรายการในแอปพลิเคชันขนาดเล็กที่สื่อสารจำนวนมาก สิ่งนี้เป็นไปตามแนวทางปฏิบัติที่ดีที่สุดหลายประการของวิศวกรรมซอฟต์แวร์ เช่น การแยกการเชื่อมต่อ การแยกข้อกังวล และสถาปัตยกรรมความรับผิดชอบเดียว
การนำ SOA ไปใช้นั้นแตกต่างกันไปตามความละเอียด: ตั้งแต่บริการเพียงเล็กน้อยที่ครอบคลุมพื้นที่การทำงานขนาดใหญ่ไปจนถึงแอปพลิเคชันขนาดเล็กจำนวนมากหรือหลายร้อยรายการในสถาปัตยกรรมที่เรียกว่า "ไมโครเซอร์วิส" โดยไม่คำนึงถึงระดับของความละเอียด สิ่งที่เป็นที่ยอมรับกันโดยทั่วไปในหมู่ผู้ปฏิบัติงาน SOA ก็คือว่าไม่ใช่อาหารกลางวันฟรี เช่นเดียวกับแนวปฏิบัติที่ดีหลายประการในด้านวิศวกรรมซอฟต์แวร์ การลงทุนจะต้องมีการวางแผน การพัฒนาและการทดสอบเพิ่มเติม
AWS แลมบ์ดาคืออะไร
AWS Lambda เป็นบริการที่นำเสนอโดยแพลตฟอร์ม Amazon Web Services AWS Lambda ให้คุณอัปโหลดโค้ดที่จะรันบนคอนเทนเนอร์แบบออนดีมานด์ที่จัดการโดย Amazon AWS Lambda จะจัดการการจัดเตรียมและการจัดการเซิร์ฟเวอร์เพื่อเรียกใช้โค้ด ดังนั้นทั้งหมดที่จำเป็นจากผู้ใช้ก็คือชุดโค้ดที่รันเป็นแพ็กเกจเพื่อเรียกใช้และตัวเลือกการกำหนดค่าบางอย่างเพื่อกำหนดบริบทที่เซิร์ฟเวอร์ทำงาน แอปพลิเคชันที่มีการจัดการเหล่านี้เรียกว่าฟังก์ชันแลมบ์ดา
AWS Lambda มีโหมดการทำงานหลักสองโหมด:
อะซิงโครนัส/ขับเคลื่อนด้วยเหตุการณ์:
ฟังก์ชัน Lambda สามารถรันเพื่อตอบสนองต่อเหตุการณ์ในโหมดอะซิงโครนัส แหล่งที่มาของเหตุการณ์ใดๆ เช่น S3, SNS ฯลฯ จะไม่ถูกบล็อก และฟังก์ชัน Lambda สามารถใช้ประโยชน์จากสิ่งนี้ได้หลายวิธี เช่น การสร้างไปป์ไลน์การประมวลผลสำหรับสายของเหตุการณ์บางกลุ่ม มีแหล่งข้อมูลมากมาย และขึ้นอยู่กับว่าเหตุการณ์ต้นทางจะถูกพุชไปยังฟังก์ชัน Lambda จากแหล่งเหตุการณ์ หรือแบบสำรวจสำหรับเหตุการณ์โดย AWS Lambda
ซิงโครนัส/คำขอ->การตอบสนอง:
สำหรับแอปพลิเคชันที่ต้องการการตอบสนองเพื่อส่งคืนแบบซิงโครนัส สามารถเรียกใช้ Lambda ในโหมดซิงโครนัสได้ โดยทั่วไปจะใช้ร่วมกับบริการที่เรียกว่า API Gateway เพื่อส่งคืนการตอบสนอง HTTP จาก AWS Lambda ไปยังผู้ใช้ปลายทาง อย่างไรก็ตาม ฟังก์ชัน Lambda ยังสามารถเรียกแบบซิงโครนัสผ่านการเรียกโดยตรงไปยัง AWS Lambda
ฟังก์ชัน AWS Lambda ถูกอัปโหลดเป็นไฟล์ zip ที่มีรหัสตัวจัดการนอกเหนือจากการพึ่งพาที่จำเป็นสำหรับการทำงานของตัวจัดการ เมื่ออัปโหลดแล้ว AWS Lambda จะรันโค้ดนี้เมื่อจำเป็นและปรับขนาดจำนวนเซิร์ฟเวอร์จากศูนย์เป็นพันเมื่อจำเป็น โดยไม่ต้องมีการแทรกแซงเพิ่มเติมจากผู้บริโภค
แลมบ์ดาทำหน้าที่เป็นวิวัฒนาการของSOA
SOA พื้นฐานเป็นวิธีหนึ่งในการจัดโครงสร้างโค้ดเบสของคุณให้เป็นแอปพลิเคชันขนาดเล็ก เพื่อประโยชน์ของแอปพลิเคชันในลักษณะที่อธิบายไว้ก่อนหน้าในบทความนี้ จากสิ่งนี้ วิธีการสื่อสารระหว่างแอปพลิเคชันเหล่านี้จึงกลายเป็นจุดสนใจ SOA ที่ขับเคลื่อนด้วยเหตุการณ์ (หรือที่รู้จักว่า SOA 2.0) ไม่เพียงแต่ช่วยให้การสื่อสารแบบบริการถึงบริการโดยตรงแบบดั้งเดิมของ SOA 1.0 เท่านั้น แต่ยังรวมถึงเหตุการณ์ที่จะเผยแพร่ทั่วทั้งสถาปัตยกรรมเพื่อสื่อสารการเปลี่ยนแปลง
สถาปัตยกรรมที่ขับเคลื่อนด้วยเหตุการณ์คือรูปแบบที่ส่งเสริมการมีเพศสัมพันธ์และการจัดองค์ประกอบที่หลวม ด้วยการสร้างและตอบสนองต่อเหตุการณ์ คุณสามารถเพิ่มบริการเฉพาะกิจเพื่อเพิ่มฟังก์ชันการทำงานใหม่ให้กับเหตุการณ์ที่มีอยู่ และสามารถประกอบหลายเหตุการณ์เพื่อให้ฟังก์ชันการทำงานที่สมบูรณ์ยิ่งขึ้น
AWS Lambda สามารถใช้เป็นแพลตฟอร์มเพื่อสร้างแอปพลิเคชัน SOA 2.0 ได้อย่างง่ายดาย มีหลายวิธีในการเรียกฟังก์ชัน Lambda; ตั้งแต่วิธีคิวข้อความแบบดั้งเดิมกับ Amazon SNS ไปจนถึงกิจกรรมที่สร้างโดยไฟล์ที่อัปโหลดไปยัง Amazon S3 หรืออีเมลที่ส่งด้วย Amazon SES
การใช้บริการอัพโหลดรูปภาพอย่างง่าย
เราจะสร้างแอปพลิเคชันอย่างง่ายเพื่ออัปโหลดและเรียกข้อมูลรูปภาพโดยใช้กอง AWS โปรเจ็กต์ตัวอย่างนี้จะประกอบด้วยฟังก์ชันแลมบ์ดาสองฟังก์ชัน: ฟังก์ชันหนึ่งทำงานในโหมดคำขอ -> ตอบกลับที่จะใช้เพื่อให้บริการส่วนหน้าของเว็บอย่างง่ายของเรา และอีกฟังก์ชันหนึ่งจะตรวจจับภาพที่อัปโหลดและปรับขนาด
ฟังก์ชันแลมบ์ดาแรกจะทำงานแบบอะซิงโครนัสเพื่อตอบสนองต่อเหตุการณ์การอัปโหลดไฟล์ที่ทริกเกอร์บนบัคเก็ต S3 ซึ่งจะเก็บรูปภาพที่อัปโหลดไว้ ระบบจะนำรูปภาพที่ให้มาและปรับขนาดให้พอดีกับรูปภาพขนาด 400x400
ฟังก์ชันแลมบ์ดาอื่นๆ จะให้บริการหน้า HTML โดยให้ทั้งฟังก์ชันสำหรับผู้ใช้ในการดูภาพที่ปรับขนาดโดยฟังก์ชันอื่นๆ ของแลมบ์ดา เช่นเดียวกับอินเทอร์เฟซสำหรับการอัปโหลดภาพ
การกำหนดค่า AWS เริ่มต้น
ก่อนที่เราจะเริ่มต้นได้ เราจะต้องกำหนดค่าบริการของ AWS ที่จำเป็นบางอย่าง เช่น IAM และ S3 สิ่งเหล่านี้จะได้รับการกำหนดค่าโดยใช้คอนโซล AWS บนเว็บ อย่างไรก็ตาม การกำหนดค่าส่วนใหญ่สามารถทำได้โดยใช้ยูทิลิตี้บรรทัดคำสั่งของ AWS ซึ่งเราจะใช้ในภายหลัง
การสร้าง S3 Buckets
S3 (หรือ Simple Storage Service) คือบริการจัดเก็บอ็อบเจ็กต์ของ Amazon ที่ให้พื้นที่จัดเก็บข้อมูลที่เชื่อถือได้และประหยัดต้นทุน เราจะใช้ S3 เพื่อจัดเก็บรูปภาพที่จะอัปโหลด เช่นเดียวกับเวอร์ชันปรับขนาดของรูปภาพที่เราประมวลผล
บริการ S3 สามารถพบได้ในเมนูแบบเลื่อนลง "บริการ" ในคอนโซล AWS ใต้ส่วนย่อย "การจัดเก็บและการจัดส่งเนื้อหา" เมื่อสร้างที่เก็บข้อมูล คุณจะได้รับแจ้งให้ป้อนทั้งชื่อที่เก็บข้อมูลและเลือกภูมิภาค การเลือกภูมิภาคที่ใกล้กับผู้ใช้ของคุณจะทำให้ S3 เพิ่มประสิทธิภาพสำหรับเวลาแฝงและค่าใช้จ่าย รวมถึงปัจจัยด้านกฎระเบียบบางประการ สำหรับตัวอย่างนี้ เราจะเลือกภูมิภาค “มาตรฐานของสหรัฐอเมริกา” ภูมิภาคเดียวกันนี้จะใช้สำหรับการโฮสต์ฟังก์ชัน AWS Lambda ในภายหลัง
เป็นที่น่าสังเกตว่าชื่อบัคเก็ต S3 จะต้องไม่ซ้ำกัน ดังนั้นหากชื่อที่เลือกถูกใช้ คุณจะต้องเลือกชื่อใหม่ที่ไม่ซ้ำ
สำหรับโปรเจ็กต์ตัวอย่างนี้ เราจะสร้างที่เก็บข้อมูลสองที่เก็บข้อมูลชื่อ “test-upload” และ “test-resized” บัคเก็ต "ทดสอบ-อัปโหลด" จะใช้สำหรับการอัปโหลดรูปภาพและจัดเก็บรูปภาพที่อัปโหลดก่อนที่จะประมวลผลและปรับขนาด เมื่อปรับขนาดแล้ว รูปภาพจะถูกบันทึกลงในบัคเก็ต "ขนาดทดสอบ" และนำรูปภาพที่อัปโหลดดิบออก
สิทธิ์ในการอัปโหลด S3
ตามค่าเริ่มต้น สิทธิ์ของ S3 จะจำกัด และจะไม่อนุญาตให้ผู้ใช้ภายนอกหรือแม้แต่ผู้ใช้ที่ไม่ใช่ผู้ดูแลระบบสามารถอ่าน เขียน อัปเดต หรือลบการอนุญาตหรืออ็อบเจ็กต์ใดๆ บนบัคเก็ตได้ ในการเปลี่ยนแปลงนี้ เราจะต้องเข้าสู่ระบบในฐานะผู้ใช้ที่มีสิทธิ์ในการจัดการสิทธิ์บัคเก็ตของ AWS
สมมติว่าเราอยู่บนคอนโซล AWS เราสามารถดูการอนุญาตสำหรับบัคเก็ตอัพโหลดของเราโดยเลือกบัคเก็ตตามชื่อ คลิกที่ปุ่ม "คุณสมบัติ" ที่ด้านบนขวาของหน้าจอ และเปิดส่วน "สิทธิ์" ที่ยุบ
เพื่อให้ผู้ใช้ที่ไม่ระบุชื่อสามารถอัปโหลดไปยังที่เก็บข้อมูลนี้ เราจะต้องแก้ไขนโยบายของที่เก็บข้อมูลเพื่ออนุญาตการอนุญาตเฉพาะที่อนุญาตให้อัปโหลดได้ ทำได้โดยใช้นโยบายการกำหนดค่าตาม JSON นโยบาย JSON ประเภทนี้มีการใช้กันอย่างแพร่หลายทั่วทั้ง AWS ร่วมกับบริการ IAM เมื่อคลิกที่ปุ่ม "แก้ไขนโยบายถัง" เพียงวางข้อความต่อไปนี้แล้วคลิก "บันทึก" เพื่ออนุญาตให้อัปโหลดภาพสาธารณะ:
{ "Version": "2008-10-17", "Id": "Policy1346097257207", "Statement": [ { "Sid": "Allow anonymous upload to /", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "s3:PutObject", "Resource": "arn:aws:s3:::test-upload/*" } ] }
หลังจากทำเช่นนี้ เราสามารถตรวจสอบว่านโยบายของที่เก็บข้อมูลนั้นถูกต้องโดยพยายามอัปโหลดรูปภาพไปยังที่เก็บข้อมูล คำสั่ง cURL ต่อไปนี้จะทำเคล็ดลับ:
curl https://test-upload.s3.amazonaws.com -F 'key=test.jpeg' -F '[email protected]'
หากมีการตอบกลับ 200 ช่วง เราจะทราบว่ามีการใช้การกำหนดค่าสำหรับที่เก็บข้อมูลการอัปโหลดเรียบร้อยแล้ว บัคเก็ต S3 ของเราควรได้รับการกำหนดค่า (ส่วนใหญ่) แล้ว เราจะกลับมาที่บริการนี้ในคอนโซลในภายหลังเพื่อเชื่อมต่อเหตุการณ์การอัปโหลดรูปภาพกับการเรียกใช้ฟังก์ชันการปรับขนาดของเรา
สิทธิ์ IAM สำหรับแลมบ์ดา
บทบาทแลมบ์ดาทั้งหมดทำงานภายในบริบทการอนุญาต ในกรณีนี้คือ "บทบาท" ที่กำหนดโดยบริการ IAM บทบาทนี้กำหนดสิทธิ์ทั้งหมดที่ฟังก์ชัน Lambda มีในระหว่างการเรียกใช้ สำหรับวัตถุประสงค์ของโครงการตัวอย่างนี้ เราจะสร้างบทบาททั่วไปที่จะใช้ระหว่างฟังก์ชัน Lambda ทั้งสอง อย่างไรก็ตาม ในสถานการณ์จริง ขอแนะนำให้ใช้ความละเอียดที่ละเอียดกว่าในข้อกำหนดสิทธิ์เพื่อให้แน่ใจว่าการใช้ประโยชน์จากความปลอดภัยจะถูกแยกออกเฉพาะบริบทการอนุญาตที่กำหนดไว้เท่านั้น
บริการ IAM จะอยู่ในส่วนย่อย "ความปลอดภัยและตัวตน" ของเมนูแบบเลื่อนลง "บริการ" บริการ IAM เป็นเครื่องมือที่ทรงพลังมากสำหรับจัดการการเข้าถึงบริการต่างๆ ของ AWS และอินเทอร์เฟซที่มีให้ในตอนแรกอาจดูล้นหลามไปหน่อย ถ้าคุณไม่คุ้นเคยกับเครื่องมือที่คล้ายคลึงกัน
เมื่ออยู่ในหน้าแดชบอร์ด IAM แล้ว ส่วนย่อย "บทบาท" จะอยู่ที่ด้านซ้ายมือของหน้า จากที่นี่ เราสามารถใช้ปุ่ม "สร้างบทบาทใหม่" เพื่อเปิดวิซาร์ดหลายขั้นตอนเพื่อกำหนดสิทธิ์ของบทบาท ลองใช้ “lambda_role” เป็นชื่อการอนุญาตทั่วไปของเรา หลังจากดำเนินการต่อจากหน้าคำจำกัดความชื่อ คุณจะมีตัวเลือกให้เลือกประเภทบทบาท เนื่องจากเราต้องการการเข้าถึง S3 เท่านั้น ให้คลิกที่ “AWS Service Roles” และภายในกล่องการเลือก ให้เลือก “AWS Lambda” คุณจะเห็นหน้านโยบายที่สามารถแนบมากับบทบาทนี้ได้ เลือกนโยบาย “AmazonS3FullAccess” และทำตามขั้นตอนต่อไปเพื่อยืนยันบทบาทที่จะสร้าง
สิ่งสำคัญคือต้องจดชื่อและ ARN (ชื่อทรัพยากร Amazon) ของบทบาทที่สร้างขึ้น สิ่งนี้จะใช้เมื่อสร้างฟังก์ชัน Lambda ใหม่เพื่อระบุบทบาทที่จะใช้สำหรับการเรียกใช้ฟังก์ชัน
หมายเหตุ: AWS Lambda จะบันทึกเอาต์พุตทั้งหมดจากการเรียกใช้ฟังก์ชันใน AWS Cloudwatch ซึ่งเป็นบริการบันทึกโดยอัตโนมัติ หากต้องการฟังก์ชันนี้เป็นที่ต้องการ ซึ่งแนะนำสำหรับสภาพแวดล้อมการใช้งานจริง ต้องเพิ่มสิทธิ์ในการเขียนไปยังสตรีมบันทึกของ Cloudwatch ในนโยบายสำหรับบทบาทนี้
รหัส!
ภาพรวม
ตอนนี้เราพร้อมที่จะเริ่มเขียนโค้ดแล้ว เราจะถือว่า ณ จุดนี้คุณได้ตั้งค่าคำสั่ง "awscli" หากยังไม่มี คุณสามารถทำตามคำแนะนำได้ที่ https://aws.amazon.com/cli/ เพื่อตั้งค่า awscli บนคอมพิวเตอร์ของคุณ
หมายเหตุ: โค้ดที่ใช้ในตัวอย่างเหล่านี้ถูกย่อให้สั้นลงเพื่อความสะดวกในการดูหน้าจอ สำหรับเวอร์ชันที่สมบูรณ์กว่านี้ โปรดไปที่ที่เก็บที่ https://github.com/gxx/aws-lambda-python/
อันดับแรก มาตั้งค่าโครงสร้างโครงกระดูกสำหรับโครงการของเรากันก่อน
aws-lambda-python/ - image_list/ - handler.py - list.html - Makefile - requirements.txt - image_resize/ - handler.py - resize.py - Makefile - requirements.txt - .pydistutils.cfg
เรามีไดเร็กทอรีย่อยสองไดเร็กทอรีในโครงสร้างของเรา หนึ่งไดเร็กทอรีสำหรับฟังก์ชันแลมบ์ดาแต่ละตัวของเรา ในแต่ละเหล่านี้ เรามีไฟล์ handler.py, Makefile และ requirements.txt ทั่วไป ไฟล์ handler.py จะมีวิธีการเรียกใช้การเรียกใช้ฟังก์ชันแลมบ์ดาแต่ละฟังก์ชัน และถือได้ว่าเป็นจุดเริ่มต้นสำหรับฟังก์ชันต่างๆ ไฟล์ requirements.txt จะมีรายการการพึ่งพาของเรา ดังนั้นเราจึงสามารถระบุและอัปเดตข้อกำหนดได้อย่างง่ายดาย สุดท้ายนี้ คำสั่ง Makefile เราจะใช้เพื่อให้กลไกที่ง่ายสำหรับการโต้ตอบกับ awscli ซึ่งจะทำให้กระบวนการสร้างและอัปเดตฟังก์ชันแลมบ์ดาของเราง่ายขึ้นมาก
คุณจะสังเกตเห็นไฟล์ .pydistutils.cfg ในรูทของไดเร็กทอรีโครงการของเรา จำเป็นต้องใช้ไฟล์นี้หากคุณกำลังทำงานกับ Python ภายใต้ Homebrew เนื่องจากวิธีการปรับใช้ฟังก์ชัน Lambda (จะกล่าวถึงในส่วนต่อไปนี้) จึงจำเป็นต้องใช้ไฟล์นี้ ดูที่เก็บสำหรับรายละเอียดเพิ่มเติม
ฟังก์ชันปรับขนาดภาพแลมบ์ดา
รหัส
เริ่มต้นด้วยฟังก์ชัน resize_image เราจะหยุดการพึ่งพา Wand ซึ่งเป็นไลบรารีประมวลผลรูปภาพของเรา โดยบันทึก Wand==0.4.2
ลงใน requirements.txt นี่จะเป็นการพึ่งพาเพียงอย่างเดียวสำหรับฟังก์ชัน image_resize lambda ของเรา ฟังก์ชัน resize_image ใน resize.py จะต้องจัดการทรัพยากรรูปภาพจากไลบรารี Wand และปรับขนาดตามพารามิเตอร์ความกว้างและความสูงที่ระบุ เพื่อรักษารูปภาพที่กำลังถูกปรับขนาด เราจะใช้อัลกอริธึมการปรับขนาดที่ "พอดีที่สุด" ซึ่งจะรักษาอัตราส่วนรูปภาพของรูปภาพต้นฉบับ ในขณะที่ลดขนาดรูปภาพให้พอดีกับความกว้างและความสูงที่ระบุ
def resize_image(image, resize_width, resize_height): ... original_ratio = image.width / float(image.height) resize_ratio = resize_width / float(resize_height) # We stick to the original ratio here, regardless of what the resize ratio is if original_ratio > resize_ratio: # If width is larger, we base the resize height as a function of the ratio of the width resize_height = int(round(resize_width / original_ratio)) else: # Otherwise, we base the width as a function of the ratio of the height resize_width = int(round(resize_height * original_ratio)) if ((image.width - resize_width) + (image.height - resize_height)) < 0: filter_name = 'mitchell' else: filter_name = 'lanczos2' image.resize(width=resize_width, height=resize_height, filter=filter_name, blur=1) return image
ด้วยเหตุนี้ ฟังก์ชันตัวจัดการจึงจำเป็นต้องยอมรับเหตุการณ์ที่สร้างโดยภาพที่อัปโหลด S3 ส่งต่อไปยังฟังก์ชัน resize_image
และบันทึกภาพที่ปรับขนาดแล้ว

from __future__ import print_function import boto3 from wand.image import Image from resize import resize_image def handle_resize(event, context): # Obtain the bucket name and key for the event bucket_name = event['Records'][0]['s3']['bucket']['name'] key_path = event['Records'][0]['s3']['object']['key'] response = boto3.resource('s3').Object(bucket_name, key_path).get() # Retrieve the S3 Object # Perform the resize operation with Image(blob=response['Body'].read()) as image: resized_data = resize_image(image, 400, 400).make_blob() # And finally, upload to the resize bucket the new image s3_connection.Object('test-resized', key_path).put(ACL='public-read', Body=resized_data) # Finally remove, as the bucket is public and we don't want just anyone dumping the list of our files! s3_object.delete()
กำลังปรับใช้
เมื่อโค้ดสมบูรณ์แล้ว จะต้องอัปโหลดไปยัง Amazon Lambda เป็นฟังก์ชัน Lambda ใหม่ นี่คือที่มาของ Makefile ที่เพิ่มเข้าไปในโครงสร้างไดเร็กทอรี Makefile นี้จะใช้เพื่อปรับใช้ข้อกำหนดฟังก์ชัน Lambda ที่เรากำลังสร้าง
ROLE_ARN = arn:aws:iam::601885388019:role/lambda_role FUNCTION_NAME = ResizeImage REGION = us-west-1 TIMEOUT = 15 MEMORY_SIZE = 512 ZIPFILE_NAME = image_resize.zip HANDLER = handler.handle_resize clean_pyc : find . | grep .pyc$ | xargs rm install_deps : pip install -r requirements.txt -t . build : install_deps clean_pyc zip $(ZIPFILE_NAME) -r * create : build aws lambda create-function --region $(REGION) \ --function-name $(FUNCTION_NAME) \ --zip-file fileb://$(ZIPFILE_NAME) \ --role $(ROLE_ARN) \ --handler $(HANDLER) \ --runtime python2.7 \ --timeout $(TIMEOUT) \ --memory-size $(MEMORY_SIZE) update : build aws lambda update-function-code --region $(REGION) \ --function-name $(FUNCTION_NAME) \ --zip-file fileb://$(ZIPFILE_NAME) \ --publish
หน้าที่หลักของ Makefile นี้คือ "สร้าง" และ "อัปเดต" ฟังก์ชันเหล่านี้จะจัดแพ็กเกจไดเร็กทอรีปัจจุบันก่อน ซึ่งแสดงถึงโค้ดทั้งหมดที่จำเป็นในการรันฟังก์ชัน Lambda ถัดไป การขึ้นต่อกันที่ระบุในไฟล์ requirements.txt
จะถูกติดตั้งในไดเร็กทอรีย่อยปัจจุบันที่จะทำแพ็กเกจ ขั้นตอนการบรรจุจะซิปเนื้อหาของไดเร็กทอรีเพื่ออัปโหลดในภายหลังด้วยคำสั่ง "awscli" Makefile ของเราสามารถปรับเปลี่ยนเพื่อใช้ในนิยามฟังก์ชันอื่นๆ ของ Lambda ได้
ในยูทิลิตี้ Makefile เรากำหนดตัวแปรสองสามตัวที่จำเป็นสำหรับการสร้าง/อัปเดตรูปภาพของเรา กำหนดค่าเหล่านี้ตามความจำเป็นเพื่อให้คำสั่ง Makefile ทำงานได้อย่างถูกต้องสำหรับคุณ
-
ROLE_ARN
: นี่คือชื่อทรัพยากรของ Amazon ที่ระบุบทบาทของเราในการเรียกใช้ฟังก์ชัน Lambda -
FUNCTION_NAME
: ชื่อของฟังก์ชัน Lambda ที่เรากำลังสร้าง/อัปเดต -
REGION
: ภูมิภาคที่จะสร้าง/อัปเดตฟังก์ชันแลมบ์ดา -
TIMEOUT
: หมดเวลาในไม่กี่วินาทีก่อนที่การเรียกใช้ Lambda จะถูกฆ่า -
MEMORY_SIZE
: ขนาดของหน่วยความจำเป็นเมกะไบต์ที่ฟังก์ชัน Lambda จะสามารถเข้าถึงได้เมื่อเรียกใช้ -
ZIPFILE_NAME
: ชื่อของแพ็คเกจซิปที่มีโค้ดฟังก์ชันแลมบ์ดาและการอ้างอิง -
HANDLER
: เส้นทางการนำเข้าแบบสัมบูรณ์ในรูปแบบจุดของฟังก์ชันตัวจัดการ
เมื่อกำหนดค่าแล้ว การรันคำสั่ง make create
จะสร้างบางสิ่งที่คล้ายกับเอาต์พุตต่อไปนี้:
$ make create pip install -r requirements.txt -t . ... find . | grep .pyc| xargs rm zip image_resize.zip -r * ... aws lambda create-function --region ap-northeast-1 \ --function-name ResizeImage2 \ --zip-file fileb://image_resize.zip \ --role arn:aws:iam::11111111111:role/lambda_role \ --handler handler.handle_resize \ --runtime python2.7 \ --timeout 15 \ --memory-size 512 { "CodeSha256": "doB1hsujmZnxZHidnLKP3XG2ifHM3jteLEBvsK1G2nasKSo=", "FunctionName": "ResizeImage", "CodeSize": 155578, "MemorySize": 512, "FunctionArn": "arn:aws:lambda:us-west-1:11111111111:function:ResizeImage", "Version": "$LATEST", "Role": "arn:aws:iam::11111111111:role/lambda_role", "Timeout": 15, "LastModified": "2016-01-10T11:11:11.000+0000", "Handler": "handler.handle_resize", "Runtime": "python2.7", "Description": "" }
การทดสอบ
หลังจากดำเนินการคำสั่งการสร้าง ฟังก์ชันการปรับขนาดสำหรับอิมเมจของเราก็พร้อมใช้งาน แต่ยังไม่ได้เชื่อมต่อกับบัคเก็ต S3 เพื่อรับเหตุการณ์ เรายังคงสามารถทดสอบฟังก์ชันผ่านคอนโซล AWS เพื่อยืนยันว่าฟังก์ชันนี้จัดการเหตุการณ์การอัปโหลดไฟล์ S3 ได้อย่างเหมาะสม บนแดชบอร์ด AWS Lambda ซึ่งอยู่ในส่วนย่อย "คำนวณ" ของเมนูแบบเลื่อนลง "บริการ" ให้เลือกชื่อของฟังก์ชันที่เราสร้างขึ้น หน้ารายละเอียดฟังก์ชันของแลมบ์ดานี้มีรายการดรอปดาวน์ที่มีป้ายกำกับว่า “การดำเนินการ” ซึ่งมีตัวเลือกที่ระบุว่า “กำหนดค่าเหตุการณ์การทดสอบ”
การคลิกที่นี่จะเป็นการเปิด modal เพื่อให้คุณระบุเหตุการณ์ทดสอบและเทมเพลตตัวอย่างบางส่วนได้ เลือกตัวอย่าง "S3 Put" และแทนที่การกล่าวถึงชื่อที่เก็บข้อมูลด้วยชื่อของที่เก็บข้อมูลที่ตั้งค่าไว้ เมื่อกำหนดค่านี้แล้ว การใช้ปุ่ม "ทดสอบ" ในหน้าฟังก์ชัน Lambda ในภายหลังจะเรียกใช้ฟังก์ชัน Lambda ราวกับว่าเหตุการณ์ที่กำหนดค่าไว้ก่อนหน้านี้ได้เกิดขึ้นจริง
ในการตรวจสอบสแต็กเทรซข้อผิดพลาดหรือข้อความบันทึก คุณสามารถดูสตรีมบันทึกใน Cloudwatch กลุ่มบันทึกใหม่จะถูกสร้างขึ้นพร้อมกับสร้างฟังก์ชัน Lambda สตรีมบันทึกเหล่านี้มีประโยชน์และสามารถนำไปวางในบริการอื่นๆ ได้
การเชื่อมต่อกับเหตุการณ์บัคเก็ต S3
กลับไปที่แดชบอร์ด S3 ให้ขยายส่วน "เหตุการณ์" ที่ยุบซึ่งอยู่ในเมนู "คุณสมบัติ" เพื่อแสดงแบบฟอร์ม "การแจ้งเตือนเหตุการณ์" ฟิลด์บังคับสำหรับเราในการกรอกคืออินพุต "กิจกรรม" และ "ส่งไปที่" จาก "เหตุการณ์" เลือกเหตุการณ์ "สร้างวัตถุ (ทั้งหมด)" ซึ่งจะทำให้สามารถสกัดกั้นเหตุการณ์ทั้งหมดที่สร้างออบเจ็กต์บนบัคเก็ตการอัปโหลดได้ สำหรับอินพุต "ส่งไปยัง" ให้เลือกปุ่มตัวเลือก "ฟังก์ชันแลมบ์ดา" ส่วนใหม่จะปรากฏขึ้นพร้อมกับรายการดรอปดาวน์ที่มีฟังก์ชันแลมบ์ดา "ResizeImage" ที่เรากำหนดค่าให้เป็นตัวเลือก เมื่อคลิก "บันทึก" เหตุการณ์ "ที่สร้างด้วยวัตถุ" จะถูกส่งไปยังการเรียกใช้ฟังก์ชัน "ResizeImage" Lambda
ตอนนี้เรามีฟังก์ชันหลักของแอปพลิเคชันแล้ว ลองทำการทดสอบ cURL อื่นเพื่อให้แน่ใจว่าทุกอย่างทำงานตามที่คาดไว้ ใช้ cURL เพื่ออัปโหลดรูปภาพลงในบัคเก็ต S3 และตรวจสอบด้วยตนเองว่าอิมเมจถูกอัปโหลดไปยังบัคเก็ตการปรับขนาดหรือไม่
curl https://test-upload.s3.amazonaws.com -F 'key=test.jpeg' -F '[email protected]'
เมื่อดำเนินการคำสั่งนี้ รูปภาพที่ปรับขนาดควรถูกสร้างขึ้นในบัคเก็ต "test-resized" หลังจาก 50-1000 มิลลิวินาที ขึ้นอยู่กับว่าฟังก์ชัน Lambda ได้ "อุ่นเครื่อง" แล้วหรือไม่
แสดงรายการฟังก์ชันแลมบ์ดา
รหัส
ฟังก์ชัน ListImage Lambda จะดึงรายการรูปภาพที่ปรับขนาดแล้วแสดงบนหน้า HTML สำหรับผู้ใช้ หน้า HTML นี้ยังให้ฟังก์ชันสำหรับผู้ใช้ในการอัปโหลดภาพของตนเอง Jinja2 ใช้ในฟังก์ชันเพื่อแสดง HTML จากคำจำกัดความของเทมเพลต เช่นเดียวกับเมื่อก่อน ข้อกำหนดเหล่านี้ระบุไว้ในไฟล์ requirements.txt
from __future__ import print_function import os import boto3 from jinja2 import Environment from jinja2 import FileSystemLoader def _render_template(image_urls): env = Environment(loader=FileSystemLoader(os.path.abspath(os.path.dirname(__file__)))) template = env.get_template('list.html') rendered_template = template.render(image_urls=image_urls) return rendered_template def handle_list_image(event, context): bucket = boto3.resource('s3').Bucket('test-resized') image_summaries = sorted((image_summary for image_summary in bucket.objects.all()), key=lambda o: o.last_modified) image_urls = [] for summary in image_summaries: image_urls.append( boto3.client('s3').generate_presigned_url( 'get_object', Params={ 'Bucket': summary.bucket_name, 'Key': summary.key } ) ) return {'htmlContent': _render_template(image_urls)}
<html> <head> <title>List Images</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> <script> var uploadImage = (function () { var inProgress = false; return function () { if (inProgress) { return; } inProgress = true; var formData = new FormData(); var fileData = $('#image-file').prop('files')[0]; formData.append('key', parseInt(Math.random() * 1000000)); formData.append('acl', 'public-read'); formData.append('file', fileData); $.ajax({ url: 'https://test-upload.s3.amazonaws.com/', type: 'POST', data: formData, processData: false, contentType: false, success: function (data) { window.location.reload(); } }); } })(); </script> <style type="text/css"> .image__container { float: left; width: 30%; margin-left: 2.5%; margin-right: 2.5%; max-width: 400px; } </style> </head> <body> <nav> <input type="file" onchange="uploadImage()" value="Upload Image" /> </nav> <section> {% for image_url in image_urls %} <div class="image__container"> <img src="{{ image_url }}" /> </div> {% endfor %} </section> </body> </html>
อีกครั้ง เราสามารถแก้ไข Makefile ก่อนหน้าและใช้คำสั่ง create เพื่อปรับใช้ฟังก์ชันแลมบ์ดาของเรา
API เกตเวย์
ฟังก์ชัน ImageList Lambda เสร็จสมบูรณ์ แต่ไม่สามารถให้บริการแก่ผู้ใช้ใดๆ ได้ เนื่องจากฟังก์ชัน Lambda สามารถเรียกได้เฉพาะเพื่อตอบสนองต่อเหตุการณ์จากบริการอื่น หรือโดยทางโปรแกรมเท่านั้น นี่คือที่มาของบริการ Amazon AWS API Gateway เกตเวย์ API สามารถพบได้ในส่วนย่อย "บริการแอปพลิเคชัน"
API Gateway เป็นวิธีการสร้างโมเดลปลายทางเป็นชุดของทรัพยากรและวิธีการ โดยพื้นฐานแล้วจะเป็นอินเทอร์เฟซ REST นอกเหนือจากการจัดเตรียมสิ่งอำนวยความสะดวกสำหรับการตรวจสอบและเปลี่ยนคำขอแล้ว API Gateway ยังทำหน้าที่อื่นๆ เช่น การจัดหาคำขอการควบคุมปริมาณ/การจำกัดอัตรา
จากแดชบอร์ด API Gateway ให้สร้าง API ใหม่สำหรับให้บริการฟังก์ชัน ListImage สามารถตั้งชื่อและคำอธิบายได้ตามต้องการ เมื่อสร้างแล้ว ให้คลิกที่ชื่อของ API ใหม่เพื่อเข้าถึงรายละเอียด API สร้างทรัพยากรใหม่สำหรับ URL รูท “/” URL นี้จะใช้เพื่อแสดงหน้า HTML
ขณะดูรายละเอียดสำหรับหน้าทรัพยากรรูท ให้เพิ่มเมธอด GET ตั้งค่า "ประเภทการรวม" เป็น "ฟังก์ชันแลมบ์ดา" ตั้งค่า "ภูมิภาคแลมบ์ดา" เป็น "us-west-1" หรือภูมิภาคที่คุณเลือก และพิมพ์ชื่อของฟังก์ชัน ListImage Lambda
ก่อนที่เราจะสามารถแมปการตอบสนองของเรากับเอาต์พุต HTML เราต้องกำหนด "โมเดล" ที่จะกำหนดสคีมาสำหรับการตอบกลับจากเซิร์ฟเวอร์ นอกเหนือจากการจับคู่การตอบสนองนี้กับประเภทเนื้อหา เลือกส่วน "โมเดล" สำหรับ API และคลิกที่ "สร้าง" เพื่อสร้างโมเดลใหม่ ตั้งชื่อโมเดลว่า "HTML" โดยมีประเภทเนื้อหาเป็น "text/html" และกำหนดสคีมาดังนี้
{ "$schema": "http://json-schema.org/draft-04/schema#", "title" : "HTML", "type" : "object" }
กลับไปที่แดชบอร์ด API เลือกทรัพยากรที่เราสร้างขึ้นและไปที่ส่วน "การตอบสนองการรวม" ส่วนนี้กำหนดการเปลี่ยนแปลงใด ๆ เพื่อดำเนินการหลังจากได้รับการตอบสนองจากฟังก์ชัน Lambda ก่อนกำหนดเส้นการตอบสนองต่อขั้นตอนสุดท้าย
เปิดส่วน "เทมเพลตการแมป" และเพิ่ม "ประเภทเนื้อหา" ใหม่ของ "ข้อความ/html" ลบ "ประเภทเนื้อหา" เก่าพร้อมกัน ทางด้านขวา เปลี่ยนเมนูแบบเลื่อนลงจาก "Output Passthrough" เป็น "Mapping template" ซึ่งจะทำให้เราสามารถแก้ไข JSON ดิบที่ API Gateway ยอมรับ และใช้เนื้อหา HTML ภายในคุณสมบัติ "htmlContent" ของข้อมูลที่ส่งคืนแทน สำหรับเทมเพลตการแมป ให้ระบุ “$input.htmlContent” เป็นเทมเพลต สุดท้าย ให้แก้ไขส่วน "Method Response" โดยลบ "application/json" ออกจาก "Response Models for 200" และเพิ่ม "text/html" แทน
กลับไปที่แดชบอร์ดสำหรับ API มีปุ่มอยู่ที่ด้านซ้ายบนของหน้าที่ระบุว่า "ปรับใช้ API" คลิกที่ปุ่มนี้เพื่ออัปเดตหรือสร้าง API ด้วยทรัพยากร วิธีการ โมเดล และการแมปที่ระบุ เมื่อดำเนินการเสร็จแล้ว URL จะแสดงสำหรับขั้นตอนการปรับใช้ที่เลือก (การจัดเตรียมโดยค่าเริ่มต้น) ในที่สุดตัวอย่างก็เสร็จสมบูรณ์! คุณสามารถอัปโหลดไฟล์บางไฟล์เพื่อทดสอบและดูภาพที่ปรับขนาดได้
ห่อ
AWS เป็นบริการขนาดใหญ่ และจะยังไม่ยุติการให้บริการในเร็วๆ นี้ แม้ว่าการล็อคอินของผู้ขายจะเป็นสิ่งที่ต้องระวังอยู่เสมอ แต่ AWS Lambda ก็ให้บริการที่ค่อนข้างบางพร้อมชุดตัวเลือกการกำหนดค่าเสริมที่หลากหลาย การใช้ประโยชน์จากบริการที่จัดหาให้โดย AWS เพื่อปรับใช้แอปพลิเคชันที่ปรับขนาดได้และบำรุงรักษาได้ง่ายจะให้ประโยชน์สูงสุดในการใช้แพลตฟอร์ม AWS AWS Lambda มอบโซลูชันที่หรูหรา ปรับขนาดได้ และคุ้มค่า โดยสนับสนุนโดยแพลตฟอร์มระดับองค์กรที่ใช้โดยผู้บริโภคจำนวนมาก ฉันเชื่อว่าแอปพลิเคชัน "ไร้เซิร์ฟเวอร์" เป็นหนทางแห่งอนาคต แจ้งให้เราทราบว่าคุณคิดอย่างไรในความคิดเห็นด้านล่าง