Menghosting dan menyebarkan aplikasi sisi Blazor server

Catatan

Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.

Penting

Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.

Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.

Artikel ini menjelaskan cara menghosting dan menyebarkan aplikasi sisi Blazor server (Blazor Web Apps dan Blazor Server aplikasi) menggunakan ASP.NET Core.

Nilai konfigurasi host

Aplikasi sisi Blazor server dapat menerima nilai konfigurasi Host Generik.

Penyebaran

Menggunakan model hosting sisi server, Blazor dijalankan di server dari dalam aplikasi ASP.NET Core. Pembaruan UI, penanganan peristiwa, dan panggilan JavaScript ditangani melalui SignalR koneksi.

Server web yang mampu menghosting aplikasi ASP.NET Core diperlukan. Visual Studio menyertakan templat proyek aplikasi sisi server. Untuk informasi selengkapnya tentang Blazor templat proyek, lihat struktur proyek ASP.NET CoreBlazor.

Terbitkan aplikasi dalam Konfigurasi rilis bin/Release/{TARGET FRAMEWORK}/publish dan sebarkan konten folder, di mana {TARGET FRAMEWORK} tempat penampung adalah kerangka kerja target.

Skalabilitas

Saat mempertimbangkan skalabilitas satu server (peningkatan skala), memori yang tersedia untuk aplikasi kemungkinan adalah sumber daya pertama yang habis saat permintaan pengguna meningkat. Memori yang tersedia di server memengaruhi:

  • Jumlah sirkuit aktif yang dapat didukung server.
  • Latensi UI pada klien.

Untuk panduan tentang membangun aplikasi sisi Blazor server yang aman dan dapat diskalakan, lihat sumber daya berikut:

Setiap sirkuit menggunakan sekitar 250 KB memori untuk aplikasi gaya Halo Dunia minimal. Ukuran sirkuit tergantung pada kode aplikasi dan persyaratan pemeliharaan status yang terkait dengan setiap komponen. Kami menyarankan agar Anda mengukur tuntutan sumber daya selama pengembangan untuk aplikasi dan infrastruktur Anda, tetapi garis besar berikut dapat menjadi titik awal dalam merencanakan target penyebaran Anda: Jika Anda mengharapkan aplikasi Anda mendukung 5.000 pengguna bersamaan, pertimbangkan untuk menganggarkan setidaknya 1,3 GB memori server ke aplikasi (atau ~273 KB per pengguna).

SignalR konfigurasi

SignalRKondisi hosting dan penskalakan berlaku untuk Blazor aplikasi yang menggunakan SignalR.

Untuk informasi selengkapnya tentang SignalR di Blazor aplikasi, termasuk panduan konfigurasi, lihat panduan ASP.NET CoreBlazorSignalR.

Transportasi

Blazorbekerja paling baik saat menggunakan WebSocket sebagai SignalR transportasi karena latensi yang lebih rendah, keandalan yang lebih baik, dan keamanan yang ditingkatkan. Polling Panjang digunakan oleh SignalR saat WebSockets tidak tersedia atau ketika aplikasi secara eksplisit dikonfigurasi untuk menggunakan Long Polling. Saat menyebarkan ke Azure App Service, konfigurasikan aplikasi untuk menggunakan WebSocket di pengaturan portal Azure untuk layanan. Untuk detail tentang mengonfigurasi aplikasi untuk Azure App Service, lihat SignalR panduan penerbitan.

Peringatan konsol muncul jika Long Polling digunakan:

Gagal tersambung melalui WebSockets, menggunakan transportasi fallback Long Polling. Ini mungkin karena VPN atau proksi memblokir koneksi.

Penyebaran global dan kegagalan koneksi

Rekomendasi untuk penyebaran global ke pusat data geografis:

  • Sebarkan aplikasi ke wilayah tempat sebagian besar pengguna berada.
  • Pertimbangkan peningkatan latensi untuk lalu lintas di seluruh benua. Untuk mengontrol tampilan antarmuka pengguna koneksi ulang, lihat panduan ASP.NET CoreBlazorSignalR.
  • Untuk hosting Azure, gunakan Layanan AzureSignalR.

Layanan Azure SignalR

Untuk Blazor Web Apps yang mengadopsi penyajian sisi server interaktif, pertimbangkan untuk menggunakan Azure SignalR Service. Layanan ini bekerja bersama dengan Hub aplikasi Blazor untuk meningkatkan skala hingga sejumlah besar koneksi bersamaan SignalR . Selain itu, jangkauan global layanan dan pusat data berkinerja tinggi secara signifikan membantu mengurangi latensi karena geografi. Jika lingkungan hosting Anda sudah menangani masalah ini, menggunakan Layanan Azure SignalR tidak diperlukan.

Catatan

Koneksi ulang stateful (WithStatefulReconnect) dirilis dengan .NET 8 tetapi saat ini tidak didukung untuk Layanan Azure SignalR . Untuk informasi selengkapnya, lihat Dukungan Sambungkan Ulang Stateful? (Azure/azure-signalr #1878).

Pertimbangkan untuk menggunakan Azure SignalR Service, yang berfungsi bersama dengan Hub aplikasi Blazor untuk meningkatkan skala hingga sejumlah besar koneksi bersamaan SignalR . Selain itu, jangkauan global layanan dan pusat data berkinerja tinggi secara signifikan membantu mengurangi latensi karena geografi. Jika lingkungan hosting Anda sudah menangani masalah ini, menggunakan Layanan Azure SignalR tidak diperlukan.

Penting

Saat WebSocket dinonaktifkan , Azure App Service mensimulasikan koneksi real time menggunakan HTTP Long Polling. Polling Panjang HTTP terasa lebih lambat daripada berjalan dengan WebSocket diaktifkan, yang tidak menggunakan polling untuk mensimulasikan koneksi server klien. Jika Long Polling harus digunakan, Anda mungkin perlu mengonfigurasi interval polling maksimum (MaxPollIntervalInSeconds), yang menentukan interval polling maksimum yang diizinkan untuk koneksi Long Polling di Azure SignalR Service jika layanan pernah mundur dari WebSockets ke Long Polling. Jika permintaan polling berikutnya tidak masuk dalam MaxPollIntervalInSeconds, Azure SignalR Service akan membersihkan koneksi klien. Perhatikan bahwa Azure SignalR Service juga membersihkan koneksi saat di-cache menunggu untuk menulis ukuran buffer lebih besar dari 1 MB untuk memastikan performa layanan. Nilai default untuk MaxPollIntervalInSeconds adalah 5 detik. Pengaturan dibatasi hingga 1-300 detik.

Sebaiknya gunakan WebSockets untuk aplikasi sisi Blazor server yang disebarkan ke Azure App Service. Layanan Azure SignalR menggunakan WebSocket secara default. Jika aplikasi tidak menggunakan Layanan Azure SignalR , lihat Menerbitkan aplikasi ASP.NET Core SignalR ke Azure App Service.

Untuk informasi selengkapnya, lihat:

Aplikasi harus mendukung afinitas sesi, juga disebut sesi lengket, di mana klien dialihkan kembali ke server yang sama. Untuk mendukung afinitas sesi, pengaturan aplikasi di portal Azure secara otomatis dikonfigurasi (Pengaturan Aplikasi Konfigurasi>: Nama: Azure__SignalR__ServerStickyMode, Nilai: Required). Oleh karena itu, Anda tidak perlu mengonfigurasi aplikasi secara manual untuk afinitas sesi.

Jika Anda lebih suka tidak menggunakan pengaturan aplikasi di Azure (dan menghapusnya di portal Azure), dua pendekatan lain untuk mengonfigurasi afinitas sesi adalah (gunakan salah satu pendekatan, bukan keduanya):

  • Atur opsi di Program.cs:

    builder.Services.AddSignalR().AddAzureSignalR(options =>
    {
        options.ServerStickyMode = 
            Microsoft.Azure.SignalR.ServerStickyMode.Required;
    });
    
  • Konfigurasikan opsi di appsettings.json:

    "Azure:SignalR:ServerStickyMode": "Required"
    

Catatan

Kesalahan berikut dilemparkan oleh aplikasi yang belum mengaktifkan afinitas sesi:

blazor.server.js:1 Uncaught (in promise) Error: Invocation canceled due to the underlying connection being closed.

Untuk memprovisikan Layanan Azure SignalR untuk aplikasi di Visual Studio:

  1. Buat profil publikasi Azure Apps di Visual Studio untuk aplikasi.
  2. Tambahkan dependensi Layanan Azure SignalR ke profil. Jika langganan Azure tidak memiliki instans Azure SignalR Service yang sudah ada sebelumnya untuk ditetapkan ke aplikasi, pilih Buat instans Azure SignalR Service baru untuk menyediakan instans layanan baru.
  3. Menerbitkan aplikasi ke Azure.

Provisi Layanan Azure SignalR di Visual Studio secara otomatis menambahkan SignalR string koneksi ke konfigurasi layanan aplikasi.

Azure App Service

Menghosting Blazor Aplikasi Web yang menggunakan penyajian sisi server interaktif di Azure App Service memerlukan konfigurasi untuk afinitas Application Request Routing (ARR) dan WebSockets. App Service juga harus didistribusikan secara tepat secara global untuk mengurangi latensi UI. Menggunakan Azure SignalR Service saat menghosting di Azure App Service tidak diperlukan.

Menghosting Blazor Server aplikasi di Azure App Service memerlukan konfigurasi untuk afinitas Perutean Permintaan Aplikasi (ARR) dan WebSocket. App Service juga harus didistribusikan secara tepat secara global untuk mengurangi latensi UI. Menggunakan Azure SignalR Service saat menghosting di Azure App Service tidak diperlukan.

  1. Gunakan panduan berikut untuk mengonfigurasi layanan:

Azure Container Apps

Untuk eksplorasi yang lebih dalam tentang penskalaan aplikasi sisi Blazor server di layanan Azure Container Apps, lihat Penskalaan ASP.NET Core Apps di Azure. Tutorial ini menjelaskan cara membuat dan mengintegrasikan layanan yang diperlukan untuk menghosting aplikasi di Azure Container Apps. Langkah-langkah dasar juga disediakan di bagian ini.

  1. Konfigurasikan layanan Azure Container Apps untuk afinitas sesi dengan mengikuti panduan dalam Afinitas Sesi di Azure Container Apps (dokumentasi Azure).

  2. Layanan ASP.NET Core Data Protection harus dikonfigurasi untuk mempertahankan kunci di lokasi terpusat yang dapat diakses semua instans kontainer. Kunci dapat disimpan di Azure Blob Storage dan dilindungi dengan Azure Key Vault. Layanan perlindungan data menggunakan kunci untuk mendeserialisasi Razor komponen. Untuk mengonfigurasi layanan perlindungan data untuk menggunakan Azure Blob Storage dan Azure Key Vault, lihat paket NuGet berikut:

    Catatan

    Untuk panduan tentang menambahkan paket ke aplikasi .NET, lihat artikel di bagian Menginstal dan mengelola paket di Alur kerja konsumsi paket (dokumentasi NuGet). Konfirmasikan versi paket yang benar di NuGet.org.

  3. Perbarui Program.cs dengan kode yang disorot berikut:

    using Azure.Identity;
    using Microsoft.AspNetCore.DataProtection;
    using Microsoft.Extensions.Azure;
    
    var builder = WebApplication.CreateBuilder(args);
    var BlobStorageUri = builder.Configuration["AzureURIs:BlobStorage"];
    var KeyVaultURI = builder.Configuration["AzureURIs:KeyVault"];
    
    builder.Services.AddRazorPages();
    builder.Services.AddHttpClient();
    builder.Services.AddServerSideBlazor();
    
    builder.Services.AddAzureClientsCore();
    
    builder.Services.AddDataProtection()
                    .PersistKeysToAzureBlobStorage(new Uri(BlobStorageUri),
                                                    new DefaultAzureCredential())
                    .ProtectKeysWithAzureKeyVault(new Uri(KeyVaultURI),
                                                    new DefaultAzureCredential());
    var app = builder.Build();
    
    if (!app.Environment.IsDevelopment())
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }
    
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    
    app.UseRouting();
    
    app.UseAuthorization();
    
    app.MapRazorPages();
    
    app.Run();
    

    Perubahan sebelumnya memungkinkan aplikasi mengelola perlindungan data menggunakan arsitektur terpusat dan dapat diskalakan. DefaultAzureCredential menemukan identitas terkelola aplikasi kontainer setelah kode disebarkan ke Azure dan menggunakannya untuk menyambungkan ke penyimpanan blob dan brankas kunci aplikasi.

  4. Untuk membuat identitas terkelola aplikasi kontainer dan memberinya akses ke penyimpanan blob dan brankas kunci, selesaikan langkah-langkah berikut:

    1. Di Portal Microsoft Azure, buka halaman gambaran umum aplikasi kontainer.
    2. Pilih Layanan Koneksi atau dari navigasi kiri.
    3. Pilih + Buat dari navigasi atas.
    4. Di menu Buat flyout koneksi, masukkan nilai berikut ini:
      • Kontainer: Pilih aplikasi kontainer yang Anda buat untuk menghosting aplikasi Anda.
      • Jenis layanan: Pilih Blob Storage.
      • Langganan: Pilih langganan yang memiliki aplikasi kontainer.
      • nama Koneksi ion: Masukkan nama scalablerazorstorage.
      • Jenis klien: Pilih .NET lalu pilih Berikutnya.
    5. Pilih Identitas terkelola yang ditetapkan sistem dan pilih Berikutnya.
    6. Gunakan pengaturan jaringan default dan pilih Berikutnya.
    7. Setelah Azure memvalidasi pengaturan, pilih Buat.

    Ulangi pengaturan sebelumnya untuk brankas kunci. Pilih layanan dan kunci brankas kunci yang sesuai di tab Dasar .

IIS

Saat menggunakan IIS, aktifkan:

Untuk informasi selengkapnya, lihat panduan dan tautan silang sumber daya IIS eksternal di Menerbitkan aplikasi ASP.NET Core ke IIS.

Kubernetes

Buat definisi ingress dengan anotasi Kubernetes berikut untuk sesi lekat:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: <ingress-name>
  annotations:
    nginx.ingress.kubernetes.io/affinity: "cookie"
    nginx.ingress.kubernetes.io/session-cookie-name: "affinity"
    nginx.ingress.kubernetes.io/session-cookie-expires: "14400"
    nginx.ingress.kubernetes.io/session-cookie-max-age: "14400"

Linux dengan Nginx

Ikuti panduan untuk aplikasi ASP.NET Core SignalR dengan perubahan berikut:

  • location Ubah jalur dari /hubroute (location /hubroute { ... }) ke jalur / akar (location / { ... }).
  • Hapus konfigurasi untuk buffering proksi (proxy_buffering off;) karena pengaturan hanya berlaku untuk Peristiwa Terkirim Server (SSE), yang tidak relevan dengan Blazor interaksi server klien aplikasi.

Untuk informasi selengkapnya dan panduan konfigurasi, lihat sumber daya berikut:

Linux dengan Apache

Untuk menghosting Blazor aplikasi di belakang Apache di Linux, konfigurasikan ProxyPass untuk lalu lintas HTTP dan WebSockets.

Dalam contoh berikut:

  • Kestrel server berjalan pada komputer host.
  • Aplikasi ini mendengarkan lalu lintas di port 5000.
ProxyPreserveHost   On
ProxyPassMatch      ^/_blazor/(.*) http://localhost:5000/_blazor/$1
ProxyPass           /_blazor ws://localhost:5000/_blazor
ProxyPass           / http://localhost:5000/
ProxyPassReverse    / http://localhost:5000/

Aktifkan modul berikut:

a2enmod   proxy
a2enmod   proxy_wstunnel

Periksa konsol browser untuk kesalahan WebSockets. Contoh kesalahan:

  • Firefox tidak dapat membuat koneksi ke server di ws://the-domain-name.tld/_blazor?id=XXX
  • Kesalahan: Gagal memulai transportasi 'WebSockets': Kesalahan: Terjadi kesalahan dengan transportasi.
  • Kesalahan: Gagal memulai transportasi 'LongPolling': TypeError: this.transport tidak terdefinisi
  • Kesalahan: Tidak dapat tersambung ke server dengan salah satu transportasi yang tersedia. WebSocket gagal
  • Kesalahan: Tidak dapat mengirim data jika koneksi tidak dalam Status 'Koneksi ed'.

Untuk informasi selengkapnya dan panduan konfigurasi, lihat sumber daya berikut:

Mengukur latensi jaringan

JS interop dapat digunakan untuk mengukur latensi jaringan, seperti yang ditunjukkan contoh berikut.

MeasureLatency.razor:

@inject IJSRuntime JS

<h2>Measure Latency</h2>

@if (latency is null)
{
    <span>Calculating...</span>
}
else
{
    <span>@(latency.Value.TotalMilliseconds)ms</span>
}

@code {
    private DateTime startTime;
    private TimeSpan? latency;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            startTime = DateTime.UtcNow;
            var _ = await JS.InvokeAsync<string>("toString");
            latency = DateTime.UtcNow - startTime;
            StateHasChanged();
        }
    }
}
@inject IJSRuntime JS

<h2>Measure Latency</h2>

@if (latency is null)
{
    <span>Calculating...</span>
}
else
{
    <span>@(latency.Value.TotalMilliseconds)ms</span>
}

@code {
    private DateTime startTime;
    private TimeSpan? latency;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            startTime = DateTime.UtcNow;
            var _ = await JS.InvokeAsync<string>("toString");
            latency = DateTime.UtcNow - startTime;
            StateHasChanged();
        }
    }
}
@inject IJSRuntime JS

<h2>Measure Latency</h2>

@if (latency is null)
{
    <span>Calculating...</span>
}
else
{
    <span>@(latency.Value.TotalMilliseconds)ms</span>
}

@code {
    private DateTime startTime;
    private TimeSpan? latency;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            startTime = DateTime.UtcNow;
            var _ = await JS.InvokeAsync<string>("toString");
            latency = DateTime.UtcNow - startTime;
            StateHasChanged();
        }
    }
}
@inject IJSRuntime JS

@if (latency is null)
{
    <span>Calculating...</span>
}
else
{
    <span>@(latency.Value.TotalMilliseconds)ms</span>
}

@code {
    private DateTime startTime;
    private TimeSpan? latency;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            startTime = DateTime.UtcNow;
            var _ = await JS.InvokeAsync<string>("toString");
            latency = DateTime.UtcNow - startTime;
            StateHasChanged();
        }
    }
}

Untuk pengalaman UI yang wajar, kami merekomendasikan latensi UI berkelanjutan sebesar 250 mdtk atau kurang.

Manajemen memori

Di server, sirkuit baru dibuat untuk setiap sesi pengguna. Setiap sesi pengguna sesuai dengan penyajian satu dokumen di browser. Misalnya, beberapa tab membuat beberapa sesi.

Blazor mempertahankan koneksi konstan ke browser, yang disebut sirkuit, yang memulai sesi. Koneksi dapat hilang kapan saja karena beberapa alasan, seperti ketika pengguna kehilangan konektivitas jaringan atau menutup browser secara tiba-tiba. Ketika koneksi hilang, Blazor memiliki mekanisme pemulihan yang menempatkan sejumlah sirkuit terbatas dalam kumpulan "terputus", memberi klien waktu terbatas untuk menyambungkan kembali dan membangun kembali sesi (default: 3 menit).

Setelah itu, Blazor merilis sirkuit dan membuang sesi. Sejak saat itu, sirkuit memenuhi syarat untuk pengumpulan sampah (GC) dan diklaim ketika koleksi untuk generasi GC sirkuit dipicu. Salah satu aspek penting untuk dipahami adalah bahwa sirkuit memiliki masa pakai yang panjang, yang berarti bahwa sebagian besar objek yang diakar oleh sirkuit akhirnya mencapai Gen 2. Akibatnya, Anda mungkin tidak melihat objek tersebut dirilis hingga koleksi Gen 2 terjadi.

Mengukur penggunaan memori secara umum

Prasyarat:

  • Aplikasi harus diterbitkan dalam konfigurasi Rilis . Pengukuran konfigurasi debug tidak relevan, karena kode yang dihasilkan tidak mewakili kode yang digunakan untuk penyebaran produksi.
  • Aplikasi harus berjalan tanpa debugger terlampir, karena ini mungkin juga memengaruhi perilaku aplikasi dan merusak hasilnya. Di Visual Studio, mulai aplikasi tanpa penelusuran kesalahan dengan memilih Debug>Mulai Tanpa Debugging dari bilah menu atau Ctrl+F5 menggunakan keyboard.
  • Pertimbangkan berbagai jenis memori untuk memahami berapa banyak memori yang sebenarnya digunakan oleh .NET. Umumnya, pengembang memeriksa penggunaan memori aplikasi di Task Manager pada OS Windows, yang biasanya menawarkan batas atas memori aktual yang digunakan. Untuk informasi selengkapnya, lihat artikel berikut:

Penggunaan memori diterapkan ke Blazor

Kami menghitung memori yang digunakan oleh blazor sebagai berikut:

(Sirkuit Aktif × Memori Per sirkuit) + (Sirkuit Terputus × Memori Per sirkuit)

Jumlah memori yang digunakan sirkuit dan potensi maksimum sirkuit aktif yang dapat dipertahankan aplikasi sangat tergantung pada cara aplikasi ditulis. Jumlah maksimum kemungkinan sirkuit aktif kira-kira dijelaskan oleh:

Memori Maksimum yang / Tersedia Per Sirkuit Memori = Maksimum PotensiAl Sirkuit Aktif

Agar kebocoran memori terjadi di Blazor, hal berikut harus benar:

  • Memori harus dialokasikan oleh kerangka kerja, bukan aplikasi. Jika Anda mengalokasikan array 1 GB di aplikasi, aplikasi harus mengelola pembuangan array.
  • Memori tidak boleh digunakan secara aktif, yang berarti sirkuit tidak aktif dan telah dikeluarkan dari cache sirkuit yang terputus. Jika Anda memiliki sirkuit aktif maksimum yang berjalan, kehabisan memori adalah masalah skala, bukan kebocoran memori.
  • Pengumpul sampah (GC) untuk generasi GC sirkuit telah berjalan, tetapi pengumpul sampah belum dapat mengklaim sirkuit karena objek lain dalam kerangka kerja memegang referensi yang kuat ke sirkuit.

Dalam kasus lain, tidak ada kebocoran memori. Jika sirkuit aktif (tersambung atau terputus), sirkuit masih digunakan.

Jika koleksi untuk generasi GC sirkuit tidak berjalan, memori tidak dirilis karena pengumpul sampah tidak perlu membebaskan memori pada saat itu.

Jika koleksi untuk generasi GC berjalan dan membebaskan sirkuit, Anda harus memvalidasi memori terhadap statistik GC, bukan prosesnya, karena .NET mungkin memutuskan untuk menjaga memori virtual tetap aktif.

Jika memori tidak dibesarkan, Anda harus menemukan sirkuit yang tidak aktif atau terputus dan itu berakar oleh objek lain dalam kerangka kerja. Dalam kasus lain, ketidakmampuan untuk mengosongkan memori adalah masalah aplikasi dalam kode pengembang.

Mengurangi penggunaan memori

Adopsi salah satu strategi berikut untuk mengurangi penggunaan memori aplikasi:

  • Batasi jumlah total memori yang digunakan oleh proses .NET. Untuk informasi selengkapnya, lihat Opsi konfigurasi runtime untuk pengumpulan sampah.
  • Kurangi jumlah sirkuit yang terputus.
  • Kurangi waktu sirkuit diizinkan untuk berada dalam status terputus.
  • Picu pengumpulan sampah secara manual untuk melakukan pengumpulan selama periode waktu henti.
  • Konfigurasikan pengumpulan sampah dalam mode Stasiun Kerja, yang secara agresif memicu pengumpulan sampah, bukan mode Server.

Ukuran timbunan untuk beberapa browser perangkat seluler

Saat membuat Blazor aplikasi yang berjalan pada klien dan menargetkan browser perangkat seluler, terutama Safari di iOS, mengurangi memori maksimum untuk aplikasi dengan properti EmccMaximumHeapSize MSBuild mungkin diperlukan. Untuk informasi selengkapnya, lihat Host dan sebarkan ASP.NET Core Blazor WebAssembly.

Tindakan dan pertimbangan tambahan

  • Ambil cadangan memori proses ketika tuntutan memori tinggi dan identifikasi objek mengambil memori paling banyak dan di mana objek tersebut berakar (apa yang menyimpan referensi untuk mereka).
  • Anda dapat memeriksa statistik tentang bagaimana memori di aplikasi Anda berulah menggunakan dotnet-counters. Untuk informasi selengkapnya, lihat Menyelidiki penghitung kinerja (penghitung dotnet).
  • Bahkan ketika GC dipicu, .NET berpegang pada memori alih-alih segera mengembalikannya ke OS, karena kemungkinan akan menggunakan kembali memori dalam waktu dekat. Ini menghindari penerapan dan penolakan memori terus-menerus, yang mahal. Anda akan melihat ini tercermin jika Anda menggunakan dotnet-counters karena Anda akan melihat GC terjadi dan jumlah memori yang digunakan turun ke 0 (nol), tetapi Anda tidak akan melihat penurunan penghitung set kerja, yang merupakan tanda bahwa .NET memegang memori untuk menggunakannya kembali. Untuk informasi selengkapnya tentang pengaturan file proyek (.csproj) untuk mengontrol perilaku ini, lihat Opsi konfigurasi runtime untuk pengumpulan sampah.
  • Server GC tidak memicu pengumpulan sampah sampai menentukan benar-benar perlu untuk melakukannya untuk menghindari pembekuan aplikasi Anda dan menganggap bahwa aplikasi Anda adalah satu-satunya hal yang berjalan di komputer, sehingga dapat menggunakan semua memori dalam sistem. Jika sistem memiliki 50 GB, pengumpul sampah berusaha menggunakan memori 50 GB penuh yang tersedia sebelum memicu koleksi Gen 2.
  • Untuk informasi tentang konfigurasi retensi sirkuit yang terputus, lihat panduan ASP.NET CoreBlazorSignalR.

Mengukur memori

  • Terbitkan aplikasi dalam Konfigurasi rilis.
  • Jalankan versi aplikasi yang diterbitkan.
  • Jangan lampirkan debugger ke aplikasi yang sedang berjalan.
  • Apakah memicu koleksi gen 2 yang dipaksakan dan memadatkan (GC.Collect(2, GCCollectionMode.Aggressive | GCCollectionMode.Forced, blocking: true, compacting: true)) bebaskan memori?
  • Pertimbangkan apakah aplikasi Anda mengalokasikan objek pada timbunan objek besar.
  • Apakah Anda menguji pertumbuhan memori setelah aplikasi dihangatkan dengan permintaan dan pemrosesan? Biasanya, ada cache yang diisi saat kode dijalankan untuk pertama kalinya yang menambahkan jumlah memori konstan ke jejak aplikasi.