dotnet服务通信协议选择技能 dotnet-service-communication

这个技能提供.NET环境中服务通信协议的全面决策支持,帮助开发者选择REST、gRPC、SignalR、SSE或JSON-RPC 2.0。通过决策矩阵、流程图和最佳实践,优化系统架构、提升性能和兼容性。关键词:.NET, 服务通信, 协议选择, gRPC, SignalR, SSE, JSON-RPC, REST, 决策矩阵, 架构设计

架构设计 0 次安装 0 次浏览 更新于 3/6/2026

名称: dotnet-service-communication 描述: “选择服务间协议。REST vs gRPC vs SignalR vs SSE 决策矩阵,权衡。” 用户可调用: false

dotnet-service-communication

高级路由技能,用于选择正确的服务通信协议。提供决策矩阵,将需求(延迟、方向、客户端类型、负载格式、浏览器支持)映射到五种主要的.NET通信协议:gRPC、SignalR、SSE、JSON-RPC 2.0 和 REST。路由到专门技能以获取实施深度。

范围

  • gRPC、SignalR、SSE、JSON-RPC、REST 的决策矩阵
  • 需求映射(延迟、方向、客户端类型、格式)
  • 路由到专门实施技能

超出范围

  • HTTP 客户端工厂和弹性管道 – 参见 [技能:dotnet-http-client] 和 [技能:dotnet-resilience]
  • 原生 AOT 架构和修剪 – 参见 [技能:dotnet-native-aot] 和 [技能:dotnet-trimming]

交叉引用: [技能:dotnet-grpc] 用于 gRPC 实施, [技能:dotnet-realtime-communication] 用于 SignalR/SSE/JSON-RPC 详情, [技能:dotnet-http-client] 用于 REST/HTTP 客户端模式。参见 [技能:dotnet-integration-testing] 用于测试服务通信模式。


决策矩阵

使用此矩阵根据您的需求选择正确的协议:

需求 gRPC SignalR SSE JSON-RPC 2.0 REST
方向 所有四种模式 全双工 服务器到客户端 请求-响应 请求-响应
传输格式 Protobuf(二进制) JSON 或 MessagePack 文本(JSON 行) JSON JSON/XML
浏览器支持 gRPC-Web(需要代理) 是(JS 客户端) 是(原生 EventSource) 通过 WebSocket 是(fetch/XHR)
契约 .proto 模式 Hub 接口 约定 JSON-RPC 规范 OpenAPI/Swagger
延迟 最低 中等 中等
吞吐量 最高 中等 中等 中等
流式传输 所有 4 种模式 服务器 + 客户端流式 仅服务器推送 否(分块传输)
连接 HTTP/2 持久 WebSocket(有回退) HTTP/1.1+ 持久 传输依赖 按请求
服务到服务 优秀 有限 小众
AOT 友好 是(Protobuf) 是(使用 STJ 源生成)

决策流程图

这是服务到服务(无浏览器)吗?
├── 是 → 您需要流式传输吗?
│   ├── 是 → gRPC 流式传输 [技能:dotnet-grpc]
│   └── 否 → 是请求-响应吗?
│       ├── 高吞吐量 / 二进制 → gRPC(单播) [技能:dotnet-grpc]
│       └── 标准 CRUD / 公共 API → REST [技能:dotnet-http-client]
└── 否(浏览器客户端) → 您需要实时吗?
    ├── 是 → 您需要双向吗?
    │   ├── 是 → SignalR [技能:dotnet-realtime-communication]
    │   └── 否(仅服务器推送) → SSE [技能:dotnet-realtime-communication]
    └── 否 → REST [技能:dotnet-http-client]

特殊情况:
- LSP / 工具协议 → JSON-RPC 2.0 [技能:dotnet-realtime-communication]
- 混合(浏览器 + 服务到服务) → 浏览器用 REST,内部用 gRPC

协议概况

gRPC

最适合: 服务到服务通信、高吞吐量流式传输、强类型契约。

  • 使用 .proto 文件进行模式优先开发
  • 所有四种流式模式:单播、服务器流式、客户端流式、双向
  • 二进制序列化(Protobuf)以获得最小负载和最快吞吐量
  • 内置客户端和服务器存根代码生成
  • 原生负载均衡和健康检查协议支持

何时不使用: 直接浏览器通信(需要 gRPC-Web 代理)、由外部客户端使用的简单 CRUD API、需要人类可读负载的场景。

参见 [技能:dotnet-grpc] 获取完整实施详情。

SignalR

最适合: 面向浏览器的实时应用程序、交互式仪表板、聊天、协作功能。

  • 自动传输协商(WebSocket → SSE → 长轮询)
  • 内置组管理和用户定位
  • Hub 抽象与强类型接口
  • 通过 Redis 背板或 Azure SignalR 服务扩展
  • 支持 JSON 和 MessagePack 序列化

何时不使用: 仅服务器到客户端推送(使用 SSE 代替)、服务到服务(使用 gRPC 代替)、无法包含 SignalR 客户端库的场景。

参见 [技能:dotnet-realtime-communication] 获取 SignalR 模式和 Hub 实施。

服务器发送事件(SSE)

最适合: 简单服务器到客户端推送通知、实时源、状态更新。

  • 在 .NET 10 中通过 TypedResults.ServerSentEvents 内置到 ASP.NET Core
  • 浏览器原生 EventSource API – 无需客户端库
  • 使用 Last-Event-ID 自动重新连接
  • 通过阻塞 WebSocket 升级的 HTTP/1.1 代理工作
  • 最轻量级的实时选项

何时不使用: 双向通信(使用 SignalR)、高吞吐量二进制流式传输(使用 gRPC)、需要客户端到服务器消息。

参见 [技能:dotnet-realtime-communication] 获取 SSE 实施详情。

JSON-RPC 2.0

最适合: 工具协议(语言服务器协议)、通过简单传输的结构化 RPC。

  • 传输无关(HTTP、WebSocket、stdio、命名管道)
  • 定义良好的请求/响应/通知语义
  • 由 Visual Studio、VS Code 和 .NET 工具通过 StreamJsonRpc 使用
  • 当不需要模式管理时,作为 gRPC 的轻量级替代品

何时不使用: 实时流式传输(使用 SignalR 或 gRPC)、高吞吐量服务到服务(使用 gRPC)、标准 Web API(使用 REST)。

参见 [技能:dotnet-realtime-communication] 获取 JSON-RPC 2.0 模式。

REST(HTTP API)

最适合: 公共 API、标准 CRUD 操作、广泛的客户端兼容性。

  • 通用客户端支持(任何 HTTP 客户端)
  • 人类可读负载(JSON)
  • 丰富的生态系统(OpenAPI、Swagger UI、API 版本控制)
  • 无状态请求-响应模型
  • ASP.NET Core Minimal API 或 MVC 控制器

何时不使用: 实时推送(使用 SSE 或 SignalR)、高吞吐量服务到服务(使用 gRPC)、双向流式传输(使用 SignalR 或 gRPC)。

参见 [技能:dotnet-http-client] 获取 HTTP 客户端模式、弹性和 IHttpClientFactory


常见架构模式

使用混合协议的 API 网关

浏览器 ─── REST/SignalR ──→ API 网关 ──→ gRPC ──→ 内部服务
                                          ──→ gRPC ──→ 订单服务
                                          ──→ gRPC ──→ 库存服务

公共面向的 API 使用 REST,实时浏览器功能使用 SignalR。内部服务到服务通信使用 gRPC 以提高性能。API 网关在协议之间转换。

事件驱动与 SSE

内部服务 ──→ 消息代理 ──→ SSE 端点 ──→ 浏览器仪表板
                                     ──→ gRPC 流 ──→ 监控服务

内部事件流经消息代理。浏览器仪表板通过 SSE 消费。其他服务通过 gRPC 流式传输消费以获得更高吞吐量。

双协议服务

单个 ASP.NET Core 主机可以同时服务 gRPC 和 REST:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGrpc();
builder.Services.AddControllers();

var app = builder.Build();

// gRPC 用于内部服务到服务
app.MapGrpcService<OrderGrpcService>();

// REST 用于外部客户端
app.MapControllers();

// SSE 用于实时浏览器更新
app.MapGet("/events/orders", (OrderEventService svc, CancellationToken ct) =>
    TypedResults.ServerSentEvents(svc.GetEventsAsync(ct)));

关键原则

  • 服务到服务使用 gRPC – 提供最佳吞吐量、强类型契约和所有流式模式
  • 公共 API 使用 REST – 通用客户端支持、人类可读、广泛的工具生态系统
  • 浏览器实时使用 SignalR – 自动传输协商和内置组管理
  • 简单服务器推送使用 SSE – 当不需要双向通信时的轻量级选项
  • 适当混合协议 – 单个 ASP.NET Core 主机可以同时服务 gRPC、REST、SignalR 和 SSE
  • 基于客户端类型路由 – 浏览器客户端获取 REST/SignalR/SSE;内部服务获取 gRPC

参见 [技能:dotnet-native-aot] 获取 AOT 编译管道和 [技能:dotnet-aot-architecture] 获取 AOT 兼容通信模式。


代理注意事项

  1. 不要默认将 gRPC 用于面向浏览器的 API – 浏览器无法本地处理 HTTP/2 尾部。使用 gRPC-Web 和代理或选择 REST/SignalR/SSE。
  2. 不要将 SignalR 用于服务到服务 – gRPC 为后端通信提供更好的性能、代码生成和流式传输。
  3. 当 SSE 足够时不要添加 SignalR – 如果仅需要服务器到客户端推送,SSE 更简单,无需客户端库,并且浏览器有自动重新连接。
  4. 不要将 REST 用于高吞吐量内部通信 – JSON 文本序列化和按请求连接相比 gRPC 的二进制格式和持久 HTTP/2 连接增加开销。
  5. 不要忘记 AOT 考虑 – 使用 System.Text.Json 的 REST 端点需要源生成上下文用于 AOT。参见 [技能:dotnet-serialization] 获取详情。
  6. 不要将 gRPC 服务暴露给不受信任的客户端而不使用 gRPC-Web – 原始 gRPC 需要 HTTP/2,这在所有环境中并非普遍可用(例如,某些代理、旧浏览器)。

参考文献