برنامه نویسی

توربوشارژ AWS Lambda: چگونه برای همیشه سرما را از بین ببریم

Summarize this content to 400 words in Persian Lang
تصور کنید عجله دارید تا قهوه صبح خود را بنوشید، فقط متوجه می شوید که باریستا باید ابتدا دستگاه اسپرسوساز را راه اندازی کند. اساساً این همان چیزی است که در هنگام شروع سرد لامبدا اتفاق می افتد – و درست مانند تأخیر قهوه شما، می تواند ناامید کننده باشد. اما نترس! امروز ما عمیقاً به این خواهیم پرداخت که چگونه همزمانی ارائه شده می‌تواند به شما کمک کند تا این عملکردها را به صورت مستقیم انجام دهید.

درک مشکل شروع سرد

هنگامی که یک تابع Lambda اخیراً استفاده نشده است، AWS باید قبل از اجرای کد شما یک محیط اجرایی جدید را بچرخاند. این فرآیند اولیه سازی شامل:

در حال دانلود کد شما
بوت استرپ کردن زمان اجرا
در حال بارگیری وابستگی های شما
اجرای کد اولیه

در اینجا یک تابع ساده Node.js وجود دارد که تأثیر شروع سرد را نشان می دهد:

const mongoose = require(‘mongoose’);

// This connection happens during cold start
let conn = null;

const connectToDb = async () => {
if (conn == null) {
conn = await mongoose.connect(process.env.MONGODB_URI, {
serverSelectionTimeoutMS: 5000
});
}
return conn;
};

exports.handler = async (event) => {
// Connection time will impact cold start duration
await connectToDb();

// Rest of your handler code…
};

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در آزمایش من، این تابع ساده با اتصال پایگاه داده می تواند 800ms-2s برای شروع سرد طول بکشد، در مقایسه با 10-50ms برای شروع گرم.

همزمانی ارائه شده را وارد کنید

همزمانی ارائه شده مانند داشتن یک باریستا است که دستگاه اسپرسوساز را حتی در زمان های آرام کار می کند. مجموعه‌ای از محیط‌های اجرایی از پیش راه‌اندازی‌شده را برای پاسخگویی فوری به درخواست‌های دریافتی حفظ می‌کند.

برای فعال کردن آن با استفاده از AWS CDK:

const lambda = new lambda.Function(this, ‘MyFunction’, {
runtime: lambda.Runtime.NODEJS_18_X,
handler: ‘index.handler’,
code: lambda.Code.fromAsset(‘lambda’),
// Other configuration…
});

const version = lambda.currentVersion;
version.addProvisionedConcurrency(5); // Keep 5 instances warm

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

جادوی پشت صحنه

هنگامی که همزمانی ارائه شده را فعال می کنید، AWS کار هوشمندانه ای انجام می دهد:

تعداد مشخصی از محیط های اجرایی را ایجاد می کند
کد اولیه شما را اجرا می کند
محیط ها را در حالت آماده منجمد می کند
این استخر را حفظ می کند و جایگزین هر استخری می شود که ناسالم می شود

این بدان معناست که عملکرد شما تقریباً بلافاصله پس از راه‌اندازی شروع به اجرا می‌کند، زیرا بلند کردن سنگین قبلاً انجام شده است.

بهترین روش ها و نکات بهینه سازی

1. کد اولیه هوشمند

تا آنجا که ممکن است مقداردهی اولیه را به محدوده جهانی منتقل کنید:

// Good: Done once during provisioned concurrency initialization
const client = new AWS.DynamoDB.DocumentClient();
const tableName = process.env.TABLE_NAME;

// Bad: Would run on every invocation
exports.handler = async (event) => {
const client = new AWS.DynamoDB.DocumentClient();
// …
};

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

2. سطوح همزمانی دقیق

اجرای همزمان عملکرد خود را با استفاده از معیارهای CloudWatch مانند ConcurrentExecutions و همزمانی ارائه شده را بر این اساس تنظیم کنید. تامین بیش از حد باعث هدر رفتن پول می شود، در حالی که تامین کم منجر به شروع سرد می شود.

3. استفاده از مقیاس خودکار برنامه

تنظیم مقیاس خودکار برای تنظیم خودکار همزمانی ارائه شده بر اساس استفاده:

const target = version.addAutoScaling({
minCapacity: 2,
maxCapacity: 10
});

target.scaleOnUtilization({
utilizationTarget: 0.75,
scaleInCooldown: Duration.seconds(60),
scaleOutCooldown: Duration.seconds(60)
});

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ملاحظات هزینه

همزمانی ارائه شده رایگان نیست – شما برای:

زمانی که نمونه های ارائه شده شما در دسترس هستند
زمان محاسبه استفاده شده در طول اجرای تابع
هر نمونه اضافی که فراتر از مبلغ ارائه شده شما باشد

یک رویکرد عملی این است که:

توابع حساس به تأخیر را شناسایی کنید
الگوهای استفاده واقعی آنها را نظارت کنید
همزمانی ارائه شده را به صورت انتخابی اعمال کنید
برای الگوهای بار قابل پیش بینی از همزمانی برنامه ریزی شده استفاده کنید

اندازه گیری تاثیر

من یک چارچوب آزمایشی ساده برای اندازه گیری تفاوت ایجاد کردم:

import concurrent.futures
import requests
import time
import statistics

def invoke_function(url):
start = time.time()
response = requests.post(url)
return time.time() – start

def run_load_test(url, concurrent_requests):
with concurrent.futures.ThreadPoolExecutor(max_workers=concurrent_requests) as executor:
futures = [executor.submit(invoke_function, url) for _ in range(concurrent_requests)] times = [f.result() for f in concurrent.futures.as_completed(futures)]

return {
‘avg’: statistics.mean(times),
‘p95’: statistics.quantile(times, 0.95),
‘max’: max(times)
}

# Results with provisioned concurrency disabled
print(“Without PC:”, run_load_test(lambda_url, 100))

# Results with provisioned concurrency enabled
print(“With PC:”, run_load_test(lambda_url, 100))

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نتایج دنیای واقعی

در محیط های تولید، من دیده ام:

سرد شروع می شود از 1-2 ثانیه به زیر 100 میلی ثانیه کاهش یافت

P95 تاخیر تا 80٪ بهبود یافته است

عملکرد پایدارتر در هنگام افزایش ترافیک

فراتر از همزمانی ارائه شده

در حالی که همزمانی ارائه شده قدرتمند است، این استراتژی های مکمل را در نظر بگیرید:

استفاده از وابستگی های کوچکتر برای کاهش زمان اولیه سازی
پیاده سازی ادغام اتصال برای پایگاه های داده
استفاده از Lambda SnapStart برای توابع جاوا
استفاده از سرویس‌های کش خارجی برای داده‌های با دسترسی مکرر

نتیجه گیری

همزمانی ارائه شده ابزاری قدرتمند برای کاهش شروع سرد لامبدا است، اما برای استفاده مؤثر به برنامه ریزی و نظارت دقیق نیاز دارد.

به یاد داشته باشید: مانند آن فنجان قهوه عالی، نکته کلیدی یافتن تعادل مناسب – بین عملکرد، هزینه و پیچیدگی – است که برای موارد استفاده خاص شما مناسب است.

برای راهنمایی‌ها و بینش‌های بیشتر، من را در توییتر @Siddhant_K_code دنبال کنید و با جدیدترین و دقیق‌ترین محتوای فنی مانند این به‌روز باشید.

تصور کنید عجله دارید تا قهوه صبح خود را بنوشید، فقط متوجه می شوید که باریستا باید ابتدا دستگاه اسپرسوساز را راه اندازی کند. اساساً این همان چیزی است که در هنگام شروع سرد لامبدا اتفاق می افتد – و درست مانند تأخیر قهوه شما، می تواند ناامید کننده باشد. اما نترس! امروز ما عمیقاً به این خواهیم پرداخت که چگونه همزمانی ارائه شده می‌تواند به شما کمک کند تا این عملکردها را به صورت مستقیم انجام دهید.

درک مشکل شروع سرد

هنگامی که یک تابع Lambda اخیراً استفاده نشده است، AWS باید قبل از اجرای کد شما یک محیط اجرایی جدید را بچرخاند. این فرآیند اولیه سازی شامل:

  1. در حال دانلود کد شما
  2. بوت استرپ کردن زمان اجرا
  3. در حال بارگیری وابستگی های شما
  4. اجرای کد اولیه

در اینجا یک تابع ساده Node.js وجود دارد که تأثیر شروع سرد را نشان می دهد:

const mongoose = require('mongoose');

// This connection happens during cold start
let conn = null;

const connectToDb = async () => {
    if (conn == null) {
        conn = await mongoose.connect(process.env.MONGODB_URI, {
            serverSelectionTimeoutMS: 5000
        });
    }
    return conn;
};

exports.handler = async (event) => {
    // Connection time will impact cold start duration
    await connectToDb();

    // Rest of your handler code...
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در آزمایش من، این تابع ساده با اتصال پایگاه داده می تواند 800ms-2s برای شروع سرد طول بکشد، در مقایسه با 10-50ms برای شروع گرم.

همزمانی ارائه شده را وارد کنید

همزمانی ارائه شده مانند داشتن یک باریستا است که دستگاه اسپرسوساز را حتی در زمان های آرام کار می کند. مجموعه‌ای از محیط‌های اجرایی از پیش راه‌اندازی‌شده را برای پاسخگویی فوری به درخواست‌های دریافتی حفظ می‌کند.

برای فعال کردن آن با استفاده از AWS CDK:

const lambda = new lambda.Function(this, 'MyFunction', {
    runtime: lambda.Runtime.NODEJS_18_X,
    handler: 'index.handler',
    code: lambda.Code.fromAsset('lambda'),
    // Other configuration...
});

const version = lambda.currentVersion;
version.addProvisionedConcurrency(5); // Keep 5 instances warm
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

جادوی پشت صحنه

هنگامی که همزمانی ارائه شده را فعال می کنید، AWS کار هوشمندانه ای انجام می دهد:

  1. تعداد مشخصی از محیط های اجرایی را ایجاد می کند
  2. کد اولیه شما را اجرا می کند
  3. محیط ها را در حالت آماده منجمد می کند
  4. این استخر را حفظ می کند و جایگزین هر استخری می شود که ناسالم می شود

این بدان معناست که عملکرد شما تقریباً بلافاصله پس از راه‌اندازی شروع به اجرا می‌کند، زیرا بلند کردن سنگین قبلاً انجام شده است.

بهترین روش ها و نکات بهینه سازی

1. کد اولیه هوشمند

تا آنجا که ممکن است مقداردهی اولیه را به محدوده جهانی منتقل کنید:

// Good: Done once during provisioned concurrency initialization
const client = new AWS.DynamoDB.DocumentClient();
const tableName = process.env.TABLE_NAME;

// Bad: Would run on every invocation
exports.handler = async (event) => {
    const client = new AWS.DynamoDB.DocumentClient();
    // ...
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

2. سطوح همزمانی دقیق

اجرای همزمان عملکرد خود را با استفاده از معیارهای CloudWatch مانند ConcurrentExecutions و همزمانی ارائه شده را بر این اساس تنظیم کنید. تامین بیش از حد باعث هدر رفتن پول می شود، در حالی که تامین کم منجر به شروع سرد می شود.

3. استفاده از مقیاس خودکار برنامه

تنظیم مقیاس خودکار برای تنظیم خودکار همزمانی ارائه شده بر اساس استفاده:

const target = version.addAutoScaling({
    minCapacity: 2,
    maxCapacity: 10
});

target.scaleOnUtilization({
    utilizationTarget: 0.75,
    scaleInCooldown: Duration.seconds(60),
    scaleOutCooldown: Duration.seconds(60)
});
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ملاحظات هزینه

همزمانی ارائه شده رایگان نیست – شما برای:

  • زمانی که نمونه های ارائه شده شما در دسترس هستند
  • زمان محاسبه استفاده شده در طول اجرای تابع
  • هر نمونه اضافی که فراتر از مبلغ ارائه شده شما باشد

یک رویکرد عملی این است که:

  1. توابع حساس به تأخیر را شناسایی کنید
  2. الگوهای استفاده واقعی آنها را نظارت کنید
  3. همزمانی ارائه شده را به صورت انتخابی اعمال کنید
  4. برای الگوهای بار قابل پیش بینی از همزمانی برنامه ریزی شده استفاده کنید

اندازه گیری تاثیر

من یک چارچوب آزمایشی ساده برای اندازه گیری تفاوت ایجاد کردم:

import concurrent.futures
import requests
import time
import statistics

def invoke_function(url):
    start = time.time()
    response = requests.post(url)
    return time.time() - start

def run_load_test(url, concurrent_requests):
    with concurrent.futures.ThreadPoolExecutor(max_workers=concurrent_requests) as executor:
        futures = [executor.submit(invoke_function, url) for _ in range(concurrent_requests)]
        times = [f.result() for f in concurrent.futures.as_completed(futures)]

    return {
        'avg': statistics.mean(times),
        'p95': statistics.quantile(times, 0.95),
        'max': max(times)
    }

# Results with provisioned concurrency disabled
print("Without PC:", run_load_test(lambda_url, 100))

# Results with provisioned concurrency enabled
print("With PC:", run_load_test(lambda_url, 100))
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نتایج دنیای واقعی

در محیط های تولید، من دیده ام:

  • سرد شروع می شود از 1-2 ثانیه به زیر 100 میلی ثانیه کاهش یافت
  • P95 تاخیر تا 80٪ بهبود یافته است
  • عملکرد پایدارتر در هنگام افزایش ترافیک

فراتر از همزمانی ارائه شده

در حالی که همزمانی ارائه شده قدرتمند است، این استراتژی های مکمل را در نظر بگیرید:

  • استفاده از وابستگی های کوچکتر برای کاهش زمان اولیه سازی
  • پیاده سازی ادغام اتصال برای پایگاه های داده
  • استفاده از Lambda SnapStart برای توابع جاوا
  • استفاده از سرویس‌های کش خارجی برای داده‌های با دسترسی مکرر

نتیجه گیری

همزمانی ارائه شده ابزاری قدرتمند برای کاهش شروع سرد لامبدا است، اما برای استفاده مؤثر به برنامه ریزی و نظارت دقیق نیاز دارد.

به یاد داشته باشید: مانند آن فنجان قهوه عالی، نکته کلیدی یافتن تعادل مناسب – بین عملکرد، هزینه و پیچیدگی – است که برای موارد استفاده خاص شما مناسب است.


برای راهنمایی‌ها و بینش‌های بیشتر، من را در توییتر @Siddhant_K_code دنبال کنید و با جدیدترین و دقیق‌ترین محتوای فنی مانند این به‌روز باشید.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا