Orleans panduan migrasi

Artikel ini menyediakan panduan migrasi untuk memutakhirkan antar versi utama Orleans . Pilih versi target Anda menggunakan pemilih versi di atas.

Migrasi dari Orleans 7.0 ke 10.0

Orleans 10.0 memperkenalkan beberapa fitur baru termasuk Dasbor bawaan. Bagian ini mencakup perubahan yang diperlukan untuk bermigrasi dari Orleans 7.0 ke 10.0, termasuk langkah-langkah menengah melalui 8.0 dan 9.0.

Ringkasan perubahan signifikan

Perubahan yang memutus kompatibilitas Dampak Migrasi
AddGrainCallFilter dihapus Kesalahan kompilasi Gunakan AddIncomingGrainCallFilter
LeaseAquisitionPeriod typo diperbaiki Kesalahan kompilasi Gunakan LeaseAcquisitionPeriod
LoadSheddingLimit Diubah nama Kesalahan kompilasi Gunakan CpuThreshold
CancelRequestOnTimeout default diubah Perilaku Secara eksplisit diatur ke true jika diperlukan
Penyedia ADO.NET memerlukan Microsoft.Data.SqlClient Kesalahan Kompilasi/Waktu Eksekusi Ganti System.Data.SqlClient paket
[Unordered] atribut usang Peringatan Hapus atribut (tidak berpengaruh)
OrleansConstructorAttribute sudah tidak digunakan Peringatan Gunakan GeneratedActivatorConstructorAttribute atau ActivatorUtilitiesConstructorAttribute hanya untuk konstruktor yang memerlukan injeksi dependensi, bukan untuk properti data berseri
RegisterTimer sudah tidak digunakan Peringatan Gunakan RegisterGrainTimer

Pembaruan paket

Perbarui referensi paket NuGet Anda dari Orleans 7.x ke 10.0:

Orleans Paket 7.x Orleans Paket 10.0
Microsoft.Orleans.Server 7.x Microsoft.Orleans.Server 10.0.0
Microsoft.Orleans.Client 7.x Microsoft.Orleans.Client 10.0.0
Microsoft.Orleans.Sdk 7.x Microsoft.Orleans.Sdk 10.0.0
Microsoft.Orleans.Streaming.EventHubs 7.x Microsoft.Orleans.Streaming.EventHubs 10.0.0
Microsoft.Orleans.Streaming.AzureStorage 7.x Microsoft.Orleans.Streaming.AzureStorage 10.0.0
Microsoft.Orleans.Persistence.AzureStorage 7.x Microsoft.Orleans.Persistence.AzureStorage 10.0.0
Microsoft.Orleans.Clustering.AzureStorage 7.x Microsoft.Orleans.Clustering.AzureStorage 10.0.0

Perubahan menerobos: AddGrainCallFilter diganti dengan AddIncomingGrainCallFilter

Metode extension AddGrainCallFilter pada IServiceCollection telah dihapus. Ganti dengan AddIncomingGrainCallFilter pada ISiloBuilder atau IClientBuilder.

// Orleans 7.x (no longer works)
services.AddGrainCallFilter(new MyFilter());
services.AddGrainCallFilter<MyFilter>();

// Orleans 10.0
siloBuilder.AddIncomingGrainCallFilter(new MyFilter());
siloBuilder.AddIncomingGrainCallFilter<MyFilter>();

// Or using a delegate
siloBuilder.AddIncomingGrainCallFilter(async context =>
{
    // Before grain call
    await context.Invoke();
    // After grain call
});

Untuk panggilan biji-bijian keluar dari klien, gunakan AddOutgoingGrainCallFilter:

siloBuilder.AddOutgoingGrainCallFilter<MyOutgoingFilter>();
clientBuilder.AddOutgoingGrainCallFilter<MyOutgoingFilter>();

Perubahan signifikan: LeaseAquisitionPeriod kesalahan ketik diperbaiki

Properti LeaseAquisitionPeriod yang salah eja pada LeaseBasedQueueBalancerOptions telah diperbaiki menjadi LeaseAcquisitionPeriod.

// Orleans 7.x (typo)
options.LeaseAquisitionPeriod = TimeSpan.FromSeconds(30);

// Orleans 10.0 (corrected)
options.LeaseAcquisitionPeriod = TimeSpan.FromSeconds(30);

Perubahan menerobos: LoadSheddingLimit diganti namanya menjadi CpuThreshold

Properti LoadSheddingLimit di LoadSheddingOptions telah diganti namanya menjadi CpuThreshold untuk mencerminkan tujuannya dengan lebih baik.

// Orleans 7.x
siloBuilder.Configure<LoadSheddingOptions>(options =>
{
    options.LoadSheddingEnabled = true;
    options.LoadSheddingLimit = 95; // No longer works
});

// Orleans 10.0
siloBuilder.Configure<LoadSheddingOptions>(options =>
{
    options.LoadSheddingEnabled = true;
    options.CpuThreshold = 95; // Use this instead
});

Perubahan signifikan: CancelRequestOnTimeout default diubah

Nilai MessagingOptions.CancelRequestOnTimeout default telah berubah dari true menjadi false. Ini berarti bahwa secara default, Orleans tidak lagi mengirim pesan pembatalan saat waktu panggilan grain habis.

Jika aplikasi Anda bergantung pada perilaku sebelumnya, atur opsi ini secara eksplisit:

siloBuilder.Configure<SiloMessagingOptions>(options =>
{
    options.CancelRequestOnTimeout = true;
});

// For clients
clientBuilder.Configure<ClientMessagingOptions>(options =>
{
    options.CancelRequestOnTimeout = true;
});

Perubahan menerobos: Penyedia ADO.NET memerlukan Microsoft.Data.SqlClient

Penyedia ADO.NET (pengklusteran, persistensi, pengingat) sekarang memerlukan Microsoft.Data.SqlClient alih-alih System.Data.SqlClient. Perbarui referensi proyek Anda:

<!-- Remove -->
<PackageReference Include="System.Data.SqlClient" Version="..." />

<!-- Add -->
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.0" />

Nama invarian juga telah berubah:

// Orleans 7.x
options.Invariant = "System.Data.SqlClient";

// Orleans 10.0
options.Invariant = "Microsoft.Data.SqlClient";

Perubahan yang mengganggu: atribut [Unordered] sudah usang

Atribut [Unordered] pada antarmuka biji-bijian sekarang usang dan tidak berpengaruh. Urutan pesan tidak pernah dijamin terlepas dari atribut ini. Hapus atribut dari kode Anda:

// Orleans 7.x
[Unordered]
public interface IMyGrain : IGrainWithStringKey
{
    Task DoSomething();
}

// Orleans 10.0 - just remove the attribute
public interface IMyGrain : IGrainWithStringKey
{
    Task DoSomething();
}

Perubahan besar: OrleansConstructorAttribute telah dihentikan

OrleansConstructorAttribute telah menjadi usang. Gunakan GeneratedActivatorConstructorAttribute atau ActivatorUtilitiesConstructorAttribute sebagai gantinya. Hanya terapkan atribut ini ke konstruktor yang mengharuskan layanan disuntikkan melalui injeksi dependensi. Jangan gunakan mereka untuk menunjukkan bagaimana Orleans harus mengatur properti atau bidang data berseri.

public interface IMyDependency
{
}

// Orleans 7.x
[GenerateSerializer]
public class MyClass
{
    [Id(0)]
    public string Value { get; set; }

    [OrleansConstructor] // Obsolete and ignored
    public MyClass(IMyDependency dependency)
    {
        Dependency = dependency;
    }

    [field: NonSerialized]
    public IMyDependency Dependency { get; }
}

// Orleans 10.0
[GenerateSerializer]
public class MyClass
{
    [Id(0)]
    public string Value { get; set; }

    [GeneratedActivatorConstructor]
    public MyClass(IMyDependency dependency)
    {
        Dependency = dependency;
    }

    [field: NonSerialized]
    public IMyDependency Dependency { get; }
}

Perubahan besar: RegisterTimer telah dihentikan

Metode Grain.RegisterTimer ini usang. Gunakan metode ekstensi baru RegisterGrainTimer sebagai gantinya, yang memberikan kontrol yang lebih baik atas perilaku timer.

// Orleans 7.x
public override Task OnActivateAsync(CancellationToken cancellationToken)
{
    RegisterTimer(
        callback: DoWork,
        state: null,
        dueTime: TimeSpan.FromSeconds(1),
        period: TimeSpan.FromSeconds(10));
    return Task.CompletedTask;
}

// Orleans 10.0
public override Task OnActivateAsync(CancellationToken cancellationToken)
{
    this.RegisterGrainTimer(
        callback: DoWork,
        state: (object?)null,
        options: new GrainTimerCreationOptions
        {
            DueTime = TimeSpan.FromSeconds(1),
            Period = TimeSpan.FromSeconds(10),
            Interleave = true // Set to true for same behavior as old RegisterTimer
        });
    return Task.CompletedTask;
}

Penting

Secara bawaan, RegisterGrainTimer menggunakan Interleave = false, yang mencegah timer callbacks terjalin dengan panggilan grain lainnya. Jika Anda memerlukan perilaku lama di mana panggilan balik timer dapat bertumpang tindih, secara eksplisit mengatur nilai Interleave = true.

Fitur baru di Orleans 10.0

Setelah bermigrasi, Anda dapat memanfaatkan fitur baru ini:

Migrasi dari Orleans 8.0 ke 9.0

Jika Anda memutakhirkan dari Orleans 8.x, perhatikan perubahan tambahan ini yang diperkenalkan di Orleans 9.0:

  • Direktori grain dengan konsistensi kuat: Direktori grain default sekarang memberikan jaminan konsistensi yang lebih kuat
  • Dukungan CancellationToken Penuh: Metode Grain sekarang sepenuhnya mendukung parameter CancellationToken
  • Pengurangan aktivasi berbasis memori: Penonaktifan butiran otomatis di bawah tekanan memori
  • Protokol keanggotaan yang lebih cepat: Waktu deteksi kegagalan default berkurang dari 10 menit menjadi 90 detik
  • Penempatan default berubah menjadi ResourceOptimized (9.2+): Strategi penempatan grain default berubah dari RandomPlacement ke ResourceOptimizedPlacement

Jika aplikasi Anda bergantung pada penempatan acak, konfigurasikan secara eksplisit:

siloBuilder.Services.AddSingleton<PlacementStrategy, RandomPlacement>();

// Or on specific grains
[RandomPlacement]
public class MyGrain : Grain, IMyGrain { }

Migrasi dari Orleans 7.0 ke 8.0

Jika Anda memutakhirkan dari Orleans 7.x, perhatikan perubahan ini yang diperkenalkan di Orleans 8.0:

  • API Timer baru: RegisterGrainTimer diperkenalkan untuk menggantikan RegisterTimer
  • Aspire integrasi: Dukungan kelas satu untuk Aspire
  • Penempatan yang Dioptimalkan Sumber Daya: Strategi penempatan baru berdasarkan pemanfaatan CPU dan memori
  • Partisi Ulang Aktivasi (8.2+): Fitur eksperimental untuk penyeimbangan ulang butir otomatis

Peningkatan bergulir

Peningkatan bergulir dari Orleans 7.x ke 10.0 tidak disarankan karena protokol dan perubahan API yang signifikan. Sebaliknya:

  1. Menyebarkan kluster baru yang menjalankan Orleans 10.0
  2. Memigrasikan data status jika perlu
  3. Mengalihkan lalu lintas ke kluster baru
  4. Menonaktifkan kluster lama

Skrip migrasi ADO.NET

Jika Anda menggunakan ADO.NET untuk pengklusteran, persistensi, atau pengingat, terapkan skrip migrasi yang sesuai:

Migrasi dari Orleans 3.x ke 7.0

Orleans 7.0 memperkenalkan beberapa perubahan bermanfaat, termasuk peningkatan dalam penyediaan layanan, serialisasi kustom, immutabilitas, dan abstraksi grain.

Migrasi

Karena perubahan dalam cara Orleans mengidentifikasi grain dan aliran, saat ini memigrasikan aplikasi yang ada menggunakan pengingat, aliran, atau persistensi grain ke Orleans 7.0 tidak mudah.

Meningkatkan aplikasi yang menjalankan versi sebelumnya Orleans dengan lancar melalui peningkatan bergulir ke Orleans 7.0 tidak memungkinkan. Oleh karena itu, gunakan strategi peningkatan yang berbeda, seperti menyebarkan kluster baru dan menonaktifkan yang sebelumnya. Orleans 7.0 mengubah protokol wire secara tidak kompatibel, artinya kluster tidak dapat mengandung campuran host Orleans 7.0 dan host yang menjalankan versi Orleans sebelumnya.

Perubahan yang dapat mendatangkan gangguan tersebut telah dihindari selama bertahun-tahun, bahkan melewati beberapa rilis besar. Mengapa sekarang? Ada dua alasan utama: identitas dan serialisasi. Mengenai identitas, identitas butir dan aliran data sekarang terdiri dari string. Ini memungkinkan biji-bijian untuk mengodekan informasi jenis generik dengan benar dan membuat aliran pemetaan ke domain aplikasi lebih mudah. Sebelumnya, Orleans jenis biji-bijian yang diidentifikasi menggunakan struktur data kompleks yang tidak dapat mewakili butir generik, yang mengarah ke kasus sudut. Aliran diidentifikasi oleh string namespace dan Guid kunci, yang efisien tetapi sulit dipetakan ke domain aplikasi. Serialisasi sekarang mendukung berbagai versi. Ini berarti jenis dapat dimodifikasi dengan cara yang kompatibel tertentu, mengikuti serangkaian aturan, dengan keyakinan bahwa aplikasi dapat ditingkatkan tanpa kesalahan serialisasi. Kemampuan ini sangat membantu ketika jenis aplikasi bertahan di aliran atau penyimpanan biji-bijian. Bagian berikut merinci perubahan besar dan mendiskusikannya lebih lanjut.

Perubahan kemasan

Saat meningkatkan proyek ke Orleans 7.0, lakukan tindakan berikut:

  • Semua klien harus mereferensikan Microsoft.Client.
  • Semua silo (server) harus merujuk Microsoft.Orleans.Server.
  • Semua paket lain harus mereferensikan Microsoft.Orleans. Sdk.
  • Hapus semua referensi ke Microsoft.Orleans.CodeGenerator.MSBuild dan Microsoft.Orleans.OrleansCodeGenerator.Build.
  • Hapus semua referensi ke Microsoft.Orleans.OrleansRuntime.
    • Orleansserver Microsoft mengacu pada penggantinya, Microsoft.Orleans.Runtime.
  • Hapus panggilan ke ConfigureApplicationParts. Bagian Aplikasi telah dihapus. Generator Sumber C# untuk Orleans ditambahkan ke semua paket (termasuk klien dan server) dan secara otomatis menghasilkan Bagian Aplikasi yang setara.
  • Ganti referensi ke Microsoft.Orleans.OrleansServiceBus dengan Microsoft.Orleans. Streaming.EventHubs.
  • Jika menggunakan reminders, tambahkan referensi ke Microsoft.Orleans.Reminders.
  • Jika menggunakan stream, tambahkan referensi ke Microsoft.Orleans. Streaming.

Petunjuk / Saran

Orleans Semua sampel telah ditingkatkan ke Orleans 7.0 dan dapat digunakan sebagai referensi untuk perubahan apa yang dibuat. Untuk informasi selengkapnya, lihat Orleans isu #8035 yang merinci perubahan yang dilakukan pada masing-masing sampel.

Orleans global menggunakan direktif

Semua proyek Orleans baik secara langsung maupun tidak langsung mereferensikan paket NuGet Microsoft.Orleans.Sdk. Orleans Ketika proyek dikonfigurasi untuk mengaktifkan pemakaian implisit (misalnya, <ImplicitUsings>enable</ImplicitUsings>), proyek secara implisit menggunakan namespace Orleans dan Orleans.Hosting. Ini berarti kode aplikasi tidak memerlukan arahan ini using .

Untuk informasi selengkapnya, lihat ImplicitUsings dan dotnet/orleans/src/Orleans. Sdk/build/Microsoft.Orleans. Sdk.targets.

Hosting

Jenis ClientBuilder digantikan dengan metode ekstensi UseOrleansClient pada IHostBuilder. Jenis IHostBuilder berasal dari Microsoft. Extensions.Hosting paket NuGet. Ini berarti Orleans klien dapat ditambahkan ke host yang ada tanpa membuat kontainer injeksi dependensi terpisah. Klien terhubung ke kluster selama startup. Setelah IHost.StartAsync selesai, klien terhubung secara otomatis. Layanan ditambahkan ke IHostBuilder dalam urutan pendaftaran dimulai. Memanggil UseOrleansClient sebelum memanggil ConfigureWebHostDefaults, misalnya, memastikan Orleans dimulai sebelum ASP.NET Core dimulai, memungkinkan akses langsung ke klien dari aplikasi ASP.NET Core.

Untuk meniru perilaku sebelumnya ClientBuilder, buat HostBuilder secara terpisah dan konfigurasikan dengan klien Orleans. Sebuah IHostBuilder dapat dikonfigurasi dengan klien Orleans atau silo Orleans. Semua silo mendaftarkan instans IGrainFactory dan IClusterClient yang dapat digunakan aplikasi, sehingga mengonfigurasi klien secara terpisah tidak perlu dan tidak didukung.

OnActivateAsync dan OnDeactivateAsync perubahan tanda tangan

Orleans memungkinkan biji-bijian untuk menjalankan kode selama aktivasi dan pennonaktifkanan. Gunakan kemampuan ini untuk melakukan tugas seperti membaca status dari penyimpanan atau mencatat pesan siklus hidup. Dalam Orleans 7.0, tanda tangan metode siklus hidup ini berubah:

Pertimbangkan contoh berikut dari grain yang mengambil alih metode baru ini:

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;
}

Butir POCO dan IGrainBase

Biji-bijian di Orleans sekarang tidak perlu lagi mewarisi dari kelas dasar Grain atau kelas lainnya. Fungsionalitas ini disebut sebagai biji-bijian POCO . Untuk mengakses metode ekstensi seperti salah satu hal berikut:

Butir harus mengimplementasikan IGrainBase atau mewarisi dari Grain. Berikut adalah contoh penerapan IGrainBase pada kelas biji-bijian:

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

    public IGrainContext GrainContext { get; }

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

IGrainBase juga mendefinisikan OnActivateAsync dan OnDeactivateAsync dengan implementasi default, memungkinkan biji-bijian untuk berpartisipasi dalam siklus hidupnya jika diinginkan:

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;
}

Serialisasi

Perubahan paling memberatkan dalam Orleans 7.0 adalah pengenalan serializer yang toleran terhadap versi. Perubahan ini dilakukan karena aplikasi cenderung berkembang, yang menyebabkan perangkap yang signifikan bagi pengembang karena serializer sebelumnya tidak dapat mentolerir penambahan properti ke jenis yang ada. Di sisi lain, serializer sebelumnya fleksibel, memungkinkan representasi sebagian besar jenis .NET tanpa modifikasi, termasuk fitur seperti generik, polimorfisme, dan pelacakan referensi. Penggantian sudah lama terlambat, tetapi representasi jenis keakuratan tinggi masih diperlukan. Oleh karena itu, Orleans 7.0 memperkenalkan serializer pengganti yang mendukung representasi keakuratan tinggi dari jenis .NET sekaligus memungkinkan jenis berkembang. Serializer baru jauh lebih efisien daripada yang sebelumnya, menghasilkan hingga 170% throughput end-to-end yang lebih tinggi.

Untuk informasi selengkapnya, lihat artikel berikut ini terkait dengan Orleans 7.0:

Identitas butir

Biji-bijian masing-masing memiliki identitas unik yang terdiri dari jenis biji-bijian dan kuncinya. Versi Orleans sebelumnya menggunakan tipe gabungan untuk GrainIds guna mendukung kunci grain dari salah satu:

Pendekatan ini melibatkan beberapa kompleksitas ketika menangani kunci grain. Identitas butir terdiri dari dua komponen: Jenis dan Kunci. Komponen jenis sebelumnya terdiri dari kode jenis numerik, kategori, dan 3 byte informasi jenis generik.

Identitas butir sekarang mengambil formulir type/key, di mana keduanya type dan key merupakan string. Antarmuka kunci grain yang paling umum digunakan adalah IGrainWithStringKey. Ini sangat menyederhanakan cara kerja identitas biji-bijian dan meningkatkan dukungan untuk jenis biji-bijian generik.

Antarmuka biji-bijian sekarang juga diwakili menggunakan nama yang dapat dibaca manusia, bukan kombinasi kode hash dan representasi string dari parameter jenis generik apa pun.

Sistem baru lebih dapat disesuaikan, dan penyesuaian ini dapat didorong dengan atribut.

  • GrainTypeAttribute(String) pada butir class menentukan bagian Jenis dari ID biji-bijiannya.
  • DefaultGrainTypeAttribute(String) pada butir interface menentukan Jenis biji-bijian yang IGrainFactory harus diselesaikan secara default saat mendapatkan referensi biji-bijian. Misalnya, saat memanggil IGrainFactory.GetGrain<IMyGrain>("my-key"), pabrik biji-bijian mengembalikan referensi ke biji-bijian "my-type/my-key" jika IMyGrain memiliki atribut yang disebutkan di atas yang ditentukan.
  • GrainInterfaceTypeAttribute(String) memungkinkan penggantian nama antarmuka. Menentukan nama secara eksplisit menggunakan mekanisme ini memungkinkan penggantian nama jenis antarmuka tanpa melanggar kompatibilitas dengan referensi butir yang ada. Perhatikan bahwa antarmuka juga harus memiliki AliasAttribute dalam hal ini, karena identitasnya mungkin diserialisasikan. Untuk informasi selengkapnya tentang menentukan alias jenis, lihat bagian tentang serialisasi.

Seperti disebutkan di atas, mengganti nama kelas default grain dan nama antarmuka untuk tipe memungkinkan penggantian nama tipe dasar tanpa merusak kompatibilitas dengan penerapan yang sudah ada.

Identitas aliran

Ketika stream Orleans pertama kali dirilis, stream hanya dapat diidentifikasi menggunakan Guid. Pendekatan ini efisien dalam hal alokasi memori tetapi membuat membuat identitas aliran yang bermakna sulit, sering membutuhkan beberapa pengodean atau tidak langsung untuk menentukan identitas aliran yang sesuai untuk tujuan tertentu.

Dalam Orleans 7.0, aliran diidentifikasi menggunakan string. Yang Orleans.Runtime.StreamIdstruct berisi tiga properti: StreamId.Namespace, StreamId.Key, dan StreamId.FullKey. Nilai properti ini adalah string UTF-8 yang dikodekan. Misalnya, lihat StreamId.Create(String, String).

Penggantian SimpleMessageStreams dengan BroadcastChannel

SimpleMessageStreams (juga disebut SMS) dihapus dalam 7.0. SMS memiliki antarmuka yang sama dengan Orleans.Providers.Streams.PersistentStreams, tetapi perilakunya sangat berbeda karena mengandalkan panggilan butir-ke-bijian langsung. Untuk menghindari kebingungan, SMS dihapus dan pengganti baru yang disebut Orleans.BroadcastChannel diperkenalkan.

BroadcastChannel hanya mendukung langganan implisit dan dapat menjadi pengganti langsung dalam kasus ini. Jika langganan eksplisit diperlukan atau PersistentStream antarmuka harus digunakan (misalnya, jika SMS digunakan dalam pengujian saat EventHub digunakan dalam produksi), maka MemoryStream adalah kandidat terbaik.

BroadcastChannel memiliki perilaku yang sama dengan SMS, sementara MemoryStream berulah seperti penyedia streaming lainnya. Pertimbangkan contoh penggunaan Saluran Siaran berikut:

// 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;
        }
    }
}

Migrasi menjadi MemoryStream lebih mudah karena hanya konfigurasi yang perlu diubah. Pertimbangkan konfigurasi berikut 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

Sistem telemetri diperbarui menjadi Orleans 7.0, dan sistem sebelumnya digantikan oleh API .NET standar seperti Metrik .NET untuk metrik dan ActivitySource untuk pelacakan.

Sebagai bagian dari ini, paket Microsoft.Orleans.TelemetryConsumers.* yang ada dihapus. Serangkaian paket baru sedang dipertimbangkan untuk menyederhanakan integrasi metrik yang dipancarkan oleh Orleans ke dalam solusi pemantauan pilihan. Seperti biasa, umpan balik dan kontribusi dipersilakan.

Alat ini dotnet-counters menyediakan pemantauan kinerja untuk pemantauan kesehatan ad-hoc dan investigasi kinerja tingkat awal. Untuk Orleans penghitung, gunakan alat dotnet-counters untuk memantaunya:

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

Demikian pula, tambahkan meter Microsoft.Orleans ke metrik OpenTelemetry, seperti yang ditunjukkan dalam kode berikut:

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

Untuk mengaktifkan pelacakan terdistribusi, konfigurasikan OpenTelemetry seperti yang ditunjukkan dalam kode berikut:

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

        tracing.AddAspNetCoreInstrumentation();

        // Good baseline for general Orleans observability
        tracing.AddSource(Orleans.Diagnostics.ActivitySources.ApplicationGrainActivitySourceName);
        tracing.AddSource(Orleans.Diagnostics.ActivitySources.LifecycleActivitySourceName);

        /*
        // Other source also available
        // Persistence spans
        tracing.AddSource(Orleans.Diagnostics.ActivitySources.StorageActivitySourceName);
        // Internal Runtime spans
        tracing.AddSource(Orleans.Diagnostics.ActivitySources.RuntimeActivitySourceName);
        */

        /*
        // Optionally add all Microsoft.Orleans.* Sources at once
        tracing.AddSource(Orleans.Diagnostics.ActivitySources.AllActivitySourceName);
        */

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

Dalam kode sebelumnya, OpenTelemetry dikonfigurasi untuk memantau:

  • Microsoft.Orleans.Application
  • Microsoft.Orleans.Lifecycle

Untuk menyebarluaskan aktivitas, panggil AddActivityPropagation:

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

Pisahkan fitur dari paket inti menjadi paket-paket terpisah

Dalam Orleans 7.0, ekstensi diperhitungkan ke dalam paket terpisah yang tidak mengandalkan Orleans.Core. Yaitu, Orleans.Streaming, Orleans.Reminders, dan Orleans.Transactions dipisahkan dari inti. Ini berarti paket ini sepenuhnya dibayar sesuai penggunaan, dan tidak ada kode dalam inti sistem yang dialokasikan khusus untuk fitur-fitur ini. Pendekatan ini menurunkan permukaan API inti dan ukuran perakitan, menyederhanakan inti, dan meningkatkan performa. Mengenai performa, transaksi di Orleans sebelumnya memerlukan beberapa kode yang dijalankan untuk setiap metode guna mengoordinasi potensi transaksi. Logika koordinasi itu sekarang dipindahkan ke basis per metode.

Ini adalah perubahan yang memecahkan kompilasi. Kode yang ada berinteraksi dengan pengingat atau aliran dengan memanggil metode yang sebelumnya ditentukan pada Grain kelas dasar mungkin rusak karena sekarang ini adalah metode ekstensi. Perbarui panggilan yang tidak menentukan this (misalnya, GetReminders) untuk menyertakan this (misalnya, this.GetReminders()) karena metode ekstensi harus dipenuhi syaratnya. Kesalahan kompilasi terjadi jika panggilan ini tidak diperbarui, dan perubahan kode yang diperlukan mungkin tidak jelas tanpa mengetahui apa yang berubah.

Klien transaksi

Orleans 7.0 memperkenalkan abstraksi baru untuk mengoordinasikan transaksi: Orleans.ITransactionClient. Sebelumnya, hanya biji-bijian yang dapat mengoordinasikan transaksi. Dengan ITransactionClient, yang tersedia melalui injeksi dependensi, klien juga dapat mengoordinasikan transaksi tanpa memerlukan grain perantara. Contoh berikut menarik kredit dari satu akun dan menyetorkannya ke akun lain dalam satu transaksi. Panggil kode ini dari dalam grain atau dari klien eksternal yang mengambil ITransactionClient dari kontainer injeksi dependensi.

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

Untuk transaksi yang dikoordinasikan oleh klien, klien harus menambahkan layanan yang diperlukan selama konfigurasi:

clientBuilder.UseTransactions();

Sampel BankAccount menunjukkan penggunaan ITransactionClient. Untuk informasi selengkapnya, lihat Orleans transaksi.

Reentransi rantai panggilan

Grain bersifat single-threaded dan memproses permintaan satu per satu dari awal hingga selesai secara bawaan. Dengan kata lain, biji-bijian tidak masuk kembali secara default. Menambahkan ReentrantAttribute ke kelas biji memungkinkan biji-bijian untuk memproses beberapa permintaan secara bersamaan dengan pola interleaving sambil tetap menjadi utas tunggal. Kemampuan ini dapat berguna untuk biji-bijian yang tidak memiliki status internal atau melakukan banyak operasi asinkron, seperti mengeluarkan panggilan HTTP atau menulis ke database. Kehati-hatian ekstra diperlukan ketika permintaan dapat saling menyisip: ada kemungkinan bahwa status biji-bijian yang diamati sebelum pernyataan await berubah pada saat operasi asinkron selesai dan metode kembali melanjutkan eksekusi.

Misalnya, biji-bijian berikut mewakili penghitung. Ini ditandai ReentrantAttribute, memungkinkan beberapa panggilan untuk saling berhubungan. Metode Increment() harus menaikkan penghitung internal dan mengembalikan nilai yang telah diamati. Namun, karena badan metode Increment() mengamati keadaan grain sebelum titik await dan memperbaruinya setelah itu, beberapa eksekusi Increment() yang saling bertumpuk dapat mengakibatkan _value lebih sedikit dari total jumlah Increment() panggilan yang diterima. Ini adalah kesalahan yang diperkenalkan oleh penggunaan reentrancy yang tidak tepat.

ReentrantAttribute Menghapus sudah cukup untuk memperbaiki masalah ini.

[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;
    }
}

Untuk mencegah kesalahan tersebut, biji-bijian tidak bersifat reentrant secara default. Kelemahannya adalah throughput yang berkurang untuk biji-bijian yang melakukan operasi asinkron dalam implementasinya, karena biji-bijian tidak dapat memproses permintaan lain sambil menunggu operasi asinkron selesai. Untuk meringankan ini, Orleans menawarkan beberapa opsi untuk memungkinkan masuknya kembali dalam kasus tertentu:

  • Untuk seluruh kelas: Menempatkan ReentrantAttribute pada biji-bijian memungkinkan permintaan apa pun ke biji-bijian terjalin dengan permintaan lainnya.
  • Untuk subset metode: Menempatkan AlwaysInterleaveAttribute pada metode antarmuka grain memungkinkan permintaan ke metode tersebut untuk berinteraksi dengan permintaan lain dan memungkinkan permintaan lain untuk menginterleksi permintaan ke metode tersebut.
  • Untuk subset metode: Menempatkan ReadOnlyAttribute pada metode antarmuka grain memungkinkan permintaan ke metode tersebut untuk berselang-seling dengan permintaan lain ReadOnlyAttribute dan memungkinkan permintaan lain ReadOnlyAttribute untuk berselang-seling dengan permintaan ke metode tersebut. Dalam pengertian ini, ini adalah bentuk yang lebih terbatas dari AlwaysInterleaveAttribute.
  • Untuk permintaan apa pun dalam rantai panggilan: RequestContext.AllowCallChainReentrancy() dan RequestContext.SuppressCallChainReentrancy() memungkinkan memilih masuk dan keluar dari mengizinkan permintaan hilir untuk memasukkan kembali gandum. Kedua panggilan mengembalikan nilai yang harus dibuang saat keluar dari permintaan. Oleh karena itu, gunakan sebagai berikut:
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;

Ikut serta dalam reentransi rantai panggilan per butir, per rantai panggilan. Misalnya, pertimbangkan dua butir, A dan B. Jika butir A memungkinkan reentransi rantai panggilan sebelum memanggil butir B, butir B dapat memanggil kembali ke butir A dalam panggilan itu. Namun, grain A tidak dapat memanggil kembali ke grain B jika grain B belum juga mengaktifkan reentransi pada rangkaian panggilan. Pengaktifan dilakukan per-grain dan per-call-chain.

Biji-bijian juga dapat menekan informasi masuknya kembali rantai panggilan dari mengalir ke bawah rantai panggilan menggunakan using var _ = RequestContext.SuppressCallChainReentrancy(). Ini mencegah panggilan berikutnya masuk kembali.

Skrip migrasi ADO.NET

Untuk memastikan kompatibilitas ke depan dengan pengklusteran Orleans, persistensi, dan pengingat yang mengandalkan ADO.NET, diperlukan skrip migrasi SQL yang sesuai:

Pilih file untuk database yang digunakan dan terapkan secara berurutan.

Migrasi dari Orleans 3.x ke 7.0

Untuk Orleans pengguna 3.x, ikuti panduan migrasi di Orleans bagian dokumentasi 7.0 menggunakan pemilih versi di atas.

Penting

Orleans 3.x tidak lagi didukung. Pertimbangkan untuk bermigrasi ke Orleans 10.0 untuk fitur terbaru dan pembaruan keamanan.