다음을 통해 공유


자습서: .NET 앱에서 푸시 새로 고침을 사용하여 동적 구성 사용

App Configuration .NET 클라이언트 라이브러리는 요청 시 애플리케이션을 다시 시작하지 않고도 구성을 업데이트할 수 있습니다. 다음 두 가지 방법 중 하나 또는 둘 모두를 사용하여 App Configuration의 변경 내용을 검색하도록 애플리케이션을 구성할 수 있습니다.

  1. 폴링 모델: 폴링을 사용하여 구성 변경 내용을 검색하는 기본 동작입니다. 설정의 캐시된 값이 만료되면 TryRefreshAsync 또는 RefreshAsync에 대한 다음 호출이 서버에 요청을 보내서 구성이 변경되었는지 확인하고, 필요한 경우 업데이트된 구성을 끌어옵니다.

  2. 푸시 모델: App Configuration 이벤트를 사용하여 구성 변경 내용을 검색합니다. Azure Event Grid에 키 값 변경 이벤트를 보내도록 App Configuration이 설정되면 애플리케이션은 이러한 이벤트를 사용하여 구성을 업데이트된 상태로 유지하는 데 필요한 총 요청 수를 최적화할 수 있습니다. 애플리케이션은 Event Grid에서 직접 구독하거나 지원되는 이벤트 처리기(예: 웹후크, Azure 함수 또는 Service Bus 토픽) 중 하나를 통해 구독하도록 선택할 수 있습니다.

이 자습서에서는 푸시 새로 고침을 사용하여 코드에서 동적 구성 업데이트를 구현하는 방법을 보여줍니다. 자습서에 소개된 앱을 기반으로 합니다. 계속하기 전에 자습서를 완료합니다. 먼저 .NET 앱에서 동적 구성을 사용합니다.

이 자습서의 단계는 임의의 코드 편집기를 사용하여 수행할 수 있습니다. Visual Studio Code는 Windows, macOS 및 Linux 플랫폼에서 사용할 수 있는 훌륭한 옵션입니다.

이 자습서에서는 다음을 하는 방법을 알아볼 수 있습니다.

  • App Configuration에서 Service Bus 토픽으로 구성 변경 이벤트를 보내도록 구독 설정
  • App Configuration의 변경에 대한 응답으로 구성을 업데이트하도록 .NET 앱 설정
  • 애플리케이션의 최신 구성을 사용합니다.

필수 조건

Azure Service Bus 토픽 및 구독 설정

이 자습서에서는 Event Grid용 Service Bus 통합을 사용하여 변경 사항에 대해 App Configuration을 지속적으로 폴링하지 않으려는 애플리케이션에 대한 구성 변경 사항을 검색하는 작업을 간소화합니다. Azure Service Bus SDK는 App Configuration에서 변경 사항이 검색되면 구성을 업데이트하는 데 사용할 수 있는 메시지 처리기를 등록하는 API를 제공합니다. 빠른 시작: Azure Portal을 사용하여 Service Bus 토픽 및 구독 만들기의 단계에 따라 Service Bus 네임스페이스, 토픽 및 구독을 만듭니다.

리소스를 만들었으면 다음 환경 변수를 추가합니다. 이러한 항목은 애플리케이션 코드의 구성 변경에 대한 이벤트 처리기를 등록하는 데 사용됩니다.

ServiceBusConnectionString Service Bus 네임스페이스에 대한 연결 문자열
ServiceBusTopic Service Bus 토픽의 이름
ServiceBusSubscription Service Bus 구독의 이름

이벤트 구독 설정

  1. Azure Portal에서 App Configuration 리소스를 열고 Events 창에서 + Event Subscription을 클릭합니다.

    App Configuration 이벤트

  2. Event SubscriptionSystem Topic에 대한 이름을 입력합니다.

    이벤트 구독 만들기

  3. Endpoint TypeService Bus Topic으로 선택하고 Service Bus 토픽을 선택한 다음, Confirm Selection을 클릭합니다.

    이벤트 구독 Service Bus 엔드포인트

  4. Create를 클릭하여 구독을 만듭니다.

  5. Events 창에서 Event Subscriptions를 클릭하여 구독이 성공적으로 만들어졌는지 확인합니다.

    App Configuration 이벤트 구독

참고 항목

구성 변경을 구독할 때는 하나 이상의 필터를 사용하여 애플리케이션으로 전송되는 이벤트 수를 줄일 수 있습니다. 이러한 필터는 Event Grid 구독 필터 또는 Service Bus 구독 필터로 구성할 수 있습니다. 예를 들어 구독 필터는 특정 문자열로 시작하는 키에 대한 변경의 이벤트만 구독하는 데 사용할 수 있습니다.

App Configuration에서 데이터를 다시 로드하는 이벤트 처리기 등록

Program.cs를 열고 이 파일을 다음 코드로 업데이트합니다.

using Azure.Messaging.EventGrid;
using Azure.Messaging.ServiceBus;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.AzureAppConfiguration;
using Microsoft.Extensions.Configuration.AzureAppConfiguration.Extensions;
using System;
using System.Threading.Tasks;

namespace TestConsole
{
    class Program
    {
        private const string AppConfigurationConnectionStringEnvVarName = "AppConfigurationConnectionString";
        // e.g. Endpoint=https://{store_name}.azconfig.io;Id={id};Secret={secret}
        
        private const string ServiceBusConnectionStringEnvVarName = "ServiceBusConnectionString";
        // e.g. Endpoint=sb://{service_bus_name}.servicebus.windows.net/;SharedAccessKeyName={key_name};SharedAccessKey={key}
        
        private const string ServiceBusTopicEnvVarName = "ServiceBusTopic";
        private const string ServiceBusSubscriptionEnvVarName = "ServiceBusSubscription";

        private static IConfigurationRefresher _refresher = null;

        static async Task Main(string[] args)
        {
            string appConfigurationConnectionString = Environment.GetEnvironmentVariable(AppConfigurationConnectionStringEnvVarName);

            IConfiguration configuration = new ConfigurationBuilder()
                .AddAzureAppConfiguration(options =>
                {
                    options.Connect(appConfigurationConnectionString);
                    options.ConfigureRefresh(refresh =>
                        refresh
                            .Register("TestApp:Settings:Message")
                            // Important: Reduce poll frequency
                            .SetCacheExpiration(TimeSpan.FromDays(1))  
                    );

                    _refresher = options.GetRefresher();
                }).Build();

            await RegisterRefreshEventHandler();
            var message = configuration["TestApp:Settings:Message"];
            Console.WriteLine($"Initial value: {configuration["TestApp:Settings:Message"]}");

            while (true)
            {
                await _refresher.TryRefreshAsync();

                if (configuration["TestApp:Settings:Message"] != message)
                {
                    Console.WriteLine($"New value: {configuration["TestApp:Settings:Message"]}");
                    message = configuration["TestApp:Settings:Message"];
                }

                await Task.Delay(TimeSpan.FromSeconds(1));
            }
        }

        private static async Task RegisterRefreshEventHandler()
        {
            string serviceBusConnectionString = Environment.GetEnvironmentVariable(ServiceBusConnectionStringEnvVarName);
            string serviceBusTopic = Environment.GetEnvironmentVariable(ServiceBusTopicEnvVarName);
            string serviceBusSubscription = Environment.GetEnvironmentVariable(ServiceBusSubscriptionEnvVarName); 
            ServiceBusClient serviceBusClient = new ServiceBusClient(serviceBusConnectionString);
            ServiceBusProcessor serviceBusProcessor = serviceBusClient.CreateProcessor(serviceBusTopic, serviceBusSubscription);

            serviceBusProcessor.ProcessMessageAsync += (processMessageEventArgs) =>
            {
                // Build EventGridEvent from notification message
                EventGridEvent eventGridEvent = EventGridEvent.Parse(BinaryData.FromBytes(processMessageEventArgs.Message.Body));

                // Create PushNotification from eventGridEvent
                eventGridEvent.TryCreatePushNotification(out PushNotification pushNotification);

                // Prompt Configuration Refresh based on the PushNotification
                _refresher.ProcessPushNotification(pushNotification);

                return Task.CompletedTask;
            };

            serviceBusProcessor.ProcessErrorAsync += (exceptionargs) =>
            {
                Console.WriteLine($"{exceptionargs.Exception}");
                return Task.CompletedTask;
            };

            await serviceBusProcessor.StartProcessingAsync();
        }
    }
}

ProcessPushNotification 메서드는 캐시 만료를 짧은 임의 연기로 초기화합니다. 이로 인해 나중에 App Configuration에 대해 캐시된 값의 유효성을 다시 검사하기 위한 RefreshAsync 또는 TryRefreshAsync을(를) 호출하고 필요에 따라 업데이트합니다. 이 예제에서는 키의 변경 내용을 모니터링하기 위해 등록합니다. TestApp:설정:1일의 캐시 만료가 있는 메시지입니다. 즉, 마지막 검사 이후 하루가 지나기 전에 App Configuration에 대한 요청이 수행되지 않습니다. ProcessPushNotification을(를) 호출하면 애플리케이션이 몇 초 안에 App Configuration에 요청을 보냅니다. 애플리케이션은 업데이트를 지속적으로 폴링할 필요 없이 App Configuration 저장소에서 변경이 발생한 직후에 새 구성 값을 로드합니다. 애플리케이션이 어떤 이유로든 변경 알림을 누락하는 경우 구성 변경 내용을 하루에 한 번 확인합니다.

푸시 모델을 사용하여 동일한 App Configuration 저장소에 연결하는 애플리케이션 또는 마이크로 서비스의 인스턴스가 많은 경우 캐시 만료에 대한 짧은 임의 연기가 유용합니다. 이 연기가 없으면 애플리케이션의 모든 인스턴스가 변경 알림을 받는 즉시 App Configuration 저장소에 요청을 동시에 보낼 수 있습니다. 이로 인해 App Configuration Service에서 저장소를 제한할 수 있습니다. 캐시 만료 연기는 기본값으로 0에서 최대 30초 사이의 난수로 설정되지만 선택적 매개 변수 maxDelay을(를) 통해 최대값을 ProcessPushNotification 메서드로 변경할 수 있습니다.

ProcessPushNotification 메서드는 App Configuration의 변경 내용으로 인해 푸시 알림이 트리거된 정보가 포함된 PushNotification 개체를 사용합니다. 이렇게 하면 트리거 이벤트까지의 모든 구성 변경 내용이 다음 구성 새로 고침에 로드되도록 할 수 있습니다. SetDirty 메서드는 즉시 구성 새로 고침에 로드되도록 푸시 알림을 트리거하는 변경 사항을 보장하지 않습니다. 푸시 모델에 SetDirty 메서드를 사용하는 경우 대신 ProcessPushNotification 메서드를 사용하는 것이 좋습니다.

로컬로 앱 빌드 및 실행

  1. AppConfigurationConnectionString이라는 환경 변수를 설정하고, App Configuration 저장소에 대한 액세스 키로 설정합니다.

    Windows 명령 프롬프트를 사용하여 로컬에서 앱을 빌드하고 실행하는 경우 다음 명령을 실행하고, 명령 프롬프트를 다시 시작하여 변경 내용을 적용합니다.

    setx AppConfigurationConnectionString "<connection-string-of-your-app-configuration-store>"
    
  2. 다음 명령을 실행하여 콘솔 앱을 빌드합니다.

    dotnet build
    
  3. 빌드가 성공적으로 완료되면 다음 명령을 실행하여 앱을 로컬로 실행합니다.

    dotnet run
    

    업데이트 전 푸시 새로 고침 실행

  4. Azure Portal에 로그인합니다. 모든 리소스를 선택하고, 빠른 시작에서 만든 App Configuration 저장소 인스턴스를 선택합니다.

  5. 구성 탐색기를 선택하고, 다음 키의 값을 업데이트합니다.

    TestApp:Settings:Message Azure App Configuration의 데이터 - 업데이트됨
  6. 이벤트가 처리될 때까지 잠시 기다립니다. 업데이트된 구성이 표시됩니다.

    업데이트 후 푸시 새로 고침 실행

리소스 정리

이 문서에서 만든 리소스를 계속 사용하지 않으려면 여기서 만든 리소스 그룹을 삭제하여 요금이 부과되지 않도록 합니다.

Important

리소스 그룹을 삭제하면 다시 되돌릴 수 없습니다. 리소스 그룹 및 포함된 모든 리소스가 영구적으로 삭제됩니다. 잘못된 리소스 그룹 또는 리소스를 자동으로 삭제하지 않도록 합니다. 유지하려는 다른 리소스가 포함된 리소스 그룹 내에서 이 문서에 대한 리소스를 만든 경우 리소스 그룹을 삭제하는 대신 해당 창에서 각 리소스를 개별적으로 삭제합니다.

  1. Azure Portal에 로그인하고 리소스 그룹을 선택합니다.
  2. 이름으로 필터링 상자에서 리소스 그룹의 이름을 입력합니다.
  3. 결과 목록에서 리소스 그룹 이름을 선택하여 개요를 확인합니다.
  4. 리소스 그룹 삭제를 선택합니다.
  5. 리소스 그룹 삭제를 확인하는 메시지가 표시됩니다. 리소스 그룹의 이름을 입력하여 확인하고 삭제를 선택합니다.

잠시 후, 리소스 그룹 및 모든 해당 리소스가 삭제됩니다.

다음 단계

이 자습서에서는 .NET 앱을 사용하도록 설정하여 App Configuration에서 구성 설정을 동적으로 새로 고칩니다. Azure 관리 ID를 사용하여 App Configuration에 대한 액세스를 간소화하는 방법을 알아보려면 다음 자습서를 계속 진행하세요.