MessagePack | Custom Protocol | WebSocket | SignalR | CSharp
- Protocolo binário oficial para alta performance
O que muda ao usar MessagePack
| Aspecto | JSON | MessagePack |
|---|---|---|
| Formato | Texto | Binário |
| Tamanho | Maior | Menor |
| Performance | Média | Alta |
| Legibilidade | Alta | Nenhuma |
| Compatibilidade | Alta | Mais restrita |
👉 MessagePack reduz payload e CPU de serialização.
1. Pacotes necessários
Servidor:
dotnet add package Microsoft.AspNetCore.SignalR.Protocols.MessagePack
Cliente:
dotnet add package Microsoft.AspNetCore.SignalR.Client
dotnet add package Microsoft.AspNetCore.SignalR.Protocols.MessagePack
2. Configuração no servidor
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddSignalR()
.AddMessagePackProtocol(options =>
{
// opcional: customizações
});
var app = builder.Build();
app.MapHub<ComandoHub>("/hub/comandos");
app.Run();
3. Hub de exemplo
using Microsoft.AspNetCore.SignalR;
public sealed class ComandoHub : Hub
{
public async Task EnviarComando(string comando)
{
await Clients.Caller.SendAsync("ReceberComando", comando);
}
}
4. Cliente .NET com MessagePack
using Microsoft.AspNetCore.SignalR.Client;
var connection = new HubConnectionBuilder()
.WithUrl("https://localhost:5001/hub/comandos")
.AddMessagePackProtocol()
.Build();
connection.On<string>("ReceberComando", mensagem =>
{
Console.WriteLine($"Recebido: {mensagem}");
});
await connection.StartAsync();
await connection.InvokeAsync("EnviarComando", "SELECT * FROM PRODUTOS");
Console.ReadLine();
5. Usando DTOs (muito importante)
MessagePack funciona melhor com objetos estruturados.
DTO simples
public class ComandoDto
{
public string Sql { get; set; } = default!;
public Guid RequestId { get; set; }
}
Hub
public async Task EnviarComando(ComandoDto dto)
{
await Clients.Caller.SendAsync("ReceberComando", dto);
}
Cliente
connection.On<ComandoDto>("ReceberComando", dto =>
{
Console.WriteLine(dto.Sql);
});
6. Versão otimizada (recomendada)
Para máxima performance, use atributos do MessagePack:
dotnet add package MessagePack
DTO otimizado
using MessagePack;
[MessagePackObject]
public class ComandoDto
{
[Key(0)]
public string Sql { get; set; } = default!;
[Key(1)]
public Guid RequestId { get; set; }
}
Por que isso é melhor
- Evita reflection
- Serialização mais rápida
- Payload menor
- Controle total da ordem dos campos
7. Configuração avançada
builder.Services
.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.SerializerOptions = MessagePack.MessagePackSerializerOptions.Standard
.WithCompression(MessagePack.MessagePackCompression.Lz4BlockArray);
});
8. Problemas comuns (importante)
❌ Problema 1 — Case sensitivity
public string Nome { get; set; }
Se o cliente tiver:
public string nome { get; set; }
👉 Vai falhar (diferente do JSON)
❌ Problema 2 — Versionamento
[Key(0)] string Sql
[Key(1)] Guid RequestId
Se você mudar ordem ou remover:
👉 Quebra compatibilidade
✔ Regra
- Nunca mudar os
Key - Apenas adicionar novos com índices novos
❌ Problema 3 — Tipos não suportados
Alguns tipos complexos exigem resolver manualmente:
- interfaces
- tipos abstratos
- objetos dinâmicos
9. Comparação prática
Payload JSON:
{
"sql": "SELECT *",
"requestId": "guid"
}
Payload MessagePack:
(binary compactado, ~40-60% menor)
10. Quando usar (seu caso)
Pelo seu cenário (SignalR + alto volume + muitos clientes):
👉 Use MessagePack quando:
- 1000+ conexões
- payload frequente
- baixa latência é importante
- tráfego alto
👉 NÃO use quando:
- precisa debugar tráfego facilmente
- integra com clientes não .NET
- precisa de flexibilidade extrema
Regra final
- JSON → simplicidade
- MessagePack → performance
- Custom Protocol → raríssimo