Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Este documento descreve o subprotocolo protobuf.webpubsub.azure.v1.
Quando um cliente está usando esse subprotocolo, espera-se que os quadros de dados de entrada e de saída sejam cargas úteis de buffers de protocolo (protobuf).
Descrição geral
O subprotocolo protobuf.webpubsub.azure.v1 permite que o cliente faça uma publicação-assinatura (PubSub) diretamente em vez de fazer uma viagem de ida e volta para o servidor upstream. A conexão WebSocket com o protobuf.webpubsub.azure.v1 subprotocolo é chamada de cliente PubSub WebSocket.
Por exemplo, em JavaScript, você pode criar um cliente PubSub WebSocket com o subprotocolo protobuf usando:
// PubSub WebSocket client
var pubsub = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1', 'protobuf.webpubsub.azure.v1');
Para um cliente WebSocket simples, o servidor tem a função necessária de manipular eventos de clientes. Uma conexão WebSocket simples sempre dispara um message evento quando envia mensagens e sempre depende do lado do servidor para processar mensagens e fazer outras operações. Com a ajuda do subprotocolo, um cliente autorizado pode ingressar em um grupo usando protobuf.webpubsub.azure.v1 de associação e publicar mensagens em um grupo usando solicitações de publicação diretamente. O cliente também pode rotear mensagens para vários manipuladores de eventos upstream usando solicitações de evento para personalizar o evento ao qual a mensagem pertence.
Nota
Atualmente, o serviço Web PubSub suporta apenas proto3.
Permissões
Um cliente PubSub WebSocket só pode publicar para outros clientes quando é autorizado. Os roles atribuídos ao cliente determinam as permissões concedidas ao cliente:
| Role | Permissão |
|---|---|
| Não especificado | O cliente pode enviar solicitações de eventos. |
webpubsub.joinLeaveGroup |
O cliente pode entrar/sair de qualquer grupo. |
webpubsub.sendToGroup |
O cliente pode publicar mensagens em qualquer grupo. |
webpubsub.joinLeaveGroup.<group> |
O cliente pode entrar/sair do grupo <group>. |
webpubsub.sendToGroup.<group> |
O cliente pode publicar mensagens no grupo <group>. |
webpubsub.joinLeaveGroups.<pattern> |
O cliente pode juntar-se/sair de qualquer grupo cujo nome corresponda <pattern> (ver padrões de funções de grupo Wildcard). |
webpubsub.sendToGroups.<pattern> |
O cliente pode publicar mensagens para qualquer grupo cujo nome corresponda <pattern> (ver Padrões de papéis de grupo curinga). |
O servidor pode conceder ou revogar dinamicamente permissões de cliente por meio de APIs REST ou SDKs de servidor.
Nota
Os papéis coringa (por exemplo, webpubsub.sendToGroups.<pattern>) ainda não são suportados em APIs REST ou SDKs de servidor durante a execução.
Pedidos do
Todas as mensagens de solicitação aderem ao seguinte formato protobuf:
syntax = "proto3";
import "google/protobuf/any.proto";
message UpstreamMessage {
oneof message {
SendToGroupMessage send_to_group_message = 1;
EventMessage event_message = 5;
JoinGroupMessage join_group_message = 6;
LeaveGroupMessage leave_group_message = 7;
SequenceAckMessage sequence_ack_message = 8;
PingMessage ping_message = 9;
StreamDataMessage stream_data_message = 13;
StreamEndMessage stream_end_message = 14;
}
message SendToGroupMessage {
string group = 1;
optional uint64 ack_id = 2;
MessageData data = 3;
optional bool no_echo = 4;
StreamStartInfo stream = 7;
}
message StreamStartInfo {
string stream_id = 1;
optional uint32 idle_timeout_ms = 2;
}
message EventMessage {
string event = 1;
MessageData data = 2;
optional uint64 ack_id = 3;
}
message JoinGroupMessage {
string group = 1;
optional uint64 ack_id = 2;
}
message LeaveGroupMessage {
string group = 1;
optional uint64 ack_id = 2;
}
message SequenceAckMessage {
uint64 sequence_id = 1;
}
message PingMessage {
}
message StreamDataMessage {
string stream_id = 1;
optional uint64 stream_sequence_id = 2;
MessageData data = 3;
}
message StreamEndMessage {
string stream_id = 1;
optional StreamEndError error = 2;
message StreamEndError {
optional string message = 1;
optional string user_error_code = 2;
}
}
}
message MessageData {
oneof data {
string text_data = 1;
bytes binary_data = 2;
google.protobuf.Any protobuf_data = 3;
}
}
Junte-se a grupos
Formato:
Defina join_group_message.group como o nome do grupo.
-
ackIdé a identidade de cada pedido e deve ser única. O serviço envia uma mensagem de resposta ack para notificar o resultado do processo da solicitação. Mais detalhes podem ser encontrados em AckId e Ack Response
Sair dos grupos
Formato:
Defina leave_group_message.group como o nome do grupo.
-
ackIdé a identidade de cada pedido e deve ser única. O serviço envia uma mensagem de resposta ack para notificar o resultado do processo da solicitação. Mais detalhes podem ser encontrados em AckId e Ack Response
Publicar mensagens
Formato:
ackId: A identidade única de cada pedido. O serviço envia uma mensagem de resposta ack para notificar o resultado do processo da solicitação. Mais detalhes podem ser encontrados em AckId e Ack ResponsedataType: O formato de dados, que pode serprotobuf,textoubinarydependendo dodatainMessageData. Os clientes recetores podem usardataTypepara processar corretamente o conteúdo.protobuf: Quando você definesend_to_group_message.data.protobuf_data, o implícitodataTypeéprotobuf.protobuf_datapode ser do tipo Qualquer mensagem. Todos os outros clientes recebem um binário codificado por protobuf, que pode ser desserializado pelo SDK do protobuf. Os clientes que suportam apenas conteúdo baseado em texto (por exemplo,json.webpubsub.azure.v1) recebem um binário codificado em Base64.text: Quando você definesend_to_group_message.data.text_data, o implícitodataTypeétext.text_datadeve ser uma cadeia de caracteres. Todos os clientes com outros protocolos recebem uma cadeia de caracteres codificada em UTF-8.binary: Quando você definesend_to_group_message.data.binary_data, o implícitodataTypeébinary.binary_datadeve ser uma matriz de bytes. Todos os clientes com outros protocolos recebem um binário bruto sem codificação protobuf. Os clientes que suportam apenas conteúdo baseado em texto (por exemplo,json.webpubsub.azure.v1) recebem um binário codificado em Base64.
Caso 1: Publicar dados de texto
Defina send_to_group_message.group como group, e defina send_to_group_message.data.text_data como "text data".
O cliente de subprotocolo protobuf em grupo
grouprecebe o quadro binário e pode usar DownstreamMessage para desserializá-lo.Os clientes do subprotocolo JSON recebem
group:{ "type": "message", "from": "group", "group": "group", "dataType" : "text", "data" : "text data" }Os clientes WebSocket simples na
groupcadeia de caracterestext datade recebimento .
Caso 2: Publicar dados protobuf
Vamos supor que você tenha uma mensagem personalizada:
message MyMessage {
int32 value = 1;
}
Defina send_to_group_message.group como group e send_to_group_message.data.protobuf_data para Any.pack(MyMessage) com value = 1.
Os clientes do subprotocolo protobuf recebem
groupo quadro binário e podem usar DownstreamMessage para desserializá-lo.O cliente de subprotocolo em
grouprecebe:{ "type": "message", "from": "group", "group": "G", "dataType" : "protobuf", "data" : "Ci90eXBlLmdvb2dsZWFwaXMuY29tL2F6dXJlLndlYnB1YnN1Yi5UZXN0TWVzc2FnZRICCAE=" // Base64-encoded bytes }Nota
Os dados são um binário protobuf desserializável codificado em Base64.
Você pode usar a seguinte definição de protobuf e usá-la Any.unpack() para desserializá-la:
syntax = "proto3";
message MyMessage {
int32 value = 1;
}
Os clientes WebSocket simples em
groupreceber o quadro binário:# Show in hexadecimal 0A 2F 74 79 70 65 2E 67 6F 6F 67 6C 65 61 70 69 73 2E 63 6F 6D 2F 61 7A 75 72 65 2E 77 65 62 70 75 62 73 75 62 2E 54 65 73 74 4D 65 73 73 61 67 65 12 02 08 01
Caso 3: Publicar dados binários
Defina send_to_group_message.group como group, e defina send_to_group_message.data.binary_data como [1, 2, 3].
O cliente de subprotocolo protobuf em grupo
grouprecebe o quadro binário e pode usar DownstreamMessage para desserializá-lo.O cliente de subprotocolo JSON no grupo
grouprecebe:{ "type": "message", "from": "group", "group": "group", "dataType" : "binary", "data" : "AQID", // Base64-encoded [1,2,3] }Como o cliente de subprotocolo JSON suporta apenas mensagens baseadas em texto, o binário é sempre codificado em Base64.
Os clientes WebSocket simples em
groupreceber os dados binários no quadro binário:# Show in hexadecimal 01 02 03
Iniciar transmitir mensagens
Para iniciar um stream de grupo, defina send_to_group_message.group para o grupo alvo e defina send_to_group_message.stream para uma StreamStartInfo mensagem. Um pedido de início de stream não define send_to_group_message.data nem send_to_group_message.ack_id.
-
send_to_group_message.stream.stream_idé o identificador do fluxo lógico. Deve ser uma string não vazia e deve ser única entre os fluxos ativos na mesma ligação do cliente. Recomenda-se que as bibliotecas clientes gerem um valor globalmente único, como um GUID ou UUID. -
send_to_group_message.stream.idle_timeout_msé opcional. Se especificado, deve ser maior que0. Se for omitido, o padrão do serviço é300000milissegundos. O valor é um timeout inativo, não uma vida útil total do fluxo. Envie dados do fluxo, envie um stream keep epalive, ou termine o fluxo antes que este timeout expire, quando a aplicação precisa de manter o stream aberto. -
send_to_group_message.no_echoé opcional. Se definidas como verdadeiras, as mensagens do stream não são enviadas de volta para a mesma ligação. Se não estiver definido, o valor padrão será false.
Quando o fluxo é aceite, o cliente recebe uma resposta de ack do fluxo com expected_sequence_id definido para 1.
Enviar dados em streaming
Para enviar dados de fluxo, defina stream_data_message.stream_id, stream_data_message.stream_sequence_id, e stream_data_message.data.
-
stream_data_message.stream_ididentifica um fluxo ativo na mesma ligação ao cliente. -
stream_data_message.stream_sequence_idé um número uint64 positivo. O primeiro fragmento de dados num fluxo usa1, e cada fragmento de dados seguinte para o mesmostream_idaumenta exatamente1em . -
stream_data_message.datausa as mesmasMessageDataregras de codificação que publish messages.
Para manter um fluxo ativo sem entregar dados aos assinantes, envie stream_data_message apenas stream_id com definido.
Fim das mensagens em streaming
Para terminar uma transmissão, defina stream_end_message.stream_id.
Para terminar um fluxo com um erro definido pela aplicação, defina stream_end_message.error.
-
stream_end_message.error.messageé uma mensagem de erro opcional legível por humanos. -
stream_end_message.error.user_error_codeé um código de erro opcional definido pela aplicação.
Quando o fluxo é encerrado, o editor recebe uma resposta de encerramento do fluxo.
Enviar eventos personalizados
Há um implícito dataType, que pode ser protobuf, text, ou binary, dependendo do dataType seu conjunto. Os clientes recetores podem usar dataType para lidar com o conteúdo corretamente.
protobuf: Quando você defineevent_message.data.protobuf_data, o implícitodataTypeéprotobuf. Oprotobuf_datavalor pode ser qualquer tipo de protobuf suportado. O manipulador de eventos recebe o binário codificado por protobuf, que pode ser desserializado por qualquer SDK de protobuf.text: Quando você defineevent_message.data.text_data, o implícitodataTypeétext. Otext_datavalor deve ser uma cadeia de caracteres. O manipulador de eventos recebe uma cadeia de caracteres codificada em UTF-8.binary: Quando você defineevent_message.data.binary_data, o implícitodataTypeébinary. Obinary_datavalor deve ser uma matriz de bytes. O manipulador de eventos recebe o quadro binário bruto.
Caso 1: Enviar um evento com dados de texto
Defina event_message.data.text_data como "text data".
O manipulador de eventos upstream recebe uma solicitação semelhante a:
POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: text/plain
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.user.<event_name>
ce-source: /client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub_name}
ce-eventName: <event_name>
text data
O Content-Type para a solicitação HTTP do CloudEvents é text/plain, onde dataType=text.
Caso 2: Enviar um evento com dados protobuf
Suponha que você recebeu a seguinte mensagem de cliente:
message MyMessage {
int32 value = 1;
}
Definir event_message.data.protobuf_data como any.pack(MyMessage) com value = 1
O manipulador de eventos upstream recebe uma solicitação semelhante a:
POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: application/json
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.user.<event_name>
ce-source: /client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub_name}
ce-eventName: <event_name>
// Just show in hexadecimal; read it as binary
0A 2F 74 79 70 65 2E 67 6F 6F 67 6C 65 61 70 69 73 2E 63 6F 6D 2F 61 7A 75 72 65 2E 77 65 62 70 75 62 73 75 62 2E 54 65 73 74 4D 65 73 73 61 67 65 12 02 08 01
O Content-Type para a solicitação HTTP do CloudEvents é application/x-protobuf, onde dataType=protobuf.
Os dados são um binário protobuf válido. Você pode usar o seguinte proto e any.unpack() desserializá-lo:
syntax = "proto3";
message MyMessage {
int32 value = 1;
}
Caso 3: Enviar um evento com dados binários
Defina send_to_group_message.binary_data como [1, 2, 3].
O manipulador de eventos upstream recebe uma solicitação semelhante a:
POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: application/octet-stream
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.user.<event_name>
ce-source: /client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub_name}
ce-eventName: <event_name>
// Just show in hexadecimal; you need to read it as binary
01 02 03
Para dataType=binary, a Content-Type solicitação HTTP do CloudEvents é application/octet-stream. O quadro WebSocket pode estar em formato para quadros de mensagem de texto ou binários codificados em text UTF-8 para binary quadros de mensagem.
O serviço recusa o cliente se a mensagem não corresponder ao formato prescrito.
Ping
O cliente pode enviar um PingMessage para o serviço para habilitar o serviço Web PubSub para detetar a vivacidade do cliente.
Respostas
Todas as mensagens de resposta aderem ao seguinte formato protobuf:
message DownstreamMessage {
oneof message {
AckMessage ack_message = 1;
DataMessage data_message = 2;
SystemMessage system_message = 3;
PongMessage pong_message = 4;
StreamAckMessage stream_ack_message = 6;
StreamNackMessage stream_nack_message = 7;
StreamClosedMessage stream_closed_message = 8;
}
message AckMessage {
uint64 ack_id = 1;
bool success = 2;
optional ErrorMessage error = 3;
message ErrorMessage {
string name = 1;
string message = 2;
}
}
message DataMessage {
string from = 1;
optional string group = 2;
MessageData data = 3;
StreamInfo stream = 6;
}
message SystemMessage {
oneof message {
ConnectedMessage connected_message = 1;
DisconnectedMessage disconnected_message = 2;
}
message ConnectedMessage {
string connection_id = 1;
string user_id = 2;
}
message DisconnectedMessage {
string reason = 2;
}
}
message PongMessage {
}
message StreamAckMessage {
string stream_id = 1;
uint64 expected_sequence_id = 2;
}
message StreamNackMessage {
string stream_id = 1;
string name = 2;
string message = 3;
uint64 expected_sequence_id = 4;
}
message StreamClosedMessage {
string stream_id = 1;
optional StreamClosedError error = 2;
message StreamClosedError {
string name = 1;
string message = 2;
}
}
}
message StreamInfo {
string stream_id = 1;
uint64 stream_sequence_id = 2;
optional bool end_of_stream = 3;
optional StreamError error = 4;
message StreamError {
string name = 1;
string message = 2;
string user_error_code = 3;
}
}
As mensagens recebidas pelo cliente podem ser ack, message, system, pong, streamAck, streamNack, ou streamClosed.
Resposta Ack
Se a solicitação contiver ackId, o serviço retornará uma resposta ack para essa solicitação. A implementação do cliente deve lidar com esse mecanismo, incluindo:
- Aguardando a resposta ack para uma
asyncawaitoperação. - Ter uma verificação de tempo limite quando a resposta ack não é recebida durante um determinado período.
A implementação do cliente deve sempre verificar primeiro se o success status é true ou false. Quando o success status é false, o cliente pode ler a error partir da propriedade para obter detalhes do erro.
Resposta à mensagem
Os clientes podem receber mensagens publicadas de um grupo ao qual o cliente aderiu. Ou eles podem receber mensagens da função de gerenciamento de servidor quando o servidor envia mensagens para um cliente específico ou um usuário específico.
Você sempre receberá uma DownstreamMessage.DataMessage mensagem nos seguintes cenários:
- Quando a mensagem é de um grupo,
fromégroup. Quando a mensagem é do servidor,froméserver. - Quando a mensagem é de um grupo,
groupé o nome do grupo.
O remetente dataType fará com que uma das seguintes mensagens seja enviada:
- Se
dataTypefortext, usemessage_response_message.data.text_data. - Se
dataTypeforbinary, usemessage_response_message.data.binary_data. - Se
dataTypeforprotobuf, usemessage_response_message.data.protobuf_data. - Se
dataTypeforjson, usemessage_response_message.data.text_data, e o conteúdo for uma cadeia de caracteres JSON serializada.
Quando uma mensagem de grupo pertence a um fluxo, DownstreamMessage.DataMessage.stream é definido.
-
stream.stream_idé o identificador lógico do fluxo. -
stream.stream_sequence_idé o número de sequência da mensagem no fluxo. -
stream.end_of_streamé opcional. Quando definido paratrue, a mensagem é a mensagem terminal do fluxo. -
stream.erroré opcional e está presente apenas quando o fluxo termina com um erro.user_error_codeestá presente apenas paraUserError.
Resposta ao fluxo de água
O serviço envia DownstreamMessage.StreamAckMessage para confirmar dados de fluxo aceites e para reportar o ID de sequência seguinte que espera.
-
stream_idé o identificador lógico do fluxo. -
expected_sequence_idé o próximo ID de sequência de fluxo que o serviço espera.
Resposta do nack do ribeiro
O serviço envia DownstreamMessage.StreamNackMessage um erro de fluxo retentável.
-
stream_idé o identificador lógico do fluxo. -
expected_sequence_idé o próximo ID de sequência de fluxo que o serviço espera. -
namepode serInvalidSequenceIdouTransientError. -
messagecontém detalhes do erro.
Resposta de fluxo fechado
O serviço envia DownstreamMessage.StreamClosedMessage quando o fluxo do lado da editora está encerrado.
-
stream_idé o identificador lógico do fluxo. -
erroré omitido quando o fluxo está normalmente fechado. -
error.namepode serStreamNotFound,Forbidden,BadRequest,InternalServerError, ouIdleTimeout. -
error.messagecontém detalhes do erro.
Resposta do sistema
O serviço Web PubSub também pode enviar respostas relacionadas ao sistema para o cliente.
Ligado
Quando o cliente se conecta ao serviço, você recebe uma DownstreamMessage.SystemMessage.ConnectedMessage mensagem.
Desligado
Quando o servidor fecha a conexão ou o serviço recusa o cliente, você recebe uma DownstreamMessage.SystemMessage.DisconnectedMessage mensagem.
Resposta Pong
O serviço Web PubSub envia um PongMessage para o cliente quando ele recebe um PingMessage do cliente.
Próximos passos
Use estes recursos para começar a criar seu próprio aplicativo: