Azure Functions를 사용한 서버리스 이벤트 처리Serverless event processing using Azure Functions

이 참조 아키텍처는 데이터 스트림을 수집 하 고, 데이터를 처리 하 고, 백 엔드 데이터베이스에 결과를 기록 하는 서버를 사용 하지 않는 이벤트 구동 아키텍처를 보여 줍니다.This reference architecture shows a serverless, event-driven architecture that ingests a stream of data, processes the data, and writes the results to a back-end database.

GitHub 로고 이 아키텍처에 대 한 참조 구현은 github에서 사용할 수 있습니다.GitHub logo A reference implementation for this architecture is available on GitHub.

Azure Functions를 사용하여 서버리스 이벤트를 처리하기 위한 참조 아키텍처

ArchitectureArchitecture

Event Hubs 에서 데이터 스트림을 수집합니다.Event Hubs ingests the data stream. Event Hubs는 높은 처리량 데이터 스트리밍 시나리오를 위해 설계되었습니다.Event Hubs is designed for high-throughput data streaming scenarios.

참고

IoT 시나리오의 경우 IoT Hub를 사용하는 것이 좋습니다.For IoT scenarios, we recommend IoT Hub. IoT Hub에는 Azure Event Hubs API와 호환되는 기본 제공 엔드포인트가 있으므로 이 아키텍처에서는 백 엔드 처리를 크게 변경하지 않고도 두 가지 서비스 중 하나를 사용할 수 있습니다.IoT Hub has a built-in endpoint that’s compatible with the Azure Event Hubs API, so you can use either service in this architecture with no major changes in the backend processing. 자세한 내용은 IoT 디바이스를 Azure에 연결: IoT Hub 및 Event Hubs를 참조하세요.For more information, see Connecting IoT Devices to Azure: IoT Hub and Event Hubs.

함수 앱 .Function App . Azure Functions는 서버리스 컴퓨팅 옵션입니다.Azure Functions is a serverless compute option. 트리거를 통해 코드("함수")가 호출되는 이벤트 구동 모델을 사용합니다.It uses an event-driven model, where a piece of code (a “function”) is invoked by a trigger. 이 아키텍처에서는 이벤트가 Event Hubs에 도착하면 이벤트를 처리하고 결과를 스토리지에 쓰는 함수를 트리거합니다.In this architecture, when events arrive at Event Hubs, they trigger a function that processes the events and writes the results to storage.

함수 앱은 Event Hubs에서 개별 레코드를 처리하는 데 적합합니다.Function Apps are suitable for processing individual records from Event Hubs. 더 복잡한 스트림 처리 시나리오의 경우 Azure Databricks 또는 Azure Stream Analytics를 사용하는 Apache Spark를 고려해 보세요.For more complex stream processing scenarios, consider Apache Spark using Azure Databricks, or Azure Stream Analytics.

Cosmos DB .Cosmos DB . Cosmos DB 는 다중 모델 데이터베이스 서비스입니다.Cosmos DB is a multi-model database service. 이 시나리오의 경우 이벤트 처리 함수는 Cosmos DB SQL API를 사용하여 JSON 레코드를 저장합니다.For this scenario, the event-processing function stores JSON records, using the Cosmos DB SQL API.

큐 저장소 .Queue storage . Queue storage는 배달 못한 편지 메시지에 사용됩니다.Queue storage is used for dead letter messages. 이벤트를 처리하는 중에 오류가 발생하면 나중에 처리하기 위해 함수에서 이벤트 데이터를 배달 못한 편지 큐에 저장합니다.If an error occurs while processing an event, the function stores the event data in a dead letter queue for later processing. 자세한 내용은 복원력 고려 사항을 참조하세요.For more information, see Resiliency Considerations.

Azure MonitorAzure Monitor . Monitor는 솔루션에 배포된 Azure 서비스에 대한 성능 메트릭을 수집합니다.Monitor collects performance metrics about the Azure services deployed in the solution. 이러한 메트릭을 대시보드에서 시각화하여 솔루션의 상태를 볼 수 있습니다.By visualizing these in a dashboard, you can get visibility into the health of the solution.

Azure Pipelines .Azure Pipelines . Pipelines는 애플리케이션을 빌드, 테스트 및 배포하는 CI(지속적인 통합) 및 CD(지속적인 업데이트) 서비스입니다.Pipelines is a continuous integration (CI) and continuous delivery (CD) service that builds, tests, and deploys the application.

확장성 고려 사항Scalability considerations

Event HubsEvent Hubs

Event Hubs의 처리량 용량은 처리량 단위로 제어됩니다.The throughput capacity of Event Hubs is measured in throughput units. 자동 팽창을 사용하도록 설정하여 이벤트 허브를 자동 크기 조정할 수 있습니다. 그러면 트래픽에 따라 처리량 단위를 구성된 최댓값까지 자동으로 크기 조정합니다.You can autoscale an event hub by enabling auto-inflate, which automatically scales the throughput units based on traffic, up to a configured maximum.

함수 앱의 Event Hub 트리거는 이벤트 허브의 파티션 수에 따라 크기 조정됩니다.The Event Hub trigger in the function app scales according to the number of partitions in the event hub. 각 파티션에는 한 번에 하나의 함수 인스턴스가 할당됩니다.Each partition is assigned one function instance at a time. 처리량을 최대화하려면 한 번에 하나씩이 아니라 일괄 처리 방식으로 이벤트를 받습니다.To maximize throughput, receive the events in a batch, instead of one at a time.

Cosmos DBCosmos DB

Cosmos DB에 대한 처리량 용량은 RU(요청 단위)로 측정됩니다.Throughput capacity for Cosmos DB is measured in Request Units (RU). 1만 r u 이전의 Cosmos DB 컨테이너 크기를 조정 하려면 컨테이너를 만들 때 파티션 키 를 지정 하 고 사용자가 만드는 모든 문서에 파티션 키를 포함 해야 합니다.In order to scale a Cosmos DB container past 10,000 RU, you must specify a partition key when you create the container, and include the partition key in every document that you create.

적절한 파티션 키에 대한 몇 가지 특징은 다음과 같습니다.Here are some characteristics of a good partition key:

  • 키 값 공간이 큽니다.The key value space is large.
  • 바로 가기 키를 사용하지 않고도 값당 읽기/쓰기 수가 균등하게 분산됩니다.There will be an even distribution of reads/writes per key value, avoiding hot keys.
  • 단일 키 값에 저장되는 최대 데이터 크기는 최대 실제 파티션 크기(10GB)를 초과하지 않습니다.The maximum data stored for any single key value will not exceed the maximum physical partition size (10 GB).
  • 문서에 대한 파티션 키는 변경되지 않습니다.The partition key for a document won't change. 기존 문서의 파티션 키는 업데이트할 수 없습니다.You can't update the partition key on an existing document.

이 참조 아키텍처에 대한 시나리오에서 함수는 정확히 데이터를 보내는 디바이스당 하나의 문서를 저장합니다.In the scenario for this reference architecture, the function stores exactly one document per device that is sending data. 함수에서 지속적으로 upsert 작업을 사용하여 문서를 최신 디바이스 상태로 업데이트합니다.The function continually updates the documents with latest device status, using an upsert operation. 쓰기가 키 전체에 균등하게 분산되므로 디바이스 ID가 이 시나리오에 적합한 파티션 키이며, 각 키 값에 대해 하나의 문서가 있으므로 각 파티션의 크기가 엄격하게 제한됩니다.Device ID is a good partition key for this scenario, because writes will be evenly distributed across the keys, and the size of each partition will be strictly bounded, because there is a single document for each key value. 파티션 키에 대한 자세한 내용은 Azure Cosmos DB의 파티션 및 확장을 참조하세요.For more information about partition keys, see Partition and scale in Azure Cosmos DB.

복원력 고려 사항Resiliency considerations

Functions에서 Event Hubs 트리거를 사용하는 경우 처리 루프 내에서 예외를 catch합니다.When using the Event Hubs trigger with Functions, catch exceptions within your processing loop. 처리되지 않은 예외가 발생하면 Functions 런타임에서 메시지를 다시 시도하지 않습니다.If an unhandled exception occurs, the Functions runtime does not retry the messages. 메시지를 처리할 수 없는 경우, 배달 못한 편지 큐에 메시지를 넣습니다.If a message cannot be processed, put the message into a dead letter queue. 대역 외 프로세스를 사용하여 메시지를 검토하고 수정 작업을 결정합니다.Use an out-of-band process to examine the messages and determine corrective action.

다음 코드에서는 수집 함수에서 예외를 catch하고, 처리되지 않은 메시지를 배달 못한 편지 큐에 넣는 방법을 보여 줍니다.The following code shows how the ingestion function catches exceptions and puts unprocessed messages onto a dead letter queue.

[FunctionName("RawTelemetryFunction")]
[StorageAccount("DeadLetterStorage")]
public static async Task RunAsync(
    [EventHubTrigger("%EventHubName%", Connection = "EventHubConnection", ConsumerGroup ="%EventHubConsumerGroup%")]EventData[] messages,
    [Queue("deadletterqueue")] IAsyncCollector<DeadLetterMessage> deadLetterMessages,
    ILogger logger)
{
    foreach (var message in messages)
    {
        DeviceState deviceState = null;

        try
        {
            deviceState = telemetryProcessor.Deserialize(message.Body.Array, logger);
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Error deserializing message", message.SystemProperties.PartitionKey, message.SystemProperties.SequenceNumber);
            await deadLetterMessages.AddAsync(new DeadLetterMessage { Issue = ex.Message, EventData = message });
        }

        try
        {
            await stateChangeProcessor.UpdateState(deviceState, logger);
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Error updating status document", deviceState);
            await deadLetterMessages.AddAsync(new DeadLetterMessage { Issue = ex.Message, EventData = message, DeviceState = deviceState });
        }
    }
}

이 함수는 Queue storage 출력 바인딩을 사용하여 항목을 큐에 넣습니다.Notice that the function uses the Queue storage output binding to put items in the queue.

위에 표시된 코드는 예외를 Application Insights에 기록합니다.The code shown above also logs exceptions to Application Insights. 파티션 키와 시퀀스 번호를 사용하여 배달 못한 편지 메시지와 로그의 예외 사이의 상관 관계를 지정할 수 있습니다.You can use the partition key and sequence number to correlate dead letter messages with the exceptions in the logs.

배달 못한 편지 큐의 메시지에는 오류 컨텍스트를 이해할 수 있도록 충분한 정보가 있어야 합니다.Messages in the dead letter queue should have enough information so that you can understand the context of error. 다음 예제에서 DeadLetterMessage 클래스에는 예외 메시지, 원래 이벤트 데이터 및 역직렬화된 이벤트 메시지(사용 가능한 경우)가 포함됩니다.In this example, the DeadLetterMessage class contains the exception message, the original event data, and the deserialized event message (if available).

public class DeadLetterMessage
{
    public string Issue { get; set; }
    public EventData EventData { get; set; }
    public DeviceState DeviceState { get; set; }
}

Azure Monitor를 사용하여 이벤트 허브를 모니터링합니다.Use Azure Monitor to monitor the event hub. 입력은 있지만 출력이 없는 경우 메시지가 처리되고 있지 않음을 의미합니다.If you see there is input but no output, it means that messages are not being processed. 이 경우 Log Analytics로 이동하여 예외 또는 다른 오류를 찾습니다.In that case, go into Log Analytics and look for exceptions or other errors.

재해 복구 고려 사항Disaster recovery considerations

여기에 표시된 배포는 단일 Azure 지역에 있습니다.The deployment shown here resides in a single Azure region. 재해 복구에 더 탄력적인 방법을 적용하려면 다양한 서비스의 지리적 배포 기능을 활용합니다.For a more resilient approach to disaster-recovery, take advantage of geo-distribution features in the various services:

  • Event Hubs .Event Hubs . 두 개의 Event Hubs 네임스페이스, 즉 기본(활성) 네임스페이스 및 보조(수동) 네임스페이스를 만듭니다.Create two Event Hubs namespaces, a primary (active) namespace and a secondary (passive) namespace. 메시지는 보조 네임스페이스로 장애 조치하지 않는 한 자동으로 활성 네임스페이스로 라우팅됩니다.Messages are automatically routed to the active namespace unless you fail over to the secondary namespace. 자세한 내용은 Azure Event Hubs 지역 재해 복구를 참조하세요.For more information, see Azure Event Hubs Geo-disaster recovery.

  • 함수 앱 .Function App . 보조 Event Hubs 네임스페이스에서 읽기를 기다리는 두 번째 함수 앱을 배포합니다.Deploy a second function app that is waiting to read from the secondary Event Hubs namespace. 이 함수는 배달 못한 편지 큐에 대한 보조 스토리지 계정에 씁니다.This function writes to a secondary storage account for dead letter queue.

  • Cosmos DB .Cosmos DB . Cosmos DB은 Cosmos DB 계정에 추가 하는 모든 지역에 대 한 쓰기를 가능 하 게 하는 여러 쓰기 지역을지원 합니다.Cosmos DB supports multiple write regions, which enables writes to any region that you add to your Cosmos DB account. 다중 쓰기를 사용 하지 않는 경우에도 기본 쓰기 지역을 장애 조치할 수 있습니다.If you don’t enable multi-write, you can still fail over the primary write region. Cosmos DB 클라이언트 SDK 및 Azure Function 바인딩은 장애 조치를 자동으로 처리하므로 애플리케이션 구성 설정을 업데이트할 필요가 없습니다.The Cosmos DB client SDKs and the Azure Function bindings automatically handle the failover, so you don’t need to update any application configuration settings.

  • Azure Storage .Azure Storage . 배달 못한 편지 큐에 대해 RA-GRS 스토리지를 사용합니다.Use RA-GRS storage for the dead letter queue. 이렇게 하면 읽기 전용 복제본이 다른 지역에 만들어집니다.This creates a read-only replica in another region. 주 지역을 사용할 수 없게 되면 현재 큐에 있는 항목을 읽을 수 있습니다.If the primary region becomes unavailable, you can read the items currently in the queue. 또한 장애 조치 후에 함수에서 쓸 수 있는 다른 스토리지 계정을 보조 지역에 프로비전합니다.In addition, provision another storage account in the secondary region that the function can write to after a fail-over.

비용 고려 사항Cost considerations

Azure 가격 책정 계산기 를 사용 하 여 비용을 예측 합니다.Use the Azure Pricing calculator to estimates costs. 다음은 몇 가지 기타 고려 사항입니다.Here are some other considerations.

Azure 기능Azure Functions

Azure Functions는 두 가지 호스팅 모델을 지원합니다.Azure Functions supports two hosting models.

  • 소비 계획 .Consumption plan .

    코드를 실행할 때 Compute 전력이 자동으로 할당 됩니다.Compute power is automatically allocated when your code is running.

  • App Service 계획.App Service plan.

    코드에 대 한 Vm 집합이 할당 됩니다.A set of VMs are allocated for your code. App Service 계획은 VM의 수와 크기를 정의합니다.The App Service plan defines the number of VMs and the VM size.

이 아키텍처에서 Event Hubs에 도착 하는 각 이벤트는 해당 이벤트를 처리 하는 함수를 트리거합니다.In this architecture, each event that arrives on Event Hubs, triggers a function that processes that event. 비용 측면에서 사용 하는 계산 리소스에 대해서만 비용을 지불 하므로 소비 계획 을 사용 하는 것이 좋습니다.From a cost perspective, the recommendation is to use consumption plan because you pay only for the compute resources you use.

Azure Cosmos DBAzure Cosmos DB

프로 비전 된 처리량에 대 한 Azure Cosmos DB 및 시간별 저장소 사용Azure Cosmos DB bills for provisioned throughput and consumed storage by hour. 프로 비전 된 처리량은 삽입, 읽기와 같은 일반적인 데이터베이스 작업에 사용할 수 있는 초당 요청 단위 (r u/초)로 표시 됩니다.Provisioned throughput is expressed in Request Units per second (RU/s), which can be used for typical database operations, such as inserts, reads. 가격은 예약 하는 r u/초의 용량을 기준으로 합니다.The price is based on the capacity in RU/s that you reserve. 또한 1KB 문서에 대 한 동시 읽기는 1 r u를 사용 하는 컨테이너 당 최소 400 RUs를 예약 해야 합니다.Also, you have to reserve a minimum of 400 RUs per container, where a concurrent read of 1KB document consumes 1 RU. 앱이이를 많이 필요로 하지 않아도 되는 경우 각 컨테이너에 고정 비용이 있으므로 단일 컨테이너를 사용 하는 것이 좋습니다.If your app does not need to be this intensive, consider using a single container because each container has a fixed cost.

이 참조 아키텍처에서 함수는 데이터를 전송 하는 장치 마다 정확히 하나의 문서를 저장 합니다.In this reference architecture, the function stores exactly one document per device that is sending data. 함수는 소비 된 저장소 측면에서 비용 효율적인 upsert 작업을 사용 하 여 최신 장치 상태로 문서를 지속적으로 업데이트 합니다.The function continually updates the documents with latest device status, using an upsert operation, which is cost effective in terms of consumed storage. 자세한 내용은 Cosmos DB 가격 책정 모델을 참조 하세요.For more information, see Cosmos DB pricing model.

저장소에는 저장 된 데이터 및 인덱스에 사용 되는 각 GB에 대 한 요금이 청구 됩니다.Storage is billed for each GB used for your stored data and index.

작업 비용을 신속 하 게 예측 하려면 Cosmos DB 용량 계산기 를 사용 하세요.Use the Cosmos DB capacity calculator to get a quick estimate of the workload cost.

자세한 내용은 Microsoft Azure Well-Architected Framework의 Cost 섹션을 참조 하십시오.For more information, see the Cost section in Microsoft Azure Well-Architected Framework.

DevOps 고려 사항DevOps considerations

가능 하면 IaC (Infrastructure as code)를 사용 합니다.Use Infrastructure as code (IaC) when possible. IaC는 Azure Resource Manager와 같은 선언적 방식으로 인프라, 응용 프로그램 및 저장소 리소스를 관리 합니다.IaC manages the infrastructure, application, and storage resources with a declarative approach like Azure Resource Manager. 이는 DevOps를 사용 하 여 CI/CD (지속적인 통합 및 지속적인 업데이트) 솔루션으로 배포를 자동화 하는 데 도움이 됩니다.That will help in automating deployment using DevOps as a continuous integration and continuous delivery (CI/CD) solution. 템플릿은 릴리스 파이프라인의 일부로 버전을 지정 하 고 포함 해야 합니다.Templates should be versioned and included as part of the release pipeline.

템플릿을 만들 때 리소스를 작업 별로 구성 하 고 격리 하는 방법으로 그룹화 합니다.When creating templates, group resources as a way to organize and isolate them per workload. 워크 로드에 대해 생각 하는 일반적인 방법은 단일 serveless 응용 프로그램 또는 가상 네트워크입니다.A common way to think about workload is a single serveless application or a virtual network. 워크 로드 격리의 목표는 리소스를 팀에 연결 하 여 DevOps 팀이 해당 리소스의 모든 측면을 독립적으로 관리 하 고 CI/CD를 수행할 수 있도록 하는 것입니다.The goal of workload isolation is to associate the resources to a team, so that the DevOps team can independently manage all aspects of those resources and perform CI/CD.

이 아키텍처에는 YAML 및 Azure Functions 슬롯과 Azure Pipelines를 사용 하 함수 앱 Drone 상태를 구성 하는 단계가 포함 되어 있습니다.This architecture includes steps to configure the Drone Status Function App using Azure Pipelines with YAML and Azure Functions Slots.

서비스를 배포할 때이를 모니터링 해야 합니다.As you deploy your services you will need to monitor them. Application Insights 를 사용 하 여 개발자가 성능을 모니터링 하 고 문제를 검색할 수 있도록 하는 것이 좋습니다.Consider using Application Insights to enable the developers to monitor performance and detect issues.

자세한 내용은 Microsoft Azure Well-Architected Framework의 devops 섹션을 참조 하십시오.For more information, see the DevOps section in Microsoft Azure Well-Architected Framework.

솔루션 배포Deploy the solution

이 참조 아키텍처를 배포하기 위해 GitHub 추가 정보를 확인합니다.To deploy this reference architecture, view the GitHub readme.

다음 단계Next steps

참조 구현에 대 한 자세한 내용을 보려면 코드 연습: 서버를 사용 하지 않는 응용 프로그램 Azure Functions를 참조 하세요.To learn more about the reference implementation, read Code walkthrough: Serverless application with Azure Functions.