영어로 읽기

다음을 통해 공유


Orleans3.x에서 7.0으로 마이그레이션

Orleans 7.0에는 호스팅 개선, 사용자 지정 직렬화, 불변성, 조직 추상화를 비롯한 몇 가지 유용한 변경이 도입되었습니다.

마이그레이션

미리 알림, 스트림, 조직 지속성을 사용하는 기존 애플리케이션은 Orleans가 조직 및 스트림을 식별하는 방식이 달라졌기 때문에 Orleans 7.0으로 쉽게 마이그레이션할 수 없습니다. 이러한 애플리케이션에 대한 마이그레이션 경로를 점진적으로 제공할 계획입니다.

이전 버전의 Orleans를 실행하는 애플리케이션은 Orleans 7.0으로의 롤링 업그레이드를 통해 원활하게 업그레이드할 수 없습니다. 따라서 새 클러스터 배포 및 이전 클러스터 서비스 해제 등의 다른 업그레이드 전략을 사용해야 합니다. Orleans7.0은 호환되지 않는 방식으로 통신 프로토콜을 변경합니다. 즉, 클러스터에 Orleans 7.0 호스트와 이전 버전의 Orleans를 실행하는 호스트가 혼합해서 존재할 수 없습니다.

Microsoft는 몇 년 동안 이러한 호환성이 손상되는 변경을 피해왔습니다. 심지어 주요 릴리스가 달라져도 마찬가지였습니다. 그런데 하필 지금 변경하는 이유는 무엇일까요? ID와 serialization이라는 두 가지 주요 이유가 있습니다. ID와 관련하여, 조직 및 스트림 ID는 이제 문자열로 구성되므로 조직이 제네릭 형식 정보를 적절히 인코딩할 수 있고 스트림이 애플리케이션 도메인에 좀 더 쉽게 매핑될 수 있습니다. 조직 형식이 이전에는 제네릭 조직을 나타낼 수 없었던 복잡한 데이터 구조를 사용하여 식별되었으므로 코너 케이스를 초래했습니다. 스트림은 string 네임스페이스와 Guid 키로 식별되었으며, 이로 인해 개발자가 애플리케이션 도메인에 매핑하기가 어려웠지만 효율적이었습니다. 이제 Serialization은 버전 독립적입니다. 즉, 호환되는 특정 방식으로 형식을 수정할 수 있고 규칙 집합을 따르며 Serialization 오류 없이 안심하고 애플리케이션을 업그레이드할 수 있습니다. 특히 애플리케이션 유형이 스트림 또는 조직 스토리지에 유지되는 경우 문제가 되었습니다. 다음 섹션에서는 주요 변경 내용을 자세히 다룹니다.

변경 내용 패키징

프로젝트를 Orleans 7.0으로 업그레이드하는 경우 다음 작업을 수행해야 합니다.

  • 모든 클라이언트는 Microsoft.Orleans.Client를 참조해야 합니다.
  • 모든 사일로(서버)는 Microsoft.Orleans.Server를 참조해야 합니다.
  • 다른 모든 패키지는 Microsoft.Orleans.Sdk를 참조해야 합니다.
    • 클라이언트서버 패키지에는 모두 Microsoft.Orleans.Sdk에 대한 참조가 포함되어 있습니다.
  • Microsoft.Orleans.CodeGenerator.MSBuildMicrosoft.Orleans.OrleansCodeGenerator.Build에 대한 모든 참조를 제거합니다.
    • KnownAssembly의 사용을 GenerateCodeForDeclaringAssemblyAttribute로 바꿉니다.
    • Microsoft.Orleans.Sdk 패키지는 C# 원본 생성기 패키지(Microsoft.Orleans.CodeGenerator)를 참조합니다.
  • Microsoft.Orleans.OrleansRuntime에 대한 모든 참조를 제거합니다.
  • ConfigureApplicationParts 호출을 제거합니다. 애플리케이션 파트가 제거되었습니다. Orleans용 C# 원본 생성기는 모든 패키지(클라이언트 및 서버 포함)에 추가되며 해당 애플리케이션 파트를 자동으로 생성합니다.
  • Microsoft.Orleans.OrleansServiceBus에 대한 참조를 Microsoft.Orleans.Streaming.EventHubs로 바꿉니다.
  • 미리 알림을 사용하는 경우 Microsoft.Orleans.Reminders에 대한 참조를 추가합니다.
  • 스트림을 사용하는 경우 Microsoft.Orleans.Streaming에 대한 참조를 추가합니다.

모든 Orleans 샘플은 Orleans 7.0으로 업그레이드되었으며 변경 내용에 대한 참조로 사용할 수 있습니다. 자세한 내용은 각 샘플에 대한 변경 내용을 항목화하는 Orleans 문제 #8035를 참조하세요.

Orleansglobal using 지시문

모든 Orleans 프로젝트는 Microsoft.Orleans.Sdk NuGet 패키지를 직접 또는 간접적으로 참조합니다. Orleans 프로젝트가 암시적 사용(예: <ImplicitUsings>enable</ImplicitUsings>)을 사용하도록 구성되면 OrleansOrleans.Hosting 네임스페이스가 모두 암시적으로 사용됩니다. 즉, 앱 코드에 이러한 지시문이 필요하지 않습니다.

자세한 내용은 ImplicitUsingsdotnet/orleans/src/Orleans.Sdk/build/Microsoft.Orleans.Sdk.targets를 참조하세요.

Hosting

ClientBuilder 형식이 IHostBuilder에서 UseOrleansClient 확장 메서드로 바뀌었습니다. IHostBuilder 형식은 Microsoft.Extensions.Hosting NuGet 패키지에서 가져옵니다. 즉, 별도의 종속성 주입 컨테이너를 만들지 않고도 Orleans 클라이언트를 기존 호스트에 추가할 수 있습니다. 클라이언트는 시작하는 동안 클러스터에 연결합니다. IHost.StartAsync가 완료되면 클라이언트가 자동으로 연결됩니다. IHostBuilder에 추가된 서비스는 등록 순서대로 시작됩니다. 따라서 ConfigureWebHostDefaults를 호출하기 전에 UseOrleansClient를 호출하면 ASP.NET Core가 시작되기 전에 Orleans가 시작되므로 ASP.NET Core 애플리케이션에서 클라이언트에 즉시 액세스할 수 있습니다.

이전 ClientBuilder 동작을 에뮬레이트하려는 경우 별도의 HostBuilder를 만들고 Orleans 클라이언트를 사용하여 구성할 수 있습니다. IHostBuilder에는 Orleans 클라이언트 또는 Orleans 사일로를 구성할 수 있습니다. 모든 사일로는 애플리케이션에서 사용할 수 있는 IGrainFactoryIClusterClient 인스턴스를 등록하므로 클라이언트를 별도로 구성하는 것은 불필요하며 지원되지 않습니다.

OnActivateAsyncOnDeactivateAsync 서명 변경

Orleans는 활성화 및 비활성화 중에 조직이 코드를 실행할 수 있도록 허용합니다. 스토리지 또는 로그 수명 주기 메시지의 상태 읽기와 같은 작업을 수행하는 데 사용할 수 있습니다. Orleans 7.0에서는 이러한 수명 주기 메서드의 서명이 변경되었습니다.

  • OnActivateAsync()는 이제 CancellationToken 매개 변수를 허용합니다. CancellationToken이 취소되면 활성화 프로세스를 중단해야 합니다.
  • OnDeactivateAsync()는 이제 DeactivationReason 매개 변수 및 CancellationToken 매개 변수를 허용합니다. DeactivationReason은 활성화가 비활성화되는 이유를 나타냅니다. 개발자는 로깅 및 진단 목적으로 이 정보를 사용해야 합니다. CancellationToken이 취소되면 비활성화 프로세스를 즉시 완료해야 합니다. 언제든지 모든 호스트가 실패할 수 있으므로 OnDeactivateAsync를 사용하여 위험 상태 유지와 같은 중요한 작업을 수행하는 것은 권장되지 않습니다.

이러한 새 메서드를 재정의하는 조직의 다음 예제를 살펴보겠습니다.

public sealed class PingGrain : Grain, IPingGrain
{
    private readonly ILogger<PingGrain> _logger;

    public PingGrain(ILogger<PingGrain> logger) =>
        _logger = logger;

    public override Task OnActivateAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("OnActivateAsync()");
        return Task.CompletedTask;
    }

    public override Task OnDeactivateAsync(DeactivationReason reason, CancellationToken token)
    {
        _logger.LogInformation("OnDeactivateAsync({Reason})", reason);
        return Task.CompletedTask;
    }

    public ValueTask Ping() => ValueTask.CompletedTask;
}

POCO 조직 및 IGrainBase

Orleans의 조직은 더 이상 Grain 기본 클래스 또는 다른 클래스에서 상속할 필요가 없습니다. 이 기능을 POCO 조직이라고 합니다. 다음과 같은 확장 메서드에 액세스하려면 다음을 수행합니다.

조직은 IGrainBase를 구현하거나 Grain에서 상속해야 합니다. 다음은 조직 클래스에서 IGrainBase를 구현하는 예제입니다.

public sealed class PingGrain : IGrainBase, IPingGrain
{
    public PingGrain(IGrainContext context) => GrainContext = context;

    public IGrainContext GrainContext { get; }

    public ValueTask Ping() => ValueTask.CompletedTask;
}

IGrainBase는 또한 OnActivateAsyncOnDeactivateAsync를 기본 구현으로 정의하여 원할 경우 조직이 수명 주기에 참여할 수 있도록 합니다.

public sealed class PingGrain : IGrainBase, IPingGrain
{
    private readonly ILogger<PingGrain> _logger;

    public PingGrain(IGrainContext context, ILogger<PingGrain> logger)
    {
        _logger = logger;
        GrainContext = context;
    }

    public IGrainContext GrainContext { get; }

    public Task OnActivateAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("OnActivateAsync()");
        return Task.CompletedTask;
    }

    public Task OnDeactivateAsync(DeactivationReason reason, CancellationToken token)
    {
        _logger.LogInformation("OnDeactivateAsync({Reason})", reason);
        return Task.CompletedTask;
    }

    public ValueTask Ping() => ValueTask.CompletedTask;
}

Serialization

Orleans 7.0에서 가장 부담스러운 변화는 버전 독립적인 직렬 변환기의 도입입니다. 이전 직렬 변환기는 기존 형식에 속성을 추가하는 것을 허용할 수 없었으며 애플리케이션이 진화하면서 개발자에게 상당한 문제를 야기했으므로 이러한 변경이 진행되었습니다. 반면에 직렬 변환기는 유연하여 개발자는 제네릭, 다형성 및 참조 추적과 같은 기능을 비롯한 대부분의 .NET 형식을 수정 없이 나타낼 수 있었습니다. 대체 형식은 이미 오래 전부터 필요했지만 사용자는 여전히 높은 충실도로 해당 형식을 나타내야 합니다. 따라서 .NET 형식이 진화하도록 허용하면서 높은 충실도로 형식을 나타내도록 지원하는 대체 직렬 변환기가 Orleans 7.0에 도입되었습니다. 새 직렬 변환기는 이전 직렬 변환기보다 훨씬 효율적이므로 엔드투엔드 처리량이 최대 170% 더 높습니다.

자세한 내용은 Orleans 7.0과 관련된 다음 문서를 참조하세요.

조직 ID

조직은 각각 조직의 유형과 해당 키로 구성된 고유한 ID를 가집니다. 이전 버전의 Orleans는 GrainId의 복합 형식을 사용하여 다음 중 하나의 조직 키를 지원했습니다.

여기서는 조직 키 처리와 관련하여 몇 가지 복잡성이 수반됩니다. 조직 ID는 형식과 키의 두 가지 구성 요소로 구성됩니다. 형식 구성 요소는 이전에 숫자 형식 코드, 범주 및 3바이트의 제네릭 형식 정보로 구성되었습니다.

이제 조직 ID는 type/key 형식을 사용합니다. 여기서 typekey 모두 문자열입니다. 가장 일반적으로 사용되는 조직 키 인터페이스는 IGrainWithStringKey입니다. 이렇게 하면 조직 ID의 작동 방식이 크게 간소화되고 제네릭 조직 형식에 대한 지원이 향상됩니다.

이제 조직 인터페이스는 해시 코드와 제네릭 형식 매개 변수의 문자열 표현 조합이 아닌 사람이 읽을 수 있는 이름을 사용하여 표시됩니다.

새 시스템은 보다 다양하게 사용자 지정할 수 있으며 이러한 사용자 지정은 특성에 의해 구동될 수 있습니다.

  • 조직 classGrainTypeAttribute(String)는 조직 ID의 Type 부분을 지정합니다.
  • 조직 interfaceDefaultGrainTypeAttribute(String)는 조직 참조를 가져올 때 기본적으로 IGrainFactory에서 확인해야 하는 조직의 Type을 지정합니다. 예를 들어 IGrainFactory.GetGrain<IMyGrain>("my-key")를 호출할 때 조직 팩터리는 IMyGrain에 앞서 언급한 특성이 지정된 경우 조직 "my-type/my-key"에 대한 참조를 반환합니다.
  • GrainInterfaceTypeAttribute(String)는 인터페이스 이름을 재정의할 수 있도록 허용합니다. 이 메커니즘을 사용하여 명시적으로 이름을 지정하면 기존 조직 참조와의 호환성을 손상하지 않고 인터페이스 형식의 이름을 바꿀 수 있습니다. 또한 이 경우 ID가 직렬화될 수 있으므로 인터페이스에는 AliasAttribute가 있어야 합니다. 형식 별칭을 지정하는 방법에 대한 자세한 내용은 serialization 관련 섹션을 참조하세요.

위에서 설명한 대로 형식에 대한 기본 조직 클래스 및 인터페이스 이름을 재정의하면 기존 배포와의 호환성을 손상하지 않고 기본 형식의 이름을 바꿀 수 있습니다.

스트림 ID

Orleans 스트림이 처음 릴리스되었을 때 스트림은 Guid를 사용해야만 식별할 수 있었습니다. 이러한 기능은 메모리 할당 측면에서는 효율적이었지만 사용자가 의미 있는 스트림 ID를 만들기가 어려웠으며, 특정 용도에 적절한 스트림 ID를 결정하기 위해 일부 인코딩 또는 간접 참조가 필요한 경우가 많았습니다.

Orleans 7.0에서는 이제 문자열을 사용하여 스트림을 식별합니다. Orleans.Runtime.StreamIdstruct에는 StreamId.Namespace, StreamId.KeyStreamId.FullKey의 세 가지 속성이 포함되어 있습니다. 이러한 속성 값은 인코딩된 UTF-8 문자열입니다. 예: StreamId.Create(String, String).

SimpleMessageStreams를 BroadcastChannel로 대체

SimpleMessageStreams(SMS라고도 함)가 7.0에서는 제거되었습니다. SMS에는 Orleans.Providers.Streams.PersistentStreams와 동일한 인터페이스가 있지만 직접 조건 간 호출에 의존했으므로 동작은 매우 달랐습니다. 혼동을 방지하기 위해 SMS가 제거되었고 Orleans.BroadcastChannel라는 새 대체 항목이 도입되었습니다.

BroadcastChannel은 암시적 구독만 지원하며 이 경우 직접 대체될 수 있습니다. 명시적 구독이 필요하거나 PersistentStream 인터페이스를 사용해야 하는 경우(예: 프로덕션에서 EventHub를 사용하면서 테스트에서 SMS 사용) MemoryStream이 가장 적합한 후보입니다.

BroadcastChannel은 SMS와 동일한 동작을 나타내지만 MemoryStream은 다른 스트림 공급자처럼 동작합니다. 다음 브로드캐스트 채널 사용 예제를 고려해 보세요.

// Configuration
builder.AddBroadcastChannel(
    "my-provider",
    options => options.FireAndForgetDelivery = false);

// Publishing
var grainKey = Guid.NewGuid().ToString("N");
var channelId = ChannelId.Create("some-namespace", grainKey);
var stream = provider.GetChannelWriter<int>(channelId);

await stream.Publish(1);
await stream.Publish(2);
await stream.Publish(3);

// Simple implicit subscriber example
[ImplicitChannelSubscription]
public sealed class SimpleSubscriberGrain : Grain, ISubscriberGrain, IOnBroadcastChannelSubscribed
{
    // Called when a subscription is added to the grain
    public Task OnSubscribed(IBroadcastChannelSubscription streamSubscription)
    {
        streamSubscription.Attach<int>(
          item => OnPublished(streamSubscription.ChannelId, item),
          ex => OnError(streamSubscription.ChannelId, ex));

        return Task.CompletedTask;

        // Called when an item is published to the channel
        static Task OnPublished(ChannelId id, int item)
        {
            // Do something
            return Task.CompletedTask;
        }

        // Called when an error occurs
        static Task OnError(ChannelId id, Exception ex)
        {
            // Do something
            return Task.CompletedTask;
        }
    }
}

구성만 변경해야 하므로 MemoryStream로 마이그레이션하는 것이 더 쉬워집니다. 다음 MemoryStream 구성을 고려해 보세요.

builder.AddMemoryStreams<DefaultMemoryMessageBodySerializer>(
    "in-mem-provider",
    _ =>
    {
        // Number of pulling agent to start.
        // DO NOT CHANGE this value once deployed, if you do rolling deployment
        _.ConfigurePartitioning(partitionCount: 8);
    });

OpenTelemetry

원격 분석 시스템은 Orleans 7.0에서 업데이트되었으며 이전 시스템은 메트릭을 위한 .NET 메트릭 및 추적을 위한 ActivitySource 같은 표준화된 .NET API를 위해 제거되었습니다.

이 작업의 일부로 기존 Microsoft.Orleans.TelemetryConsumers.* 패키지가 제거되었습니다. Orleans에서 내보낸 메트릭을 선택한 모니터링 솔루션과 통합하는 프로세스를 간소화하기 위해 새로운 패키지 집합을 도입하는 방안을 고려하고 있습니다. 항상 그런 것처럼 피드백과 기여도 환영합니다.

dotnet-counters 도구는 임시 상태 모니터링 및 1단계 수준 성능 조사를 위한 성능 모니터링 기능을 제공합니다. Orleans 카운터의 경우 dotnet-counters 도구를 사용하여 다음을 모니터링할 수 있습니다.

dotnet counters monitor -n MyApp --counters Microsoft.Orleans

마찬가지로 OpenTelemetry 메트릭은 다음 코드와 같이 Microsoft.Orleans 미터를 추가할 수 있습니다.

builder.Services.AddOpenTelemetry()
    .WithMetrics(metrics => metrics
        .AddPrometheusExporter()
        .AddMeter("Microsoft.Orleans"));

분산 추적을 사용하도록 설정하려면 다음 코드와 같이 OpenTelemetry를 구성합니다.

builder.Services.AddOpenTelemetry()
    .WithTracing(tracing =>
    {
        tracing.SetResourceBuilder(ResourceBuilder.CreateDefault()
            .AddService(serviceName: "ExampleService", serviceVersion: "1.0"));

        tracing.AddAspNetCoreInstrumentation();
        tracing.AddSource("Microsoft.Orleans.Runtime");
        tracing.AddSource("Microsoft.Orleans.Application");

        tracing.AddZipkinExporter(options =>
        {
            options.Endpoint = new Uri("http://localhost:9411/api/v2/spans");
        });
    });

앞의 코드에서 OpenTelemetry는 다음을 모니터링하도록 구성됩니다.

  • Microsoft.Orleans.Runtime
  • Microsoft.Orleans.Application

활동을 전파하려면 AddActivityPropagation을 호출합니다.

builder.Host.UseOrleans((_, clientBuilder) =>
{
    clientBuilder.AddActivityPropagation();
});

핵심 패키지의 기능을 별도의 패키지로 리팩터링

Orleans 7.0에서는 Orleans.Core에 의존하지 않는 별도의 패키지로 확장을 리팩터링하려고 노력했습니다. 즉, Orleans.Streaming, Orleans.RemindersOrleans.Transactions는 코어에서 분리되었습니다. 즉, 이러한 패키지는 전적으로 사용한 양에 대해서만 비용을 결제하며 Orleans의 핵심에는 이러한 기능 전용 코드가 없습니다. 이렇게 하면 코어 API 화면과 어셈블리 크기가 축소되고, 코어가 간소화되고, 성능이 향상됩니다. 성능과 관련하여 이전에는 Orleans의 트랜잭션에 잠재적인 트랜잭션을 조정하기 위해 모든 메서드에 대해 실행되었던 일부 코드가 필요했습니다. 그 이후에는 메서드별로 이동되었습니다.

이것은 컴파일 호환성이 손상되는 변경입니다. 이전에는 Grain 기본 클래스에 정의되었지만 지금은 확장 메서드인 메서드로 호출하여 미리 알림 또는 스트림과 상호 작용하는 기존 코드가 있을 수 있습니다. this를 지정하지 않는 이러한 호출(예: GetReminders)은 확장 메서드를 정규화해야 하므로 this를 포함하도록 업데이트해야 합니다(예: this.GetReminders()). 이러한 호출을 업데이트하지 않으면 컴파일 오류가 발생하며 변경된 내용을 모르는 경우 필요한 코드 변경이 명확하지 않을 수 있습니다.

트랜잭션 클라이언트

Orleans 7.0에서는 트랜잭션 조정을 위한 새로운 추상화인 Orleans.ITransactionClient가 도입되었습니다. 이전에는 트랜잭션이 조직에 의해서만 조정될 수 있습니다. 종속성 주입을 통해 사용할 수 있는 ITransactionClient를 사용하면 클라이언트는 중간 조직 없이도 트랜잭션을 조정할 수 있습니다. 다음 예제에서는 한 계정에서 크레딧을 인출하고 단일 트랜잭션 내의 다른 계정에 입금합니다. 이 코드는 종속성 주입 컨테이너에서 ITransactionClient를 검색한 외부 클라이언트 내에서 호출할 수 있습니다.

await transactionClient.RunTransaction(
  TransactionOption.Create,
  () => Task.WhenAll(from.Withdraw(100), to.Deposit(100)));

클라이언트가 조정하는 트랜잭션의 경우 클라이언트는 구성 시간 동안 필요한 서비스를 추가해야 합니다.

clientBuilder.UseTransactions();

BankAccount 샘플은 ITransactionClient의 사용을 보여 줍니다. 자세한 내용은 Orleans 전환을 참조하세요.

호출 체인 재진입

조직은 단일 스레드이며 기본적으로 요청을 처음부터 완료까지 하나씩 처리합니다. 즉, 조직은 기본적으로 재진입되지 않습니다. ReentrantAttribute를 조직 클래스에 추가하면 단일 스레드이지만 인터리빙 방식으로 여러 요청을 동시에 처리할 수 있습니다. 내부 상태가 없거나 많은 비동기 작업(예: HTTP 호출 실행 또는 데이터베이스에 쓰기)을 수행하는 조직에 유용할 수 있습니다. 요청이 인터리브될 수 있는 경우 주의해야 합니다. 비동기 작업이 완료되고 메서드가 실행을 다시 시작할 때까지 await 문이 변경되기 전에 관찰된 조직의 상태가 변경될 수 있습니다.

예를 들어 다음 조직은 카운터를 나타냅니다. Reentrant로 표시되어 여러 호출이 인터리브되도록 했습니다. Increment() 메서드는 내부 카운터를 증가시키고 관찰된 값을 반환해야 합니다. 그러나 Increment() 메서드 본문은 await 시점 이전의 조직 상태를 관찰하고 나중에 업데이트하므로 Increment()의 여러 인터리빙 실행으로 인해 _value가 수신된 총 Increment() 호출 수보다 작아질 수 있습니다. 이것은 잘못된 재진입 사용으로 인해 발생하는 오류입니다.

ReentrantAttribute를 제거하면 문제를 해결할 수 있습니다.

[Reentrant]
public sealed class CounterGrain : Grain, ICounterGrain
{
    int _value;
    
    /// <summary>
    /// Increments the grain's value and returns the previous value.
    /// </summary>
    public Task<int> Increment()
    {
        // Do not copy this code, it contains an error.
        var currentVal = _value;
        await Task.Delay(TimeSpan.FromMilliseconds(1_000));
        _value = currentVal + 1;
        return currentValue;
    }
}

이러한 오류를 방지하기 위해 조직은 기본적으로 재진입되지 않습니다. 이에 대한 단점은 조직이 비동기 작업 완료를 기다리는 동안 다른 요청을 처리할 수 없으므로 구현에서 비동기 작업을 수행하는 조직의 처리량이 줄어든다는 것입니다. 이를 완화하기 위해 Orleans는 특정 경우에 재진입을 허용하는 몇 가지 옵션을 제공합니다.

  • 전체 클래스의 경우: ReentrantAttribute를 조직에 배치하면 조직에 대한 모든 요청이 다른 요청과 인터리브될 수 있습니다.
  • 메서드 하위 집합의 경우: AlwaysInterleaveAttribute를 조직 interface 메서드에 배치하면 해당 메서드에 대한 요청이 다른 요청과 인터리브되고 해당 메서드에 대한 요청이 다른 요청에 의해 인터리브될 수 있습니다.
  • 메서드 하위 집합의 경우: ReadOnlyAttribute를 조직 interface 메서드에 배치하면 해당 메서드에 대한 요청이 다른 ReadOnly 요청과 인터리브되고 해당 메서드에 대한 요청이 다른 ReadOnly 요청에 의해 인터리브될 수 있습니다 이러한 의미에서 AlwaysInterleave의 좀 더 제한된 형식이라고 할 수 있습니다.
  • 호출 체인 내의 모든 요청의 경우: RequestContext.AllowCallChainReentrancy() 및 <xref:Orleans.Runtime.RequestContext.SuppressCallChainReentrancy?displayProperty=nameWithType을 사용하면 다운스트림 요청이 다시 조직으로 다시 입력되도록 옵트인 및 옵트아웃할 수 있습니다. 두 호출 모두 요청을 종료하는 동안 must가 삭제해야 하는 값을 반환합니다. 따라서 적절한 사용법은 다음과 같습니다.
public Task<int> OuterCall(IMyGrain other)
{
    // Allow call-chain reentrancy for this grain, for the duration of the method.
    using var _ = RequestContext.AllowCallChainReentrancy();
    await other.CallMeBack(this.AsReference<IMyGrain>());
}

public Task CallMeBack(IMyGrain grain)
{
    // Because OuterCall allowed reentrancy back into that grain, this method 
    // will be able to call grain.InnerCall() without deadlocking.
    await grain.InnerCall();
}

public Task InnerCall() => Task.CompletedTask;

호출 체인 재진입은 조직별로, 호출 체인별로 옵트인(opt-in)되어야 합니다. 예를 들어 조직 A와 조직 B라는 두 가지 조직이 있고 조직 A가 조직 B를 호출하기 전에 호출 체인 재진입을 사용하도록 설정하면 조직 B는 해당 호출에서 조직 A로 콜백할 수 있습니다. 그러나 조직 B가 호출 체인 재진입 ‘또한’ 사용하도록 설정하지 않은 경우 조직 A는 조직 B로 콜백될 수 없습니다. 이 작업은 조직별, 호출 체인별로 진행됩니다.

또한 조직은 using var _ = RequestContext.SuppressCallChainReentrancy()를 사용하여 호출 체인 재진입 정보가 호출 체인 아래로 흐르지 않도록 합니다. 이를 통해 후속 호출이 재진입되지 않습니다.

ADO.NET 마이그레이션 스크립트

ADO.NET을 사용하는 Orleans 클러스터링, 지속성, 미리 알림과의 호환성을 보장하려면 적절한 SQL 마이그레이션 스크립트가 필요합니다.

사용된 데이터베이스의 파일을 선택하고 순서대로 적용합니다.