Реалізація Serverless Warming для зниження латентності

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація Serverless Warming для зниження латентності
Середня
від 1 робочого дня до 3 робочих днів
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Реалізація Serverless Warming для зменшення латентності

Cold start — головна проблема serverless функцій в latency-sensitive приложеннях. Перший виклик після періоду бездіяльності займає 200ms-2s залежно від runtime, розміру пакета та конфігурації. Для API, що обробляє реальні запити користувачів, це неприйнятно. Warming вирішує проблему, підтримуючи функції «гарячими».

Природа cold start

Що відбувається при cold start:

  1. Хмара знаходить доступний контейнер/VM
  2. Завантажує образ функції
  3. Ініціалізує runtime (Node.js, Python, JVM)
  4. Виконує initialization code (поза handler)
  5. Виконує handler

Кроки 1-4 — overhead cold start. Кроки 1-3 контролює провайдер, кроки 4-5 — розробник.

Типові часи cold start:

  • Python 3.12 (AWS Lambda, 256MB) — 200-400ms
  • Node.js 20 — 100-300ms
  • Java 17 — 800ms-2s (JVM startup)
  • Go — 50-150ms

Scheduled Warming

Найпростіший підхід: запускати функцію кожні 5 хвилин через CloudWatch Events / EventBridge, щоб вона не остигала.

# lambda_warmer.py — ping-функція
import json

def handler(event, context):
    if event.get('source') == 'warming':
        # Це ping від warmers, не реальний запит
        return {'statusCode': 200, 'body': json.dumps({'warm': True})}

    # Реальна логіка функції
    return process_request(event)
# Terraform: CloudWatch rule для warming
resource "aws_cloudwatch_event_rule" "warmer" {
  name                = "lambda-warmer"
  schedule_expression = "rate(5 minutes)"
}

resource "aws_cloudwatch_event_target" "warmer" {
  rule  = aws_cloudwatch_event_rule.warmer.name
  arn   = aws_lambda_function.api.arn
  input = jsonencode({"source": "warming"})
}

Обмеження: кожен EventBridge trigger запускає лише один concurrent інстанс. При кількох бажаних гарячих інстансах потрібно N паралельних викликів.

Warming кількох паралельних інстансів

import boto3
import asyncio

lambda_client = boto3.client('lambda')

async def warm_instance(function_name: str, instance_num: int):
    lambda_client.invoke(
        FunctionName=function_name,
        InvocationType='RequestResponse',
        Payload=json.dumps({
            'source': 'warming',
            'instance': instance_num,
            'sleep': 10  # Тримаємо інстанс занятим 10 секунд
        })
    )

async def warm_function(function_name: str, concurrent_count: int = 5):
    """Запустити N паралельних warmup викликів"""
    tasks = [warm_instance(function_name, i) for i in range(concurrent_count)]
    await asyncio.gather(*tasks)

Поки один виклик тримає інстанс занятим (sleep 10s), Lambda створює новий контейнер для наступного паралельного виклику. Результат: 5 гарячих інстансів.

AWS Lambda Provisioned Concurrency

Офіційне рішення від AWS: резервування ініціалізованих інстансів. За доплату, але гарантує P99 latency без cold start.

resource "aws_lambda_provisioned_concurrency_config" "api" {
  function_name                  = aws_lambda_function.api.function_name
  qualifier                      = aws_lambda_alias.live.name
  provisioned_concurrent_executions = 5
}

Auto Scaling Provisioned Concurrency — масштабувати провіжніннінг за розкладом (вранці більше, вночі менше):

resource "aws_appautoscaling_target" "lambda_pc" {
  max_capacity       = 20
  min_capacity       = 2
  resource_id        = "function:${aws_lambda_function.api.function_name}:live"
  scalable_dimension = "lambda:function:ProvisionedConcurrency"
  service_namespace  = "lambda"
}

resource "aws_appautoscaling_policy" "lambda_pc_tracking" {
  policy_type        = "TargetTrackingScaling"
  resource_id        = aws_appautoscaling_target.lambda_pc.resource_id
  scalable_dimension = aws_appautoscaling_target.lambda_pc.scalable_dimension
  service_namespace  = aws_appautoscaling_target.lambda_pc.service_namespace

  target_tracking_scaling_policy_configuration {
    target_value = 0.7  # 70% utilization провіжніннінгу
    predefined_metric_specification {
      predefined_metric_type = "LambdaProvisionedConcurrencyUtilization"
    }
  }
}

Оптимізація initialization code

Warming допомагає, але зменшення самого cold start — краща стратегія:

# ПЛОХО: створювати клієнти всередині handler
def handler(event, context):
    dynamodb = boto3.resource('dynamodb')  # Кожен cold start
    db_client = psycopg2.connect(DSN)      # Створює connection
    ...

# ХОРОШО: створювати клієнти на рівні модуля (один раз)
import boto3
import psycopg2

dynamodb = boto3.resource('dynamodb')  # Ініціалізується при cold start
_connection = None  # Lazy connection pool

def get_connection():
    global _connection
    if _connection is None or _connection.closed:
        _connection = psycopg2.connect(DSN)
    return _connection

def handler(event, context):
    conn = get_connection()  # Переиспользує існуюче соединення
    ...

Lambda SnapStart (Java)

AWS Lambda SnapStart для Java: створює снапшот ініціалізованого стану функції. Cold start для Java скорочується з 1-2s до 100-200ms.

resource "aws_lambda_function" "java_api" {
  ...
  snap_start {
    apply_on = "PublishedVersions"
  }
}

Терміни реалізації

  • Scheduled warming (EventBridge) — 0.5 дня
  • Parallel warming скрипт — 1 день
  • Provisioned Concurrency + Auto Scaling — 1-2 дні
  • Оптимізація initialization code — 1-3 дні (залежить від кодової бази)