Öğretici: Alt protokol kullanarak WebSocket istemcileri arasında iletiler yayımlama ve iletilere abone olma

Sohbet uygulaması oluşturma öğreticisinde, Azure Web PubSub ile veri göndermek ve almak için WebSocket API'lerini kullanmayı öğrendiniz. İstemci hizmetle iletişim kurarken gerekli bir protokol olmadığını görebilirsiniz. Örneğin, kullanarak WebSocket.send()herhangi bir veri türünü gönderebilirsiniz ve sunucu bu verileri olduğu gibi alır. WebSocket API'leri işleminin kullanımı kolaydır, ancak işlevsellik sınırlıdır. Örneğin, olayı sunucunuza gönderirken olay adını belirtemez veya iletiyi sunucunuza göndermek yerine diğer istemcilere yayımlayamazsınız. Bu öğreticide, istemcinin işlevselliğini genişletmek için alt protokol kullanmayı öğreneceksiniz.

Bu öğreticide aşağıdakilerin nasıl yapılacağını öğreneceksiniz:

  • Web PubSub hizmet örneği oluşturma
  • WebSocket bağlantısını kurmak için tam URL'yi oluşturma
  • Altprotocol kullanarak WebSocket istemcileri arasında ileti yayımlama

Azure hesabınız yoksa, başlamadan önce ücretsiz hesap oluşturun.

Önkoşullar

  • Bu kurulum, Azure CLI'nın 2.22.0 veya üzeri bir sürümünü gerektirir. Azure Cloud Shell kullanılıyorsa en son sürüm zaten yüklüdür.

Önemli

Ham bağlantı dizesi yalnızca tanıtım amacıyla bu makalede görünür.

Bir bağlantı dizesi, uygulamanızın Azure Web PubSub hizmetine erişmesi için ihtiyaç duyduğu yetkilendirme bilgilerini içerir. Bağlantı dizesindeki erişim anahtarı, hizmetiniz için bir root parolası işlevi görür. Üretim ortamlarında erişim anahtarlarınızı her zaman koruyun. Anahtarlarınızı güvenli bir şekilde yönetmek ve döndürmek ve bağlantınızın WebPubSubServiceClientgüvenliğini sağlamak için Azure Key Vault kullanın.

Erişim anahtarlarını diğer kullanıcılara dağıtmaktan, sabit kodlamaktan veya başkalarının erişebileceği herhangi bir yerde düz metin olarak kaydetmekten kaçının. Ele geçirilmiş olabileceklerini düşünüyorsanız anahtarlarınızı döndürün.

Azure Web PubSub örneği oluşturma

Kaynak grubu oluşturma

Kaynak grubu, Azure kaynaklarının dağıtıldığı ve yönetildiği bir mantıksal kapsayıcıdır. az group create komutunu kullanarak konumunda adlı bir kaynak grubu oluşturun.

az group create --name myResourceGroup --location EastUS

Web PubSub örneği oluşturma

az extension add komutunu çalıştırarak webpubsub uzantısını yükleyin veya geçerli sürüme yükseltin.

az extension add --upgrade --name webpubsub

Oluşturduğunuz kaynak grubunda bir Web PubSub oluşturmak için Azure CLI az webpubsub create komutunu kullanın. Aşağıdaki komut, EastUS'ta myResourceGroup kaynak grubu altında bir Ücretsiz Web PubSub kaynağı oluşturur:

Önemli

Her Web PubSub kaynağının benzersiz bir adı olmalıdır. Aşağıdaki örneklerde <your-unique-resource-name> ifadesini Web PubSub hizmetinizin adıyla değiştirin.

az webpubsub create --name "<your-unique-resource-name>" --resource-group "myResourceGroup" --location "EastUS" --sku Free_F1

Bu komutun çıktısı yeni oluşturulan kaynağın özelliklerini gösterir. Aşağıda listelenen iki özelliği not edin:

  • Kaynak Adı: Yukarıdaki parametreye --name sağladığınız ad.
  • hostName: Örnekte ana bilgisayar adı şeklindedir <your-unique-resource-name>.webpubsub.azure.com/.

Bu noktada, azure hesabınız bu yeni kaynak üzerinde herhangi bir işlem gerçekleştirme yetkisi olan tek hesaptır.

Gelecekte kullanmak üzere ConnectionString'i edinin

Ham bağlantı dizesi yalnızca tanıtım amacıyla bu makalede görünür. Üretim ortamlarında erişim anahtarlarınızı her zaman koruyun. Anahtarlarınızı güvenli bir şekilde yönetmek ve döndürmek ve bağlantınızın WebPubSubServiceClientgüvenliğini sağlamak için Azure Key Vault kullanın.

Hizmetin ConnectionString değerini almak için Azure CLI az webpubsub key komutunu kullanın. Yer tutucuyu <your-unique-resource-name> Azure Web PubSub örneğinizin adıyla değiştirin.

az webpubsub key show --resource-group myResourceGroup --name <your-unique-resource-name> --query primaryConnectionString --output tsv

Daha sonra kullanmak üzere bağlantı dizesi kopyalayın.

Getirilen ConnectionString'i kopyalayın ve bu öğreticide daha sonra <connection_string> değeri olarak kullanın.

Projeyi ayarlama

Önkoşullar

Altprotocol kullanma

İstemci, belirli bir altprotocol kullanarak bir WebSocket bağlantısı başlatabilir. Azure Web PubSub hizmeti, istemcilerin yukarı akış sunucusuna gidiş dönüş yapmak yerine doğrudan Web PubSub hizmeti üzerinden yayınlama/abone olma işlemlerini gerçekleştirebilmesini sağlayan json.webpubsub.azure.v1 adlı bir alt protokolü destekler. Azure Web PubSub tarafından desteklenen JSON WebSocket alt protokolü hakkında ayrıntılar için buna bakın.

Başka protokol adları kullanırsanız, bunlar hizmet tarafından yok sayılır ve connect olay işleyicisinde sunucuya olduğu gibi iletilir; böylece kendi protokollerinizi oluşturabilirsiniz.

Şimdi altprotokolü kullanarak json.webpubsub.azure.v1 bir web uygulaması oluşturalım.

  1. Bağımlılıkları yükleme

    mkdir logstream
    cd logstream
    dotnet new web
    dotnet add package Microsoft.Extensions.Azure
    dotnet add package Azure.Messaging.WebPubSub
    
  2. /negotiate API ve web sayfasını barındırmak için sunucu tarafını oluşturun.

    Aşağıdaki kodla güncelleştirin Program.cs .

    • Hizmet istemcisini eklemek ve bağlantı dizesini yapılandırmadan okumak için AddAzureClients kullanın.
    • Statik dosyaları desteklemek için app.Run(); öğesinden önce app.UseStaticFiles(); ekleyin.
    • Ve app.MapGet öğesini, istemci erişim belirtecini /negotiate isteklerini kullanarak oluşturacak şekilde güncelleştirin.
    using Azure.Messaging.WebPubSub;
    using Microsoft.Extensions.Azure;
    
    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddAzureClients(s =>
    {
        s.AddWebPubSubServiceClient(builder.Configuration["Azure:WebPubSub:ConnectionString"], "stream");
    });
    
    var app = builder.Build();
    app.UseStaticFiles();
    app.MapGet("/negotiate", async context =>
    {
        var service = context.RequestServices.GetRequiredService<WebPubSubServiceClient>();
        var response = new
        {
            url = service.GetClientAccessUri(roles: new string[] { "webpubsub.sendToGroup.stream", "webpubsub.joinLeaveGroup.stream" }).AbsoluteUri
        };
        await context.Response.WriteAsJsonAsync(response);
    });
    
    app.Run();
    
  3. Web sayfasını oluşturma

    Aşağıdaki içeriğe sahip bir HTML sayfası oluşturun ve olarak wwwroot/index.htmlkaydedin:

    <html>
      <body>
        <div id="output"></div>
        <script>
          (async function () {
            let res = await fetch('/negotiate')
            let data = await res.json();
            let ws = new WebSocket(data.url, 'json.webpubsub.azure.v1');
            ws.onopen = () => {
              console.log('connected');
            };
    
            let output = document.querySelector('#output');
            ws.onmessage = event => {
              let d = document.createElement('p');
              d.innerText = event.data;
              output.appendChild(d);
            };
          })();
        </script>
      </body>
    </html>                                                                
    

    Yukarıdaki kod hizmete bağlanır ve sayfaya alınan tüm iletileri yazdırır. Ana değişiklik, WebSocket bağlantısını oluştururken altprotokolü belirtmemizdir.

  4. Sunucuyu çalıştırma

    bağlantı dizesi ayarlamak için .NET Core için Gizli Dizi Yöneticisi aracını kullanırız. Aşağıdaki komutu çalıştırın, <connection_string> öğesini önceki adımda alınanla değiştirin ve öğesini tarayıcıda açın:

    dotnet user-secrets init
    dotnet user-secrets set Azure:WebPubSub:ConnectionString "<connection-string>"
    dotnet run
    

    Chrome kullanıyorsanız F12 tuşuna basabilir veya -Inspect ->>Developer Tools'a sağ tıklayıp Ağ sekmesini seçebilirsiniz. Web sayfasını yüklediğinizde WebSocket bağlantısının kurulduğunu görebilirsiniz. WebSocket bağlantısını incelemek için seçin, istemcide aşağıdaki connected olay iletisinin alındiğini görebilirsiniz. Bu istemci için connectionId oluşturulabildiğini görebilirsiniz.

    {"type":"system","event":"connected","userId":null,"connectionId":"<the_connection_id>"}
    

Alt protokolün yardımıyla, bağlantı connected durumundayken bağlantının bazı üst verilerini alabileceğinizi görebilirsiniz.

İstemci artık düz metin yerine bir JSON iletisi alır. JSON iletisi, iletinin türü ve kaynağı gibi daha fazla bilgi içerir. Bu nedenle, iletide daha fazla işlem yapmak için bu bilgileri kullanabilirsiniz (örneğin, ileti farklı bir kaynaktan geliyorsa farklı bir stilde görüntülenir), sonraki bölümlerde bulabilirsiniz.

İstemciden ileti yayımlama

Sohbet uygulaması oluşturma öğreticisinde, istemci Web PubSub hizmetine WebSocket bağlantısı üzerinden bir ileti gönderdiğinde, hizmet sunucu tarafınızda bir kullanıcı olayını tetikler. Altprotocol ile istemci, JSON iletisi göndererek daha fazla işleve sahiptir. Örneğin, iletileri doğrudan Web PubSub hizmeti aracılığıyla istemciden diğer istemcilere yayımlayabilirsiniz.

Bu, büyük miktarda veriyi diğer istemcilere gerçek zamanlı olarak akışla göndermek istiyorsanız kullanışlıdır. Şimdi bu özelliği kullanarak konsol günlüklerini gerçek zamanlı olarak tarayıcıya aktarabilen bir günlük akışı uygulaması oluşturalım.

  1. Akış programı oluşturma

    stream Program oluşturma:

    mkdir stream
    cd stream
    dotnet new console
    

    Aşağıdaki içerikle güncelleştirin Program.cs :

    using System;
    using System.Net.Http;
    using System.Net.WebSockets;
    using System.Text;
    using System.Text.Json;
    using System.Threading.Tasks;
    
    namespace stream
    {
        class Program
        {
            private static readonly HttpClient http = new HttpClient();
            static async Task Main(string[] args)
            {
                // Get client url from remote
                var stream = await http.GetStreamAsync("http://localhost:5000/negotiate");
                var url = (await JsonSerializer.DeserializeAsync<ClientToken>(stream)).url;
                var client = new ClientWebSocket();
                client.Options.AddSubProtocol("json.webpubsub.azure.v1");
    
                await client.ConnectAsync(new Uri(url), default);
    
                Console.WriteLine("Connected.");
                var streaming = Console.ReadLine();
                while (streaming != null)
                {
                    if (!string.IsNullOrEmpty(streaming))
                    {
                        var message = JsonSerializer.Serialize(new
                        {
                            type = "sendToGroup",
                            group = "stream",
                            data = streaming + Environment.NewLine,
                        });
                        Console.WriteLine("Sending " + message);
                        await client.SendAsync(Encoding.UTF8.GetBytes(message), WebSocketMessageType.Text, true, default);
                    }
    
                    streaming = Console.ReadLine();
                }
    
                await client.CloseAsync(WebSocketCloseStatus.NormalClosure, null, default);
            }
    
            private sealed class ClientToken
            {
                public string url { get; set; }
            }
        }
    }
    
    

    Burada yeni bir "grup" kavramı olduğunu görebilirsiniz. Grup, bir bağlantı grubuna ileti yayımlayabileceğiniz bir hub'daki mantıksal kavramdır. Bir hub'da birden çok gruba sahip olabilirsiniz ve bir istemci aynı anda birden çok gruba abone olabilir. Altprotocol kullanırken, hub'ın tamamına yayınlamak yerine yalnızca bir gruba yayımlayabilirsiniz. Terimler hakkında ayrıntılı bilgi için temel kavramları gözden geçirin.

  2. Burada group kullandığımız için, WebSocket bağlantısı ws.onopen geri çağrısı içinde kurulduğunda gruba katılmak üzere web sayfasını index.html da güncellememiz gerekir.

    let ackId = 0;
    ws.onopen = () => {
      console.log('connected');
      ws.send(JSON.stringify({
        type: 'joinGroup',
        group: 'stream',
        ackId: ++ackId
      }));
    };
    

    türünde bir ileti joinGroup göndererek istemcinin gruba katıldığını görebilirsiniz.

  3. Ayrıca JSON yanıtını ws.onmessage ayrıştırmak için geri çağırma mantığını biraz güncelleştirin ve iletileri yalnızca gruptan stream yazdırarak canlı akış yazıcısı işlevi görebilmesini sağlayın.

    ws.onmessage = event => {
      let message = JSON.parse(event.data);
      if (message.type === 'message' && message.group === 'stream') {
        let d = document.createElement('span');
        d.innerText = message.data;
        output.appendChild(d);
        window.scrollTo(0, document.body.scrollHeight);
      }
    };
    
  4. Güvenlikle ilgili dikkat edilmesi gerekenler için, istemci varsayılan olarak bir grubu tek başına yayımlayamaz veya gruba abone olamaz. Yani, belirteci oluştururken roles öğesini istemci olarak ayarladığımızı fark ettiniz mi?

    Startup.cs içinde GenerateClientAccessUri olduğunda roles değerini aşağıdaki gibi ayarlayın:

    service.GenerateClientAccessUri(roles: new string[] { "webpubsub.sendToGroup.stream", "webpubsub.joinLeaveGroup.stream" })
    
  5. Son olarak, güzel görünmesi için index.html öğesine de biraz stil uygulayın.

    <html>
    
      <head>
        <style>
          #output {
            white-space: pre;
            font-family: monospace;
          }
        </style>
      </head>
    

Şimdi aşağıdaki kodu çalıştırın ve herhangi bir metin yazın; bunlar tarayıcıda gerçek zamanlı olarak görüntülenir:

ls -R | dotnet run

# Or call `dir /s /b | dotnet run` when you are using CMD under Windows

Alternatif olarak, verilerin gerçek zamanlı olarak tarayıcıya akışını görebilmek için verileri daha yavaş hale getirirsiniz:

for i in $(ls -R); do echo $i; sleep 0.1; done | dotnet run

Bu eğitimin tam kod örneğini burada bulabilirsiniz.

Sonraki adımlar

Bu öğretici, Web PubSub hizmetine bağlanma ve altprotocol kullanarak bağlı istemcilere ileti yayımlama hakkında temel bir fikir sağlar.

Hizmetin nasıl kullanılacağı hakkında daha fazla bilgi edinmek için diğer öğreticileri gözden geçirin.