Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

AWS Lambda ด้วย Ruby: คู่มือ Build, Test, Deploy แบบ End-to-End

การพัฒนาซอฟต์แวร์ท้าทาย แต่ Maintenance ยากกว่ามาก Maintenance รวม Software Patches และ Server Maintenance ใน Post นี้ Focus ที่ Server Management และ Maintenance

แบบดั้งเดิม Servers เป็น On-premises หมายถึงซื้อและ Maintain Physical Hardware ด้วย Cloud Computing เซิร์ฟเวอร์ไม่ต้อง Own Physically ในปี 2006 Amazon เริ่ม AWS และ Introduce EC2 Service ยุค Modern Cloud Computing เริ่มต้น ด้วย Service นี้ ไม่ต้อง Maintain Physical Servers หรือ Upgrade Physical Hardware แก้ปัญหาเยอะ แต่ Server Maintenance และ Resource Management ยังเรา Taking to next level ตอนนี้มี Serverless Technology

AWS Lambda ด้วย Ruby: คู่มือ Build, Test, Deploy แบบ End-to-End

Serverless Technology คืออะไร?

Serverless Technology ช่วย Offload งาน Manage และ Provision Servers ให้ Cloud Provider ใน Post นี้ Discuss AWS

Serverless ไม่ได้หมายถึง No Server At All มี Server แต่ Fully Manged by Cloud Provider ในความหมายหนึ่ง สำหรับ Users ของ Serverless Technology ไม่มี Visible Server Servers ไม่ Directly Visible ให้เรา และ Job Managing Automated by Cloud Provider ลักษณะเฉพาะที่ทำให้ Serverless:

  • No Operational Management - ไม่ต้อง Patch Servers หรือ Manage High Availability
  • Scale as Needed - จาก Serve ผู้ใช้น้อยไปจน Millions
  • Pay as You Go - Cost จัดการตาม Usage

Serverless Technology Categorize ได้:

  • Compute (e.g., Lambda และ Fargate)
  • Storage (e.g., S3)
  • Data Store (e.g., DynamoDB และ Aurora)
  • Integration (e.g., API Gateway, SNS, SQS)
  • Analytics (e.g., Kinesis และ Athena)

ทำไมใช้ Serverless Technology?

Cost

Pay as you go ข้อได้เปรียบหลัก Traffic Volume Unpredictable ต้อง Scale Server Up/Down ตาม Usage Patterns แต Self-managed Autoscaling ยากและ Inefficient Serverless Computing เช่น AWS Lambda ช่วย Save Cost เพราะไม่ต้องจ่ายตอน Idle

Developer Productivity

Serverless = Fully Managed Services by Cloud Provider ไม่ต้อง Provision Servers หรือ Develop Server Applications Developers เริ่ม Code ทันทีโดยไม่ Manage Server Approach นี้ Remove Patch Servers และ Manage Autoscaling ประหยัดเวลา Increase Productivity

Elasticity

Serverless Computing Highly Elastic Scale Up/Down ตาม Usage Spike Users จัดการง่าย ประหยัดเวลา Developers มาก

High Availability

Serverless Managed by Cloud Provider Servers High Uptime Failovers Automated Managing Issues นี้ต้อง Specialized Skills Serverless Approach Ops และ Devs Work ทำโดยคนเดียวได้

How To Implement Serverless Functionality In Ruby

ตาม AWS Ruby หนึ่งในภาษาที่ใช้มากที่สุดใน AWS Lambda รองรับ Ruby ตั้งแต่ November 2018 เราจะ Build Web API ใน Ruby ใช้ Serverless Technologies ของ AWS เท่านั้น

สร้าง Serverless Infra ใน AWS Login AWS Console สร้างได้ แต่เราอยาก Develop ที่ Easily Testable และ Facilitate Disaster Recovery เขียน Serverless Feature As Code AWS ให้ Serverless Application Model (SAM) SAM เป็น Framework Build Serverless Apps ใน AWS ให้ YAML-based Syntax 設計 Lambda, Databases, APIs AWS SAM Applications Build ด้วย AWS SAM-CLI ดาวน์โหลด ที่นี่

AWS SAM CLI Built on AWS CloudFormation ถ้า Familiar IaC กับ CloudFormation จะ Simple หรือใช้ Serverless Framework ก็ได้ ใน Post นี้ใช้ AWS SAM

AWS Lambda ด้วย Ruby: คู่มือ Build, Test, Deploy แบบ End-to-End

ก่อนใช้ SAM CLI ต้องมี:

  • AWS Profile Setup
  • Docker Installed
  • SAM CLI Installed

เราจะ Develop Serverless Application เริ่มสร้าง Serverless Infra อย่าง DynamoDB และ Lambda ใน Application เริ่ม Database:

DynamoDB

DynamoDB คือ Serverless AWS-managed Database Service Serverless ทำให้ Quick และ Easy Setup สร้าง DynamoDB Define SAM Template:


AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
  UsersTable:
    Type: AWS::Serverless::SimpleTable
    Properties:
      PrimaryKey:
        Name: id
        Type: String
      TableName: users

กับ SAM CLI และ Template ข้างบน สร้าง Basic DynamoDB Table ได้ รัน Command Build Package Push ไป S3 สร้าง S3 Bucket ชื่อ serverless-users-bucket ก่อนรัน:


$ sam package --template-file sam.yaml \
  --output-template-file out.yaml \
  --s3-bucket serverless-users-bucket

S3 กลายเป็น Source สำหรับ Template และ Code ของ Serverless App Deploy Template สร้าง DynamoDB:


$ sam deploy --template-file out.yaml \
  --stack-name serverless-users-app \
  --capabilities CAPABILITY_IAM

DynamoDB Setup Ready ต่อไปสร้าง Lambda ใช้ Table นี้

Lambda

Lambda คือ Serverless Compute Service AWS Execute Code As-needed โดยไม่ต้อง Actual Server Management ที่ Code Executed Lambda ใช้ Async Processes, REST APIs, Scheduled Jobs ทั้งหมด ต้องเขียน Handler Function Push ไป AWS Lambda Lambda Execute Task ตาม Events Event Triggered โดย Sources ต่างๆ: API Gateway, SQS, S3 หรือ Codebase อื่น Manual/Programmatically Trigger Lambda โดย Pass Events/Context ให้ Handler Handler รับ 2 Arguments:

Event - Events มัก Key-value Hash จาก Trigger Source Values Auto-passed เมื่อ Triggered โดย SQS, Kinesis, API Gateway Trigger Manual Pass Events ที่นี่ Event มี Input Data สำหรับ Lambda Handler ตัวอย่าง API Gateway Request Body อยู่ใน Event นี้

Context - Argument ที่สองใน Handler Function มี Details: Trigger Source, Lambda Function Name, Version, Request-id ฯลฯ

Output ของ Handler ส่งกลับ Service ที่ Triggered Lambda Output คือ Return Value ของ Handler Function

AWS Lambda รองรับ 7 Languages รวม Ruby ที่นี่ใช้ AWS Ruby-sdk Connect DynamoDB

ก่อนเขียนโค้ด สร้าง Infra สำหรับ Lambda ด้วย SAM Template:


AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: "Serverless users app"
Resources:
  CreateUserFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: users.create
      Runtime: ruby2.7
      Policies:
        - DynamoDBWritePolicy:
            TableName: !Ref UsersTable
      Environment:
        Variables:
          USERS_TABLE: !Ref UsersTable

ใน Handler เขียน Reference Function ที่ Execute Handler: <filename>.<method_name>

Refer Serverless Policy Template สำหรับ Policy Attach ให้ Lambda ตาม Resource ที่ใช้ เราเขียน DynamoDB ใช้ DynamoDBWritePolicy ใน Policies Section

Provide Env Variable USERS_TABLE ให้ Lambda ส่ง Requests ไป Database ที่ระบุ

นี่คือ Infra สำหรับ Lambda เขียน Code Create User ใน DynamoDB ที่ Lambda Execute

เพิ่ม AWS Record ใน Gemfile:


# Gemfile
source 'https://rubygems.org' do
  gem 'aws-record', '~> 2'
end

Code เขียน Input ไป DynamoDB:


# users.rb
require 'aws-record'
class UsersTable
  include Aws::Record
  set_table_name ENV['USERS_TABLE']
  string_attr :id, hash_key: true
  string_attr :body
end

def create(event:, context:)
  body = event["body"]
  id = SecureRandom.uuid
  user = UsersTable.new(id: id, body: body)
  user.save!
  user.to_h
end

Quick และ Easy AWS ให้ aws-record Gem Access DynamoDB คล้าย Rails activerecord

รัน Commands ติดตั้ง Dependencies:

Note: ต้องมี Ruby Version เดียวกับ Lambda ตัวอย่างต้อง Ruby2.7 บน Machine


# install dependencies
$ bundle install
$ bundle install --deployment

Package Changes:


$ sam package --template-file sam.yaml \
  --output-template-file out.yaml \
  --s3-bucket serverless-users-bucket

Deploy:


sam deploy --template-file out.yaml \
  --stack-name serverless-users-app \
  --capabilities CAPABILITY_IAM

ตอนนี้มี Lambda รัน เขียน Input ไป Database เพิ่ม API Gateway หน้า Lambda เข้าถึงได้ผ่าน HTTP Calls API Gateway ให้ API Management: Rate Limiting, Authentication แต่อาจแพงตาม Usage มี Cheaper Option: HTTP API Only ไม่มี API Management เลือกตาม Use Case

AWS Lambda มี Limits บ้าง Modify ได้ บ้าง Fixed:

  • Memory - Default 128 MB เพิ่มได้ถึง 3,008 MB ทีละ 64 MB
  • Timeout - Default 3 seconds เพิ่มได้ถึง 900 seconds
  • Storage - /tmp Directory Limit 512 MB
  • Request/Response Size - 6 MB Sync Trigger, 256 MB Async Trigger
  • Environment Variables - 4KB

เขียน Code ให้ Fit Limitations ถ้าไม่ Fit Split Code ให้ Lambda Trigger Lambda อื่น มี Step Functions AWS สำหรับ Sequence Multiple Lambdas

Test Serverless Applications Locally ยังไง?

Serverless Apps ต้อง Vendor ให้ Managed Serverless Services เรา Depends on AWS เพื่อ Test มี Local Options จาก AWS Open-source Tools รองรับ AWS Serverless Technologies Test Locally ได้

Test Lambda และ DynamoDB Local Run 它们

สร้าง Docker Network Network ช่วย Communicate ระหว่าง Lambda และ DynamoDB


$ docker network create lambda-local --docker-network lambda-local

DynamoDB Local คือ Local Version ของ DynamoDB จาก AWS Test Locally ได้ Run Docker Image:


$ docker run -p 8000:8000 --network lambda-local --name dynamodb amazon/dynamodb-local

เพิ่มบรรทัดใน user.rb Connect Lambda ไป Local DynamoDB:


local_client = Aws::DynamoDB::Client.new(
  region: "local",
  endpoint: 'https://dynamodb:8000'
)
UsersTable.configure_client(client: local_client)

เพิ่ม input.json Input สำหรับ Lambda:


{
  "name": "Milap Neupane",
  "location": "Global"
}

ก่อน Execute Lambda เพิ่ม Table ใน Local DynamoDB ใช้ Migration จาก aws-migrate สร้าง migrate.rb เพิ่ม Migration:


require 'aws-record'
require './users.rb'
local_client = Aws::DynamoDB::Client.new(
  region: "local",
  endpoint: 'https://localhost:8000'
)
migration = Aws::Record::TableMigration.new(UsersTable, client: local_client)
migration.create!(
  provisioned_throughput: {
    read_capacity_units: 5,
    write_capacity_units: 5
  }
)
migration.wait_until_available

Execute Lambda Locally:


$ sam local invoke "CreateUserFunction" -t sam.yaml \
  -e input.json \
  --docker-network lambda-local

จะสร้าง User Data ใน DynamoDB Table มี Options อย่าง Localstack รัน AWS Stacks Locally

เมื่อไหร่ควรใช้ Serverless Computing

Decide ใช้ Serverless ต้อง Aware Benefits และ Shortcomings ตาม Characteristics นี้ Decide:

Cost

  • App มี Idle Time และ Inconsistent Traffic Lambdas Good เพราะ Reduce Costs
  • App Consistent Traffic Volume AWS Lambda อาจ Costly

Performance

  • App Not Performance-sensitive AWS Lambda Good Choice
  • Lambdas มี Cold Boot Time ทำให้ Slow Response Times ตอน Cold Boot

Background Processing

  • Lambda Good สำหรับ Background Processing Tools อย่าง Sidekiq มี Server Scaling/Maintenance Overhead Combine AWS Lambda + AWS SQS Queue Process Background Jobs โดยไม่ต้อง Server Maintenance

Concurrent Processing

  • Concurrency ใน Ruby ไม่ง่าย Lambda ทำได้โดยไม่ต้อง Programming Language Support Lambda Execute Concurrently Improve Performance

Running Periodic/One-time Scripts

  • Cron Jobs Execute Ruby Codes แต Server Maintenance Cron Jobs ยาก Large-scale Apps Event-based Lambdas Help Scaling

Use Cases เหล่านี้สำหรับ Lambda Functions ใน Serverless Apps ไม่ต้อง Build ทุกอย่าง Serverless สร้าง Hybrid Model สำหรับ Use Cases ข้างบน ช่วย Scaling และ Increase Developer Productivity Serverless Technologies Evolving และ Better มีอื่นๆ เช่น AWS Fargate, Google CloudRun ไม่มี Limitations ของ AWS Lambda