Biblioteca de clientes do Web PubSub para JavaScript

O Azure Web PubSub é um serviço de nuvem que ajuda os desenvolvedores a criar facilmente recursos em tempo real em aplicativos Web com padrões de publicação-assinatura em escala.

Qualquer cenário que exija mensagens em tempo real entre servidor e clientes ou entre clientes que seguem padrões de publicação/assinatura pode se beneficiar do uso do Web PubSub. Os desenvolvedores não precisam mais sondar o servidor enviando solicitações HTTP repetidas em intervalos, o que é um desperdício e difícil de dimensionar.

Conforme mostrado no diagrama abaixo, seus clientes estabelecem conexões WebSocket com o recurso Web PubSub. Esta biblioteca de clientes:

  • simplifica o gerenciamento de conexões de cliente
  • simplifica o envio de mensagens entre clientes
  • tenta novamente automaticamente após quedas não intencionais da conexão do cliente
  • entrega mensagens de maneira confiável em número e em ordem após a recuperação de quedas de conexão

Estouro

Os detalhes sobre os termos usados aqui são descritos na seção principais conceitos .

Essa biblioteca está hospedada no NPM.


Introdução

Ambientes com suporte no momento

Pré-requisitos

1. Instalar o pacote @azure/web-pubsub-client

npm install @azure/web-pubsub-client

2. Conectar-se com o recurso Web PubSub

Um cliente usa uma URL de Acesso ao cliente para se conectar e autenticar com o serviço, que segue um padrão de wss://<service_name>.webpubsub.azure.com/client/hubs/<hub_name>?access_token=<token>. Um cliente pode ter algumas maneiras de obter a URL de Acesso ao cliente. Para este início rápido, você pode copiar e colar um no Portal do Azure mostrado abaixo. (Para produção, seus clientes geralmente obtêm a URL de Acesso do Cliente criada em seu servidor de aplicativos. Veja os detalhes abaixo )

get_client_url

Conforme mostrado no diagrama acima, o cliente tem as permissões para enviar mensagens e ingressar em um grupo específico chamado "group1".

// Imports the client libray
const { WebPubSubClient } = require("@azure/web-pubsub-client");

// Instantiates the client object
const client = new WebPubSubClient("<client-access-url>");

// Starts the client connection with your Web PubSub resource
await client.start();

// ...
// The client can join/leave groups, send/receive messages to and from those groups all in real-time

3. Unir grupos

Observe que um cliente só pode receber mensagens de grupos que ele ingressou e você precisa adicionar um retorno de chamada para especificar a lógica ao receber mensagens.

// ...continues the code snippet from above

// Specifies the group to join
let groupName = "group1";

// Registers a listener for the event 'group-message' early before joining a group to not miss messages
client.on("group-message", (e) => {
  console.log(`Received message: ${e.message.data}`);
});

// A client needs to join the group it wishes to receive messages from
await client.joinGroup(groupName);

4. Enviar mensagens para um grupo

// ...continues the code snippet from above

// Send a message to a joined group
await client.sendToGroup(groupName, "hello world", "text");

// In the Console tab of your developer tools found in your browser, you should see the message printed there.

Exemplos

Adicionar retornos de chamada para eventos conectados, desconectados e interrompidos

  1. Quando um cliente é conectado com êxito ao recurso Web PubSub, o connected evento é disparado.
client.on("connected", (e) => {
  console.log(`Connection ${e.connectionId} is connected.`);
});
  1. Quando um cliente é desconectado e falha ao recuperar a conexão, o disconnected evento é disparado.
client.on("disconnected", (e) => {
  console.log(`Connection disconnected: ${e.message}`);
});
  1. O stopped evento será disparado quando o cliente for desconectado e o cliente parar de tentar se reconectar. Isso geralmente acontece depois que o client.stop() é chamado ou autoReconnect está desabilitado ou um limite especificado para tentar se reconectar foi atingido. Se você quiser reiniciar o cliente, poderá chamar client.start() no evento parado.
// Registers a listener for the "stopped" event
client.on("stopped", () => {
  console.log(`Client has stopped`);
});

Usar um servidor de negociação para gerar a URL de Acesso ao Cliente programaticamente

Em produção, os clientes geralmente buscam a URL de Acesso ao Cliente de um servidor de aplicativos. O servidor contém a cadeia de conexão para o recurso Web PubSub e gera a URL de Acesso ao Cliente com a ajuda da biblioteca @azure/web-pubsubde servidores .

1. Servidor de aplicativos

O snippet de código abaixo é um exemplo de um servidor de aplicativos que expõe um /negotiate caminho e retorna a URL de Acesso ao Cliente.

// This code snippet uses the popular Express framework
const express = require('express');
const app = express();
const port = 8080;

// Imports the server library, which is different from the client library
const { WebPubSubServiceClient } = require('@azure/web-pubsub');
const hubName = 'sample_chat';

const serviceClient = new WebPubSubServiceClient("<web-pubsub-connectionstring>", hubName);

// Note that the token allows the client to join and send messages to any groups. It is specified with the "roles" option.
app.get('/negotiate', async (req, res) => {
  let token = await serviceClient.getClientAccessToken({roles: ["webpubsub.joinLeaveGroup", "webpubsub.sendToGroup"] });
  res.json({
    url: token.url
  });
});

app.listen(port, () => console.log(`Application server listening at http://localhost:${port}/negotiate`));

2. Lado do cliente

O snippet de código abaixo é um exemplo do lado do cliente.

const { WebPubSubClient } = require("@azure/web-pubsub-client")

const client = new WebPubSubClient({
  getClientAccessUrl: async () => {
    let value = await (await fetch(`/negotiate`)).json();
    return value.url;
  }
});

await client.start();

Para ver o código completo deste exemplo, consulte samples-browser.


Um cliente consome mensagens do servidor de aplicativos ou grupos ingressados

Um cliente pode adicionar retornos de chamada para consumir mensagens do servidor ou grupos de aplicativos. Observe que, para group-message o evento, o cliente pode receber mensagens de grupo ingressadas.

// Registers a listener for the "server-message". The callback will be invoked when your application server sends message to the connectionID, to or broadcast to all connections.
client.on("server-message", (e) => {
  console.log(`Received message ${e.message.data}`);
});

// Registers a listener for the "group-message". The callback will be invoked when the client receives a message from the groups it has joined.
client.on("group-message", (e) => {
    console.log(`Received message from ${e.message.group}: ${e.message.data}`);
});

Manipular falha de reingressão

Quando um cliente é desconectado e falha na recuperação, todos os contextos de grupo serão limpos no recurso Web PubSub. Isso significa que, quando o cliente se reconecta, ele precisa reencontrar grupos. Por padrão, o cliente tem autoRejoinGroup a opção habilitada.

No entanto, você deve estar ciente das autoRejoinGrouplimitações.

  • O cliente só pode reencontrar grupos em que é ingressado originalmente pelo código do cliente e não pelo código do lado do servidor.
  • As operações de "reencontrar grupo" podem falhar devido a vários motivos, por exemplo, o cliente não tem permissão para ingressar nos grupos. Nesses casos, você precisa adicionar um retorno de chamada para lidar com essa falha.
// By default autoRejoinGroups=true. You can disable it by setting to false.
const client = new WebPubSubClient("<client-access-url>", { autoRejoinGroups: true });

// Registers a listener to handle "rejoin-group-failed" event
client.on("rejoin-group-failed", e => {
  console.log(`Rejoin group ${e.group} failed: ${e.error}`);
})

Operação e repetição

Por padrão, a operação como client.joinGroup(), client.leaveGroup(), client.sendToGroup()tem client.sendEvent() três tentativas. Você pode configurar por meio do messageRetryOptions. Se todas as tentativas falharem, um erro será gerado. Você pode continuar tentando novamente passando o mesmo ackId que as tentativas anteriores para que o serviço Web PubSub possa deduplicar a operação.

try {
  await client.joinGroup(groupName);
} catch (err) {
  let id = null;
  if (err instanceof SendMessageError) {
    id = err.ackId;
  }
  await client.joinGroup(groupName, {ackId: id});
}

Especificar subprotocol

Você pode alterar o subprotocol a ser usado pelo cliente. Por padrão, o cliente usa json.reliable.webpubsub.azure.v1. Você pode optar por usar json.reliable.webpubsub.azure.v1 ou json.webpubsub.azure.v1.

// Change to use json.webpubsub.azure.v1
const client = new WebPubSubClient("<client-access-url>", { protocol: WebPubSubJsonProtocol() });
// Change to use json.reliable.webpubsub.azure.v1
const client = new WebPubSubClient("<client-access-url>", { protocol: WebPubSubJsonReliableProtocol() });

Principais conceitos

Conexão

Uma conexão, também conhecida como um cliente ou uma conexão de cliente, representa uma conexão WebSocket individual conectada ao Web PubSub. Quando conectado com êxito, uma ID de conexão exclusiva é atribuída a essa conexão pelo Web PubSub. Cada WebPubSubClient um cria sua própria conexão exclusiva.

Recuperação

Se um cliente que usa protocolos confiáveis se desconectar, um novo WebSocket tentará estabelecer usando a ID de conexão da conexão perdida. Se a nova conexão WebSocket for conectada com êxito, a conexão será recuperada. Ao longo do tempo em que um cliente é desconectado, o serviço retém o contexto do cliente, bem como todas as mensagens às quais o cliente foi inscrito e, quando o cliente se recuperar, o serviço enviará essas mensagens ao cliente. Se o serviço retornar o código 1008 de erro WebSocket ou a tentativa de recuperação durar mais de 30 segundos, a recuperação falhará.

Reconectar

A reconexão ocorre quando a conexão do cliente é descartada e falha na recuperação. A reconexão inicia uma nova conexão e a nova conexão tem uma nova ID de conexão. Ao contrário da recuperação, o serviço trata o cliente reconectado como uma nova conexão de cliente. A conexão do cliente precisa reencontrar grupos. Por padrão, a biblioteca de clientes reencontra grupos após a reconexão.

Hub

Um hub é um conceito lógico para um conjunto de conexões de cliente. Normalmente, você usa um hub para uma finalidade, por exemplo, um hub de chat ou um hub de notificação. Quando uma conexão de cliente é criada, ela se conecta a um hub e, durante seu tempo de vida, pertence a esse hub. Aplicativos diferentes podem compartilhar um Web PubSub usando nomes de hub diferentes.

Grupo

Um grupo é um subconjunto de conexões com o hub. Você pode adicionar uma conexão de cliente a um grupo ou removê-la do grupo sempre que desejar. Por exemplo, quando um cliente entra em uma sala de chat ou quando um cliente sai da sala de chat, essa sala de chat pode ser considerada um grupo. Um cliente pode ingressar em vários grupos e um grupo pode conter vários clientes.

Usuário

As conexões com o Web PubSub podem pertencer a um usuário. Um usuário pode ter várias conexões, por exemplo, quando apenas um usuário está conectado a vários dispositivos ou a várias guias do navegador.


Tempo de vida do cliente

Cada um dos clientes do Web PubSub é seguro para armazenar em cache e ser usado como singleton durante o tempo de vida do aplicativo. Os retornos de chamada de evento registrados compartilham o mesmo tempo de vida com o cliente. Isso significa que você pode adicionar ou remover retornos de chamada a qualquer momento e o registro status não será alterado após a reconexão ou o cliente ser interrompido.


Pacote JavaScript

Para usar essa biblioteca de clientes no navegador, primeiro, você precisa usar um empacotador. Para obter detalhes sobre como fazer isso, consulte nossa documentação de agrupamento.


Solução de problemas

  • Habilitar logs

    Você pode definir a variável de ambiente a seguir para obter os logs de depuração ao usar essa biblioteca.

export AZURE_LOG_LEVEL=verbose

Para obter instruções mais detalhadas sobre como habilitar logs, veja os documentos do pacote @azure/logger.


Recursos adicionais


Contribuição

Se você quiser contribuir com essa biblioteca, leia o guia de contribuição para saber como criar e testar o código.