.NET용 Azure Service Bus 클라이언트 라이브러리 - 버전 7.13.1

Azure Service Bus 사용하면 매우 신뢰할 수 있는 서비스를 사용하여 비동기 메시징 패턴을 활용하여 생산자와 소비자 간의 메시지를 중개하는 애플리케이션을 빌드할 수 있습니다. Azure Service Bus 복잡한 라우팅을 통해 구조화된 FIFO(선점) 메시징과 함께 클라이언트와 서버 간에 유연하고 조정된 메시징을 제공하고 게시/구독 기능을 제공합니다. Azure Service Bus 대해 자세히 알아보려면 다음을 검토할 수 있습니다. Azure Service Bus 무엇인가요?

Azure Service Bus 클라이언트 라이브러리를 사용하여 다음을 수행합니다.

  • 비즈니스 데이터 전송: 판매 또는 구매 주문, 저널 또는 재고 이동과 같은 지속적인 정보 교환을 위해 메시징을 활용합니다.

  • 애플리케이션 분리: 애플리케이션 및 서비스의 안정성과 확장성을 개선하여 발신자와 수신자가 동시에 온라인 상태여야 하는 필요성을 완화합니다.

  • 메시지 처리 방법 제어: 큐를 사용하는 메시지에 대해 기존 경쟁 소비자를 지원하거나 각 소비자가 topics 및 구독을 사용하여 메시지의 자체 instance 허용합니다.

  • 복잡한 워크플로 구현: 메시지 세션은 메시지 순서 또는 메시지 지연이 필요한 시나리오를 지원합니다.

소스 코드 | 패키지(NuGet) | API 참조 설명서 | 제품 설명서 | 마이그레이션 가이드 | 문제 해결 가이드

시작

필수 조건

  • Microsoft Azure 구독: Azure Service Bus 포함하여 Azure 서비스를 사용하려면 구독이 필요합니다. 기존 Azure 계정이 없는 경우 무료 평가판에 등록하거나 계정을 만들 때 MSDN 구독자 혜택을 사용할 수 있습니다.

  • Service Bus 네임스페이스: Azure Service Bus 상호 작용하려면 네임스페이스도 사용할 수 있어야 합니다. Azure 리소스를 만드는 데 익숙하지 않은 경우 Azure Portal 사용하여 Service Bus 네임스페이스를 만들기 위한 단계별 가이드를 따를 수 있습니다. 또한 Azure CLI, Azure PowerShell 또는 ARM(Azure Resource Manager) 템플릿을 사용하여 Service Bus 엔터티를 만들기 위한 자세한 지침을 찾을 수 있습니다.

  • C# 8.0: Azure Service Bus 클라이언트 라이브러리는 C# 8.0에 도입된 새로운 기능을 사용합니다. C# 8.0 구문을 활용하려면 언어 버전latest이 인 .NET Core SDK 3.0 이상을 사용하여 컴파일하는 것이 좋습니다.

    C# 8.0 구문을 최대한 활용하려는 Visual Studio 사용자는 Visual Studio 2019 이상을 사용해야 합니다. 체험 Community 버전을 비롯한 Visual Studio 2019는 여기서 다운로드할 수 있습니다. Visual Studio 2017 사용자는 Microsoft.Net.Compilers NuGet 패키지를 사용하고 언어 버전을 설정하여 C# 8 구문을 활용할 수 있지만 편집 환경은 적합하지 않을 수 있습니다.

    이전 C# 언어 버전에서 라이브러리를 계속 사용할 수 있지만 새 구문의 이점을 활용하지 않고 비동기 열거 가능 및 비동기 일회용 멤버를 수동으로 관리해야 합니다. 이전 버전의 .NET Core 또는 .NET Framework를 포함하여 .NET Core SDK에서 지원하는 프레임워크 버전을 계속 대상으로 지정할 수 있습니다. 자세한 내용은 대상 프레임워크를 지정하는 방법을 참조하세요.

    중요 참고 사항:예제샘플을 수정하지 않고 빌드하거나 실행하려면 C# 8.0을 사용해야 합니다. 다른 언어 버전에 맞게 조정하려는 경우에도 샘플을 실행할 수 있습니다.

Azure에서 필요한 Service Bus 리소스를 빠르게 만들고 이에 대한 연결 문자열을 받으려면 다음을 클릭하여 샘플 템플릿을 배포할 수 있습니다.

Azure에 배포

패키지 설치

NuGet을 사용하여 .NET용 Azure Service Bus 클라이언트 라이브러리를 설치합니다.

dotnet add package Azure.Messaging.ServiceBus

클라이언트 인증

Service Bus 클라이언트 라이브러리가 큐 또는 토픽과 상호 작용하려면 연결하고 권한을 부여하는 방법을 이해해야 합니다. 이를 위한 가장 쉬운 방법은 Service Bus 네임스페이스를 만들 때 자동으로 만들어지는 연결 문자열을 사용하는 것입니다. Azure의 공유 액세스 정책에 익숙하지 않은 경우 단계별 가이드에 따라 Service Bus 연결 문자열을 가져올 수 있습니다.

연결 문자열이 있으면 클라이언트를 인증할 수 있습니다.

// Create a ServiceBusClient that will authenticate using a connection string
string connectionString = "<connection_string>";
await using var client = new ServiceBusClient(connectionString);

Azure.Identity를 사용하여 인증하는 방법을 보려면 이 예제를 참조 하세요.

사용자 지정 엔드포인트를 사용하여 연결을 시작하는 방법을 보려면 이 샘플을 참조하세요.

ASP.NET Core

ASP.NET Core 앱에 종속성으로 삽입 ServiceBusClient 하려면 ASP.NET Core 패키지용 Azure 클라이언트 라이브러리 통합을 설치합니다.

dotnet add package Microsoft.Extensions.Azure

그런 다음, 메서드에 클라이언트를 등록합니다 Startup.ConfigureServices .

public void ConfigureServices(IServiceCollection services)
{
    services.AddAzureClients(builder =>
    {
        builder.AddServiceBusClient(Configuration.GetConnectionString("ServiceBus"));
    });
  
    services.AddControllers();
}

위의 코드를 사용하려면 구성에 다음을 추가합니다.

{
  "ConnectionStrings": {
    "ServiceBus": "<connection_string>"
  }
}

자세한 내용은 .NET용 Azure SDK를 사용하여 종속성 주입을 참조하세요.

주요 개념

를 초기화 ServiceBusClient한 후에는 Service Bus 네임스페이스 내의 기본 리소스 유형과 상호 작용할 수 있으며, 그 중 여러 리소스가 존재할 수 있으며 실제 메시지 전송이 수행되는 경우 네임스페이스는 애플리케이션 컨테이너로 사용되는 경우가 많습니다.

  • : 메시지 보내기 및 수신을 허용합니다. 지점 간 통신에 자주 사용됩니다.

  • 토픽: 큐와 달리 토픽은 시나리오를 게시/구독하는 데 더 적합합니다. 토픽을 보낼 수 있지만 구독이 필요하며, 그 중 여러 항목을 병렬로 사용할 수 있어야 합니다.

  • 구독: 토픽에서 사용하는 메커니즘입니다. 각 구독은 독립적이며 토픽에 전송된 각 메시지의 복사본을 받습니다. 규칙 및 필터를 사용하여 특정 구독에서 수신되는 메시지를 조정할 수 있습니다.

이러한 리소스에 대한 자세한 내용은 Azure Service Bus?을 참조하세요.

이러한 리소스와 상호 작용하려면 다음 SDK 개념에 익숙해야 합니다.

  • Service Bus 클라이언트는 Service Bus 클라이언트 라이브러리와 상호 작용하는 개발자를 위한 기본 인터페이스입니다. 라이브러리와의 모든 상호 작용이 발생하는 게이트웨이 역할을 합니다.

  • Service Bus 발신자는 특정 큐 또는 토픽으로 범위가 지정되며 Service Bus 클라이언트를 사용하여 만들어집니다. 발신자를 사용하면 큐 또는 토픽에 메시지를 보낼 수 있습니다. 또한 지정된 날짜에 메시지를 배달할 수 있도록 예약할 수 있습니다.

  • Service Bus 수신기는 특정 큐 또는 구독으로 범위가 지정되며 Service Bus 클라이언트를 사용하여 만들어집니다. 수신기를 사용하면 큐 또는 구독에서 메시지를 받을 수 있습니다. 또한 메시지를 받은 후 메시지를 정정할 수 있습니다. 메시지를 해결하는 방법에는 네 가지가 있습니다.

    • 완료 - 큐 또는 토픽에서 메시지를 삭제합니다.
    • 중단 - 다른 수신자가 메시지를 받을 수 있도록 메시지에 대한 수신자의 잠금을 해제합니다.
    • 연기 - 정상적인 수단으로 메시지가 수신되지 않도록 연기합니다. 지연된 메시지를 받으려면 메시지의 시퀀스 번호를 보존해야 합니다.
    • DeadLetter - 메시지를 배달 못한 편지 큐로 이동합니다. 이렇게 하면 메시지가 다시 수신되지 않습니다. 배달 못 한 편지 큐에서 메시지를 받으려면 배달 못 한 편지 큐로 범위가 지정된 수신자가 필요합니다.
  • Service Bus 세션 수신기는 특정 세션 사용 큐 또는 구독으로 범위가 지정되며 Service Bus 클라이언트를 사용하여 만들어집니다. 세션 수신기는 표준 수신기와 거의 동일하며, 세션 관리 작업이 세션 사용 엔터티에만 적용되는 노출된다는 차이점이 있습니다. 이러한 작업에는 세션 상태 가져오기 및 설정과 세션 잠금 갱신이 포함됩니다.

  • Service Bus 프로세서는 특정 큐 또는 구독으로 범위가 지정되며 Service Bus 클라이언트를 사용하여 만들어집니다. 는 ServiceBusProcessor 수신기 집합을 추상화로 간주할 수 있습니다. 콜백 모델을 사용하여 메시지를 받을 때와 예외가 발생할 때 코드를 지정할 수 있도록 합니다. 처리된 메시지의 자동 완성, 자동 메시지 잠금 갱신 및 사용자 지정 이벤트 처리기의 동시 실행을 제공합니다. 기능 집합으로 인해 Service Bus 엔터티에서 수신하는 애플리케이션을 작성하기 위한 이동 도구여야 합니다. ServiceBusReceiver는 프로세서가 ServiceBusReceiver를 직접 사용할 때 기대할 수 있는 세분화된 컨트롤을 제공할 수 없는 보다 복잡한 시나리오에 권장됩니다.

  • Service Bus 세션 프로세서는 특정 세션 사용 큐 또는 구독으로 범위가 지정되며 Service Bus 클라이언트를 사용하여 만들어집니다. 세션 프로세서는 표준 프로세서와 거의 동일하며, 세션 관리 작업이 세션 사용 엔터티에만 적용되는 노출된다는 차이점이 있습니다.

더 많은 개념과 심층적인 논의는 Service Bus 고급 기능을 참조하세요.

클라이언트 수명

ServiceBusClient, 보낸 사람, 수신자 및 프로세서는 메시지를 정기적으로 보내거나 받을 때 모범 사례인 애플리케이션 수명 동안 캐시하고 싱글톤으로 사용하는 것이 안전합니다. 네트워크, CPU 및 메모리 사용을 효율적으로 관리하여 비활성 기간 동안 사용량을 낮게 유지합니다.

이러한 형식은 삭제 가능하며 네트워크 리소스 및 기타 관리되지 않는 개체가 제대로 정리되도록 하려면 또는 CloseAsync 중 하나를 DisposeAsync 호출해야 합니다. ServiceBusClient instance 삭제되면 이를 사용하여 만든 보낸 사람, 수신기 및 프로세서를 자동으로 닫고 정리합니다.

스레드로부터의 안전성

모든 클라이언트 instance 메서드는 스레드로부터 안전하고 서로 독립적임을 보장합니다(지침). 이렇게 하면 스레드 간에 클라이언트 인스턴스를 다시 사용하는 것이 항상 안전합니다.

추가 개념

클라이언트 옵션 | 진단 | 조롱

예제

메시지 보내기 및 받기

메시지 전송은 를 사용하여 수행됩니다 ServiceBusSender. 수신은 를 사용하여 수행됩니다 ServiceBusReceiver.

string connectionString = "<connection_string>";
string queueName = "<queue_name>";
// since ServiceBusClient implements IAsyncDisposable we create it with "await using"
await using var client = new ServiceBusClient(connectionString);

// create the sender
ServiceBusSender sender = client.CreateSender(queueName);

// create a message that we can send. UTF-8 encoding is used when providing a string.
ServiceBusMessage message = new ServiceBusMessage("Hello world!");

// send the message
await sender.SendMessageAsync(message);

// create a receiver that we can use to receive the message
ServiceBusReceiver receiver = client.CreateReceiver(queueName);

// the received message is a different type as it contains some service set properties
ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();

// get the message body as a string
string body = receivedMessage.Body.ToString();
Console.WriteLine(body);

메시지 일괄 처리 보내기

한 번에 여러 메시지를 보내는 방법에는 두 가지가 있습니다. 이 작업을 수행하는 첫 번째 방법은 안전한 일괄 처리를 사용합니다. 안전 일괄 처리를 사용하면 개체를 ServiceBusMessageBatch 만들 수 있습니다. 그러면 메서드를 사용하여 TryAdd 일괄 처리에 메시지를 한 번에 하나씩 추가할 수 있습니다. 메시지가 일괄 처리에 맞지 않으면 는 TryAdd false를 반환합니다.

// add the messages that we plan to send to a local queue
Queue<ServiceBusMessage> messages = new Queue<ServiceBusMessage>();
messages.Enqueue(new ServiceBusMessage("First message"));
messages.Enqueue(new ServiceBusMessage("Second message"));
messages.Enqueue(new ServiceBusMessage("Third message"));

// create a message batch that we can send
// total number of messages to be sent to the Service Bus queue
int messageCount = messages.Count;

// while all messages are not sent to the Service Bus queue
while (messages.Count > 0)
{
    // start a new batch
    using ServiceBusMessageBatch messageBatch = await sender.CreateMessageBatchAsync();

    // add the first message to the batch
    if (messageBatch.TryAddMessage(messages.Peek()))
    {
        // dequeue the message from the .NET queue once the message is added to the batch
        messages.Dequeue();
    }
    else
    {
        // if the first message can't fit, then it is too large for the batch
        throw new Exception($"Message {messageCount - messages.Count} is too large and cannot be sent.");
    }

    // add as many messages as possible to the current batch
    while (messages.Count > 0 && messageBatch.TryAddMessage(messages.Peek()))
    {
        // dequeue the message from the .NET queue as it has been added to the batch
        messages.Dequeue();
    }

    // now, send the batch
    await sender.SendMessagesAsync(messageBatch);

    // if there are any remaining messages in the .NET queue, the while loop repeats
}

두 번째 방법은 의 SendMessagesAsync IEnumerable을 허용하는 오버로드를 ServiceBusMessage사용합니다. 이 메서드를 사용하면 제공된 모든 메시지를 서비스에 보낼 단일 메시지 일괄 처리에 맞추려고 시도합니다. 메시지가 너무 커서 단일 일괄 처리에 맞지 않으면 작업이 예외를 throw합니다.

IList<ServiceBusMessage> messages = new List<ServiceBusMessage>();
messages.Add(new ServiceBusMessage("First"));
messages.Add(new ServiceBusMessage("Second"));
// send the messages
await sender.SendMessagesAsync(messages);

메시지 일괄 처리 받기

// create a receiver that we can use to receive the messages
ServiceBusReceiver receiver = client.CreateReceiver(queueName);

// the received message is a different type as it contains some service set properties
// a batch of messages (maximum of 2 in this case) are received
IReadOnlyList<ServiceBusReceivedMessage> receivedMessages = await receiver.ReceiveMessagesAsync(maxMessages: 2);

// go through each of the messages received
foreach (ServiceBusReceivedMessage receivedMessage in receivedMessages)
{
    // get the message body as a string
    string body = receivedMessage.Body.ToString();
}

메시지 완료

큐 또는 구독에서 메시지를 제거하기 위해 메서드를 호출할 CompleteAsync 수 있습니다.

string connectionString = "<connection_string>";
string queueName = "<queue_name>";
// since ServiceBusClient implements IAsyncDisposable we create it with "await using"
await using var client = new ServiceBusClient(connectionString);

// create the sender
ServiceBusSender sender = client.CreateSender(queueName);

// create a message that we can send
ServiceBusMessage message = new ServiceBusMessage("Hello world!");

// send the message
await sender.SendMessageAsync(message);

// create a receiver that we can use to receive and settle the message
ServiceBusReceiver receiver = client.CreateReceiver(queueName);

// the received message is a different type as it contains some service set properties
ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();

// complete the message, thereby deleting it from the service
await receiver.CompleteMessageAsync(receivedMessage);

메시지 중단

메시지를 중단하면 수신자의 잠금이 해제되므로 이 또는 다른 수신자가 메시지를 받을 수 있습니다.

ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();

// abandon the message, thereby releasing the lock and allowing it to be received again by this or other receivers
await receiver.AbandonMessageAsync(receivedMessage);

메시지 연기

메시지를 연기하면 또는 ReceiveMessagesAsync 메서드를 사용하여 ReceiveMessageAsync 메시지를 다시 받지 못하게 됩니다. 대신 지연된 메시지를 수신하기 위한 별도의 메서드 ReceiveDeferredMessageAsyncReceiveDeferredMessagesAsync 이 있습니다.

ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();

// defer the message, thereby preventing the message from being received again without using
// the received deferred message API.
await receiver.DeferMessageAsync(receivedMessage);

// receive the deferred message by specifying the service set sequence number of the original
// received message
ServiceBusReceivedMessage deferredMessage = await receiver.ReceiveDeferredMessageAsync(receivedMessage.SequenceNumber);

배달 못한 편지 메시지

메시지를 배달 못한 편지로 보내는 것은 메시지가 특정 횟수만큼 수신된 후 서비스에서 자동으로 배달 못 한 편지가 된다는 기본 차이로 지연하는 것과 유사합니다. 애플리케이션은 요구 사항에 따라 수동으로 배달 못한 편지 메시지를 선택할 수 있습니다. 메시지가 배달 못한 편지로 전송되면 실제로 원래 큐의 하위 큐로 이동됩니다. 는 ServiceBusReceiver 기본 큐가 세션 사용 여부에 관계없이 배달 못한 편지 하위 큐에서 메시지를 받는 데 사용됩니다.

ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();

// Dead-letter the message, thereby preventing the message from being received again without receiving from the dead letter queue.
// We can optionally pass a dead letter reason and dead letter description to further describe the reason for dead-lettering the message.
await receiver.DeadLetterMessageAsync(receivedMessage, "sample reason", "sample description");

// receive the dead lettered message with receiver scoped to the dead letter queue.
ServiceBusReceiver dlqReceiver = client.CreateReceiver(queueName, new ServiceBusReceiverOptions
{
    SubQueue = SubQueue.DeadLetter
});
ServiceBusReceivedMessage dlqMessage = await dlqReceiver.ReceiveMessageAsync();

// The reason and the description that we specified when dead-lettering the message will be available in the received dead letter message.
string reason = dlqMessage.DeadLetterReason;
string description = dlqMessage.DeadLetterErrorDescription;

자세한 내용은 ServiceBus 배달 못한 편지 큐 개요를 참조하세요.

프로세서 사용

ServiceBusProcessor 수신기 집합을 추상화로 간주할 수 있습니다. 콜백 모델을 사용하여 메시지를 받을 때와 예외가 발생할 때 코드를 지정할 수 있도록 합니다. 처리된 메시지의 자동 완성, 자동 메시지 잠금 갱신 및 사용자 지정 이벤트 처리기의 동시 실행을 제공합니다. 기능 집합으로 인해 Service Bus 엔터티에서 수신하는 애플리케이션을 작성하기 위한 이동 도구여야 합니다. ServiceBusReceiver는 프로세서가 ServiceBusReceiver를 직접 사용할 때 기대할 수 있는 세분화된 컨트롤을 제공할 수 없는 보다 복잡한 시나리오에 권장됩니다.

string connectionString = "<connection_string>";
string queueName = "<queue_name>";
// since ServiceBusClient implements IAsyncDisposable we create it with "await using"
await using var client = new ServiceBusClient(connectionString);

// create the sender
ServiceBusSender sender = client.CreateSender(queueName);

// create a set of messages that we can send
ServiceBusMessage[] messages = new ServiceBusMessage[]
{
    new ServiceBusMessage("First"),
    new ServiceBusMessage("Second")
};

// send the message batch
await sender.SendMessagesAsync(messages);

// create the options to use for configuring the processor
var options = new ServiceBusProcessorOptions
{
    // By default or when AutoCompleteMessages is set to true, the processor will complete the message after executing the message handler
    // Set AutoCompleteMessages to false to [settle messages](/azure/service-bus-messaging/message-transfers-locks-settlement#peeklock) on your own.
    // In both cases, if the message handler throws an exception without settling the message, the processor will abandon the message.
    AutoCompleteMessages = false,

    // I can also allow for multi-threading
    MaxConcurrentCalls = 2
};

// create a processor that we can use to process the messages
await using ServiceBusProcessor processor = client.CreateProcessor(queueName, options);

// configure the message and error handler to use
processor.ProcessMessageAsync += MessageHandler;
processor.ProcessErrorAsync += ErrorHandler;

async Task MessageHandler(ProcessMessageEventArgs args)
{
    string body = args.Message.Body.ToString();
    Console.WriteLine(body);

    // we can evaluate application logic and use that to determine how to settle the message.
    await args.CompleteMessageAsync(args.Message);
}

Task ErrorHandler(ProcessErrorEventArgs args)
{
    // the error source tells me at what point in the processing an error occurred
    Console.WriteLine(args.ErrorSource);
    // the fully qualified namespace is available
    Console.WriteLine(args.FullyQualifiedNamespace);
    // as well as the entity path
    Console.WriteLine(args.EntityPath);
    Console.WriteLine(args.Exception.ToString());
    return Task.CompletedTask;
}

// start processing
await processor.StartProcessingAsync();

// since the processing happens in the background, we add a Console.ReadKey to allow the processing to continue until a key is pressed.
Console.ReadKey();

Azure.Identity를 사용하여 인증

Azure ID 라이브러리는 인증을 위한 간편한 Azure Active Directory 지원을 제공합니다.

// Create a ServiceBusClient that will authenticate through Active Directory
string fullyQualifiedNamespace = "yournamespace.servicebus.windows.net";
await using var client = new ServiceBusClient(fullyQualifiedNamespace, new DefaultAzureCredential());

세션 작업

세션은 관련 메시지를 그룹화하기 위한 메커니즘을 제공합니다. 세션을 사용하려면 세션 사용 엔터티로 작업해야 합니다.

문제 해결

Service Bus 문제 해결 가이드를 참조하세요.

다음 단계

설명된 소개 시나리오 외에도 Azure Service Bus 클라이언트 라이브러리는 Azure Service Bus 서비스의 전체 기능 집합을 활용하는 데 도움이 되는 추가 시나리오를 지원합니다. 이러한 시나리오 중 일부를 탐색하는 데 도움이 되도록 Service Bus 클라이언트 라이브러리는 일반적인 시나리오에 대한 그림으로 사용할 샘플 프로젝트를 제공합니다. 자세한 내용은 샘플 추가 정보를 참조하세요.

참여

이 프로젝트에 대한 기여와 제안을 환영합니다. 대부분의 경우 기여하려면 권한을 부여하며 실제로 기여를 사용할 권한을 당사에 부여한다고 선언하는 CLA(기여자 라이선스 계약)에 동의해야 합니다. 자세한 내용은 https://cla.microsoft.com 을 참조하세요.

끌어오기 요청을 제출하면 CLA-bot은 CLA를 제공하고 PR을 적절하게 데코레이팅해야 하는지 여부를 자동으로 결정합니다(예: 레이블, 설명). 봇에서 제공하는 지침을 따르기만 하면 됩니다. 이 작업은 CLA를 사용하여 모든 리포지토리에서 한 번만 수행하면 됩니다.

이 프로젝트에는 Microsoft Open Source Code of Conduct(Microsoft 오픈 소스 준수 사항)가 적용됩니다. 자세한 내용은 Code of Conduct FAQ(규정 FAQ)를 참조하세요. 또는 추가 질문이나 의견은 opencode@microsoft.com으로 문의하세요.

자세한 내용은 기여 가이드를 참조하세요.

Impressions