Pengembangan dan konfigurasi Azure Functions dengan Azure SignalR Service

Aplikasi Azure Functions dapat menggunakan pengikatan Azure SignalR Service untuk menambahkan kemampuan real time. Aplikasi klien menggunakan SDK klien yang tersedia dalam beberapa bahasa untuk tersambung ke Azure SignalR Service dan menerima pesan real-time.

Artikel ini menjelaskan konsep untuk mengembangkan dan mengonfigurasi aplikasi Azure Function yang terintegrasi dengan SignalR Service.

Konfigurasi SignalR Service

Azure SignalR Service dapat dikonfigurasi dalam mode yang berbeda. Saat digunakan dengan Azure Functions, layanan harus dikonfigurasi dalam mode Tanpa Server.

Di portal Microsoft Azure, temukan halaman Pengaturan sumber daya SignalR Service Anda. Atur mode Layanan ke Tanpa server.

Mode SignalR Service

Pengembangan Azure Functions

Aplikasi real-time tanpa server yang dibangun dengan Azure Functions dan Azure SignalR Service memerlukan setidaknya dua Azure Functions:

  • Fungsi negotiate yang dipanggil klien untuk mendapatkan token akses SignalR Service yang valid dan URL titik akhir.
  • Satu atau beberapa fungsi yang menangani pesan yang dikirim dari SignalR Service ke klien.

Fungsi negosiasi

Aplikasi klien memerlukan token akses yang valid untuk tersambung ke Azure SignalR Service. Token akses dapat berupa anonim atau diautentikasi ke ID pengguna. Aplikasi SignalR Service tanpa server memerlukan titik akhir HTTP bernama negotiate untuk mendapatkan token dan informasi koneksi lainnya, seperti URL titik akhir SignalR Service.

Gunakan Fungsi Azure yang dipicu HTTP dan SignalRConnectionInfo pengikatan input untuk menghasilkan objek informasi koneksi. Fungsi harus memiliki rute HTTP yang berakhiran /negotiate.

Dengan model berbasis kelas di C#, Anda tidak memerlukan SignalRConnectionInfo pengikatan input dan dapat menambahkan klaim kustom dengan lebih mudah. Untuk informasi selengkapnya, lihat Pengalaman negosiasi dalam model berbasis kelas.

Untuk informasi selengkapnya tentang fungsi ini negotiate , lihat Pengembangan Azure Functions.

Untuk mempelajari cara membuat token terautentikasi, lihat Menggunakan Autentikasi App Service.

Menangani pesan yang dikirim dari SignalR Service

Gunakan pengikatan SignalRTrigger untuk menangani pesan yang dikirim dari SignalR Service. Anda bisa mendapatkan pemberitahuan ketika klien mengirim pesan atau klien tersambung atau terputus.

Untuk informasi selengkapnya, lihat referensi pengikatan pemicu SignalR Service.

Anda juga perlu mengonfigurasi titik akhir fungsi Anda sebagai titik akhir upstream sehingga layanan memicu fungsi ketika ada pesan dari klien. Untuk informasi selengkapnya tentang cara mengonfigurasi titik akhir upstram, lihat Titik akhir upstram.

Catatan

SignalR Service tidak mendukung StreamInvocation pesan dari klien dalam Mode Tanpa Server.

Mengirim pesan dan mengelola keanggotaan grup

Gunakan pengikatan SignalR output untuk mengirim pesan ke klien yang terhubung ke Azure SignalR Service. Anda dapat menyiarkan pesan ke semua klien, atau Anda dapat mengirimnya ke subset klien. Misalnya, hanya mengirim pesan ke klien yang diautentikasi dengan ID pengguna tertentu, atau hanya ke grup tertentu.

Pengguna dapat ditambahkan ke satu atau beberapa grup. Anda juga dapat menggunakan pengikatan SignalR output untuk menambahkan atau menghapus pengguna ke/dari grup.

Untuk informasi selengkapnya, lihat SignalR referensi pengikatan output.

Hub SignalR

SignalR memiliki konsep hub. Setiap sambungan klien dan setiap pesan yang dikirim dari Azure Functions dicakup ke hub tertentu. Anda dapat menggunakan hub sebagai cara untuk memisahkan sambungan dan pesan Anda ke dalam namespace layanan logis.

Model berbasis kelas

Model berbasis kelas didedikasikan untuk C#.

Model berbasis kelas memberikan pengalaman pemrograman yang lebih baik, yang dapat menggantikan pengikatan input dan output SignalR, dengan fitur-fitur berikut:

  • Negosiasi yang lebih fleksibel, mengirim pesan, dan mengelola pengalaman grup.
  • Fungsi pengelolaan lainnya didukung, termasuk menutup koneksi, memeriksa apakah koneksi, pengguna, atau grup ada.
  • Hub yang sangat ditik
  • Nama hub terpadu dan pengaturan string koneksi di satu tempat.

Kode berikut menunjukkan cara menulis pengikatan SignalR dalam model berbasis kelas:

Pertama, tentukan hub Anda yang berasal dari kelas ServerlessHub:

[SignalRConnection("AzureSignalRConnectionString")]
public class Functions : ServerlessHub
{
    private const string HubName = nameof(Functions); // Used by SignalR trigger only

    public Functions(IServiceProvider serviceProvider) : base(serviceProvider)
    {
    }

    [Function("negotiate")]
    public async Task<HttpResponseData> Negotiate([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
    {
        var negotiateResponse = await NegotiateAsync(new() { UserId = req.Headers.GetValues("userId").FirstOrDefault() });
        var response = req.CreateResponse();
        response.WriteBytes(negotiateResponse.ToArray());
        return response;
    }

    [Function("Broadcast")]
    public Task Broadcast(
    [SignalRTrigger(HubName, "messages", "broadcast", "message")] SignalRInvocationContext invocationContext, string message)
    {
        return Clients.All.SendAsync("newMessage", new NewMessage(invocationContext, message));
    }

    [Function("JoinGroup")]
    public Task JoinGroup([SignalRTrigger(HubName, "messages", "JoinGroup", "connectionId", "groupName")] SignalRInvocationContext invocationContext, string connectionId, string groupName)
    {
        return Groups.AddToGroupAsync(connectionId, groupName);
    }
}

Dalam file Program.cs, daftarkan hub tanpa server Anda:

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults(b => b.Services
        .AddServerlessHub<Functions>())
    .Build();

Pengalaman negosiasi dalam model berbasis kelas

Alih-alih menggunakan pengikatan [SignalRConnectionInfoInput]input SignalR, negosiasi dalam model berbasis kelas bisa lebih fleksibel. ServerlessHub Kelas dasar memiliki metode NegotiateAsync, yang memungkinkan pengguna untuk menyesuaikan opsi negosiasi seperti userId, , claimsdll.

Task<BinaryData> NegotiateAsync(NegotiationOptions? options = null)

Mengirim pesan dan mengelola pengalaman dalam model berbasis kelas

Anda dapat mengirim pesan, mengelola grup, atau mengelola klien dengan mengakses anggota yang disediakan oleh kelas ServerlessHubdasar .

  • ServerlessHub.Clients untuk mengirim pesan ke klien.
  • ServerlessHub.Groups untuk mengelola koneksi dengan grup, seperti menambahkan koneksi ke grup, menghapus koneksi dari grup.
  • ServerlessHub.UserGroups untuk mengelola pengguna dengan grup, seperti menambahkan pengguna ke grup, menghapus pengguna dari grup.
  • ServerlessHub.ClientManager untuk memeriksa keberadaan koneksi, menutup koneksi, dll.

Hub yang sangat ditik

Hub yang sangat ditik memungkinkan Anda menggunakan metode yang sangat ditik ketika Anda mengirim pesan ke klien. Untuk menggunakan hub yang sangat ditik dalam model berbasis kelas, ekstrak metode klien ke dalam antarmuka T, dan buat kelas hub Anda berasal dari ServerlessHub<T>.

Kode berikut adalah sampel antarmuka untuk metode klien.

public interface IChatClient
{
    Task newMessage(NewMessage message);
}

Kemudian Anda dapat menggunakan metode yang ditik dengan kuat sebagai berikut:

[SignalRConnection("AzureSignalRConnectionString")]
public class Functions : ServerlessHub<IChatClient>
{
    private const string HubName = nameof(Functions);  // Used by SignalR trigger only

    public Functions(IServiceProvider serviceProvider) : base(serviceProvider)
    {
    }

    [Function("Broadcast")]
    public Task Broadcast(
    [SignalRTrigger(HubName, "messages", "broadcast", "message")] SignalRInvocationContext invocationContext, string message)
    {
        return Clients.All.newMessage(new NewMessage(invocationContext, message));
    }
}

Catatan

Anda bisa mendapatkan sampel proyek lengkap dari GitHub.

Nama hub terpadu dan pengaturan string koneksi di satu tempat

  • Nama kelas hub tanpa server secara otomatis digunakan sebagai HubName.
  • Anda mungkin telah memperhatikan atribut yang SignalRConnection digunakan pada kelas hub tanpa server sebagai berikut:
    [SignalRConnection("AzureSignalRConnectionString")]
    public class Functions : ServerlessHub<IChatClient>
    
    Ini memungkinkan Anda untuk menyesuaikan di mana string koneksi untuk hub tanpa server berada. Jika tidak ada, nilai AzureSignalRConnectionString default digunakan.

Penting

Pemicu SignalR dan hub tanpa server bersifat independen. Oleh karena itu, nama kelas hub tanpa server dan SignalRConnection atribut tidak mengubah pengaturan pemicu SignalR, meskipun Anda menggunakan pemicu SignalR di dalam hub tanpa server.

Pengembangan klien

Aplikasi klien SignalR dapat menggunakan SDK klien SignalR dalam salah satu dari beberapa bahasa untuk terhubung dengan mudah dan menerima pesan dari Azure SignalR Service.

Mengonfigurasi sambungan klien

Untuk tersambung ke SignalR Service, klien harus menyelesaikan negosiasi sambungan berhasil yang terdiri dari langkah-langkah berikut:

  1. Buat permintaan ke titik akhir HTTP yang negotiate dibahas di atas untuk mendapatkan informasi koneksi yang valid
  2. Koneksi ke SignalR Service menggunakan URL titik akhir layanan dan token akses yang diperoleh dari negotiate titik akhir

SDK klien SignalR sudah memuat logika yang diperlukan untuk melakukan handshake negosiasi. Teruskan URL titik akhir negosiasi, dikurangi negotiate segmen, ke SDK HubConnectionBuilder. Berikut adalah contoh di JavaScript:

const connection = new signalR.HubConnectionBuilder()
  .withUrl("https://my-signalr-function-app.azurewebsites.net/api")
  .build();

Berdasarkan konvensi, SDK secara otomatis menambahkan /negotiate ke URL dan menggunakannya untuk memulai negosiasi.

Catatan

Jika Anda menggunakan JavaScript/TypeScript SDK di browser, Anda harus mengaktifkan cross-origin resource sharing (CORS) di Function App Anda.

Untuk informasi selengkapnya tentang cara menggunakan SDK klien SignalR, lihat dokumentasi untuk bahasa Anda:

Mengirim pesan dari klien ke layanan

Jika Anda telah mengonfigurasi hulu untuk sumber daya SignalR, Anda dapat mengirim pesan dari klien ke Azure Functions menggunakan klien SignalR apa pun. Berikut adalah contoh di JavaScript:

connection.send("method1", "arg1", "arg2");

Konfigurasi Azure Functions

Aplikasi Azure Function yang terintegrasi dengan Azure SignalR Service dapat digunakan seperti aplikasi Azure Function pada umumnya, menggunakan teknik seperti penyebaran terus menerus, penyebaran zip, dan dijalankan dari paket.

Namun, ada beberapa pertimbangan khusus untuk aplikasi yang menggunakan pengikatan SignalR Service. Jika klien berjalan di browser, CORS harus diaktifkan. Dan jika aplikasi memerlukan autentikasi, Anda dapat mengintegrasikan titik akhir negosiasi dengan Autentikasi App Service.

Mengaktifkan CORS

Klien JavaScript/TypeScript membuat permintaan HTTP ke fungsi negosiasi untuk memulai negosiasi koneksi. Ketika aplikasi klien dihosting di domain yang berbeda dari aplikasi Azure Function, berbagi sumber daya lintas asal (CORS) harus diaktifkan pada aplikasi fungsi, atau browser akan memblokir permintaan.

Localhost

Saat menjalankan aplikasi Function di komputer lokal, Anda dapat menambahkan bagian Host ke local.settings.js untuk mengaktifkan CORS. Di bagian Host tersebut, tambahkan dua properti:

  • CORS - masukkan URL dasar yang merupakan asal aplikasi klien
  • CORSCredentials - atur ke true untuk mengizinkan permintaan "withCredentials"

Contoh:

{
  "IsEncrypted": false,
  "Values": {
    // values
  },
  "Host": {
    "CORS": "http://localhost:8080",
    "CORSCredentials": true
  }
}

Cloud - Azure Functions CORS

Untuk mengaktifkan CORS pada aplikasi Azure Function, buka layar konfigurasi CORS pada tab Fitur platform aplikasi Function Anda di portal Microsoft Azure.

Catatan

Konfigurasi CORS belum tersedia dalam paket Azure Functions Linux Consumption. Gunakan Azure API Management untuk mengaktifkan CORS.

CORS dengan Access-Control-Allow-Credentials harus diaktifkan agar klien SignalR memanggil fungsi negosiasi. Untuk mengaktifkannya, pilih kotak centang.

Di bagian Asal yang diizinkan, tambahkan entri dengan URL dasar asal aplikasi web Anda.

Mengonfigurasi CORS

Cloud - Azure API Management

Azure API Management menyediakan gateway API yang menambahkan kemampuan ke layanan ujung belakang yang ada. Anda dapat menggunakannya untuk menambahkan CORS ke aplikasi fungsi Anda. Ini menawarkan tingkat konsumsi dengan harga bayar per tindakan dan pemberian gratis bulanan.

Lihat dokumentasi API Management untuk informasi tentang cara mengimpor aplikasi Azure Function. Setelah diimpor, Anda bisa menambahkan kebijakan masuk untuk mengaktifkan CORS dengan dukungan Access-Control-Allow-Credentials.

<cors allow-credentials="true">
  <allowed-origins>
    <origin>https://azure-samples.github.io</origin>
  </allowed-origins>
  <allowed-methods>
    <method>GET</method>
    <method>POST</method>
  </allowed-methods>
  <allowed-headers>
    <header>*</header>
  </allowed-headers>
  <expose-headers>
    <header>*</header>
  </expose-headers>
</cors>

Konfigurasikan klien SignalR Anda untuk menggunakan URL API Management.

Menggunakan Autentikasi App Service

Azure Functions memiliki autentikasi bawaan, mendukung penyedia populer seperti Facebook, Twitter, Akun Microsoft, Google, dan ID Microsoft Entra. Fitur ini dapat diintegrasikan dengan SignalRConnectionInfo pengikatan untuk membuat koneksi ke Azure SignalR Service yang diautentikasi ke ID pengguna. Aplikasi Anda dapat mengirim pesan menggunakan pengikatan output yang ditargetkan ke ID pengguna tersebut SignalR .

Di portal Microsoft Azure, di tab Fitur platform aplikasi Fungsi buka jendela pengaturan Autentikasi/otorisasi. Ikuti dokumentasi Autentikasi App Service untuk mengonfigurasi autentikasi menggunakan penyedia identitas pilihan Anda.

Setelah dikonfigurasi, permintaan HTTP yang diautentikasi mencakup x-ms-client-principal-name dan x-ms-client-principal-id header yang masing-masing berisi nama pengguna dan ID pengguna identitas yang diautentikasi.

Anda dapat menggunakan header ini dalam konfigurasi pengikatan Anda SignalRConnectionInfo untuk membuat koneksi terautentikasi. Berikut adalah contoh fungsi negosiasi C# yang menggunakan x-ms-client-principal-id header .

[FunctionName("negotiate")]
public static SignalRConnectionInfo Negotiate(
    [HttpTrigger(AuthorizationLevel.Anonymous)]HttpRequest req,
    [SignalRConnectionInfo
        (HubName = "chat", UserId = "{headers.x-ms-client-principal-id}")]
        SignalRConnectionInfo connectionInfo)
{
    // connectionInfo contains an access key token with a name identifier claim set to the authenticated user
    return connectionInfo;
}

Anda lalu dapat mengirim pesan ke pengguna tersebut dengan mengatur properti UserId pesan SignalR.

[FunctionName("SendMessage")]
public static Task SendMessage(
    [HttpTrigger(AuthorizationLevel.Anonymous, "post")]object message,
    [SignalR(HubName = "chat")]IAsyncCollector<SignalRMessage> signalRMessages)
{
    return signalRMessages.AddAsync(
        new SignalRMessage
        {
            // the message will only be sent to these user IDs
            UserId = "userId1",
            Target = "newMessage",
            Arguments = new [] { message }
        });
}

Untuk informasi mengenai bahasa lain, lihat pengikatan Azure SignalR Service untuk referensi Azure Functions.

Langkah berikutnya

Dalam artikel ini, Anda mempelajari cara mengembangkan dan mengonfigurasi aplikasi SignalR Service tanpa server menggunakan Azure Functions. Cobalah membuat aplikasi sendiri menggunakan salah satu mulai cepat atau tutorial di halaman ringkasan SignalR Service.