关于 dotnet-service-communication
面向 .NET 开发者的服务通信选型技能,根据延迟、通信方向、客户端类型和载荷格式等需求比较五种协议,并指向具体实现技能。
主要功能
- 01五种协议的决策矩阵
- 02按需求比较协议特性
- 03涵盖 gRPC、SignalR、SSE、JSON-RPC 2.0 和 REST
- 04链接到专项实现技能
适用场景
- 01为浏览器服务选择协议
- 02为内部服务选择通信方式
- 03规划组合多种协议的 API
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ wshaddix/ dotnet-skills --skill dotnet-service-communication安装后在 Claude Code 中输入/dotnet-service-communication确认已加载。
详细介绍
dotnet-service-communication
用于选择合适服务通信协议的高阶路由技能。提供决策矩阵,根据需求(延迟、方向、客户端类型、载荷格式、浏览器支持)映射到 5 种主要的 .NET 通信协议:gRPC、SignalR、SSE、JSON-RPC 2.0 和 REST。引导用户前往专门技能,了解实现细节。
不在范围内: HTTP 客户端工厂模式和弹性管道——请参阅 [skill:dotnet-http-client] 和 [skill:dotnet-resilience]。Native AOT 架构和裁剪策略——AOT 编译请参阅 [skill:dotnet-native-aot],AOT 优先设计模式请参阅 [skill:dotnet-aot-architecture],安全裁剪开发请参阅 [skill:dotnet-trimming]。
交叉参考:[skill:dotnet-grpc] 介绍 gRPC 实现,[skill:dotnet-realtime-communication] 介绍 SignalR/SSE/JSON-RPC 详情,[skill:dotnet-http-client] 介绍 REST/HTTP 客户端模式。服务通信模式的测试请参阅 [skill:dotnet-integration-testing]。
决策矩阵
根据需求使用此矩阵选择合适的协议:
| 需求 | gRPC | SignalR | SSE | JSON-RPC 2.0 | REST |
|---|---|---|---|---|---|
| 方向 | 全部 4 种模式 | 全双工 | 服务端到客户端 | 请求-响应 | 请求-响应 |
| 线路格式 | 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 源生成) |
决策流程图
Is this service-to-service (no browser)?
├── Yes → Do you need streaming?
│ ├── Yes → gRPC streaming [skill:dotnet-grpc]
│ └── No → Is it request-response?
│ ├── High throughput / binary → gRPC (unary) [skill:dotnet-grpc]
│ └── Standard CRUD / public API → REST [skill:dotnet-http-client]
└── No (browser client) → Do you need real-time?
├── Yes → Do you need bidirectional?
│ ├── Yes → SignalR [skill:dotnet-realtime-communication]
│ └── No (server push only) → SSE [skill:dotnet-realtime-communication]
└── No → REST [skill:dotnet-http-client]
Special cases:
- LSP / tooling protocol → JSON-RPC 2.0 [skill:dotnet-realtime-communication]
- Mixed (browser + service-to-service) → REST for browser, gRPC for internal
协议概览
gRPC
最适合: 服务间通信、高吞吐量流式传输、强类型契约。
- 使用
.proto文件进行架构优先开发 - 支持全部 4 种流式传输模式:一元、服务端流式传输、客户端流式传输、双向流式传输
- 使用二进制序列化(Protobuf),实现更小的载荷和更高的吞吐量
- 内置客户端和服务端存根代码生成
- 原生支持负载均衡和健康检查协议
不适用场景: 直接与浏览器通信(需要 gRPC-Web 代理)、由外部客户端调用的简单 CRUD API、需要人类可读载荷的场景。
完整实现详情请参阅 [skill:dotnet-grpc]。
SignalR
最适合: 面向浏览器的实时应用、交互式仪表板、聊天和协作功能。
- 自动协商传输方式(WebSocket → SSE → Long Polling)
- 内置组管理和用户定向功能
- 使用强类型接口的 Hub 抽象
- 可通过 Redis backplane 或 Azure SignalR Service 扩展
- 支持 JSON 和 MessagePack 序列化
不适用场景: 仅需服务端到客户端推送(改用 SSE)、服务间通信(改用 gRPC)、无法引入 SignalR 客户端库的场景。
SignalR 模式和 Hub 实现请参阅 [skill:dotnet-realtime-communication]。
Server-Sent Events(SSE)
最适合: 简单的服务器到客户端推送通知、实时信息流、状态更新。
- 通过
TypedResults.ServerSentEvents内置于 .NET 10 的 ASP.NET Core 中 - 浏览器原生
EventSourceAPI——无需客户端库 - 使用
Last-Event-ID自动重新连接 - 可通过会阻止 WebSocket 升级的 HTTP/1.1 代理
- 开销最低的实时通信选项
不适用的情况: 需要双向通信时(使用 SignalR)、需要高吞吐量二进制流时(使用 gRPC)、需要客户端到服务器的消息时。
有关 SSE 实现细节,请参阅 [skill:dotnet-realtime-communication]。
JSON-RPC 2.0
最适合: 工具协议(语言服务器协议)、通过简单传输方式实现结构化 RPC。
- 与传输方式无关(HTTP、WebSocket、stdio、命名管道)
- 请求、响应和通知语义定义明确
- Visual Studio、VS Code 和 .NET 工具通过 StreamJsonRpc 使用
- 不需要管理架构时,可作为 gRPC 的轻量级替代方案
不适用的情况: 实时流传输(使用 SignalR 或 gRPC)、高吞吐量的服务间通信(使用 gRPC)、标准 Web API(使用 REST)。
有关 JSON-RPC 2.0 模式,请参阅 [skill:dotnet-realtime-communication]。
REST(HTTP API)
最适合: 公共 API、标准 CRUD 操作、广泛的客户端兼容性。
- 客户端支持广泛(任何 HTTP 客户端)
- 负载易于阅读(JSON)
- 生态系统完善(OpenAPI、Swagger UI、API 版本控制)
- 无状态请求-响应模型
- ASP.NET Core Minimal API 或 MVC 控制器
不适用的情况: 实时推送(使用 SSE 或 SignalR)、高吞吐量的服务间通信(使用 gRPC)、双向流传输(使用 SignalR 或 gRPC)。
有关 HTTP 客户端模式、弹性处理和 IHttpClientFactory,请参阅 [skill:dotnet-http-client]。
常见架构模式
混合协议的 API 网关
Browser ─── REST/SignalR ──→ API Gateway ──→ gRPC ──→ Internal Services
──→ gRPC ──→ Order Service
──→ gRPC ──→ Inventory Service
面向公共 API 使用 REST,实时浏览器功能使用 SignalR。内部服务间通信使用 gRPC,以获得更高性能。API 网关负责在不同协议之间进行转换。
使用 SSE 的事件驱动架构
Internal Services ──→ Message Broker ──→ SSE Endpoint ──→ Browser Dashboard
──→ gRPC Stream ──→ Monitoring Service
内部事件通过消息代理流转。浏览器仪表板通过 SSE 接收事件。其他服务通过 gRPC 流传输接收事件,以获得更高吞吐量。
双协议服务
单个 ASP.NET Core 主机可以同时提供 gRPC 和 REST:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
builder.Services.AddControllers();
var app = builder.Build();
// gRPC for internal service-to-service
app.MapGrpcService<OrderGrpcService>();
// REST for external clients
app.MapControllers();
// SSE for real-time browser updates
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
有关 AOT 编译流程,请参阅 [skill:dotnet-native-aot];有关兼容 AOT 的通信模式,请参阅 [skill:dotnet-aot-architecture]。
Agent 注意事项
- 不要默认在面向浏览器的 API 中使用 gRPC——浏览器原生不支持 HTTP/2 trailers。请使用带代理的 gRPC-Web,或选择 REST/SignalR/SSE。
- 不要在服务间通信中使用 SignalR——对于后端通信,gRPC 的性能更好,并支持代码生成和流式传输。
- SSE 足够时不要添加 SignalR——如果只需要服务端向客户端推送,SSE 更简单,无需客户端库,并且浏览器内置自动重连功能。
- 不要在高吞吐量的内部通信中使用 REST——与 gRPC 的二进制格式和持久化 HTTP/2 连接相比,JSON 文本序列化和每次请求单独建立连接会增加开销。
- 不要忽略 AOT 注意事项——使用 System.Text.Json 的 REST 端点需要源生成的上下文才能支持 AOT。详情请参阅 [skill:dotnet-serialization]。
- 不要在未使用 gRPC-Web 的情况下向不受信任的客户端公开 gRPC 服务——原始 gRPC 需要 HTTP/2,而并非所有环境(例如某些代理和较旧的浏览器)都能普遍支持 HTTP/2。