NetCore+Web客户端实现gRPC实时推送
📅 2026/7/26 1:19:03
👁️ 阅读次数
📝 编程学习
NetCore+Web客户端实现gRPC实时推送
引言在现代Web应用中,实时推送是一个常见需求,比如股票行情、聊天消息、系统通知等。传统的HTTP轮询方式效率低下且延迟高,而WebSocket虽然解决了部分问题,但在微服务架构中,gRPC凭借其高性能、强类型和双向流特性,成为实时推送的理想选择。本文将带你从零开始,使用.NET Core(NetCore)作为服务端,结合gRPC实现实时推送,并在Web客户端(JavaScript)中接收推送数据。我们将通过两个完整的代码示例来演示整个过程。## 技术栈与环境准备-服务端: .NET 8 (NetCore)-客户端: 纯HTML + JavaScript (使用gRPC-Web)-通信协议: gRPC + Protobuf-工具: Visual Studio 2022, Node.js (用于测试)在开始之前,确保已安装:- .NET SDK 8.0± Node.js 18+## 1. 创建gRPC服务端项目首先,我们创建一个gRPC服务端项目,用于定义服务和推送逻辑。### 1.1 定义Protobuf协议创建一个名为ChatService的gRPC服务,支持双向流推送。protobuf// chat.protosyntax = "proto3";package chat;// 聊天服务定义service ChatService { // 双向流:客户端发送消息,服务端返回实时通知 rpc ChatStream (stream ChatMessage) returns (stream Notification);}// 客户端发送的消息结构message ChatMessage { string user = 1; // 用户名 string content = 2; // 消息内容 int64 timestamp = 3; // 时间戳(毫秒)}// 服务端推送的通知结构message Notification { string type = 1; // 通知类型:new_message, system string payload = 2; // 通知内容(JSON格式) int64 timestamp = 3; // 时间戳}### 1.2 实现服务端逻辑在.NET Core中实现ChatService,并添加实时推送功能。csharp// Services/ChatService.csusing Grpc.Core;using ChatGrpc; // 自动生成的代码namespace GrpcServer.Services;public class ChatServiceImpl : ChatService.ChatServiceBase{ private static readonly List<IServerStreamWriter<Notification>> _clients = new(); private static readonly object _lock = new(); // 处理双向流:接收客户端消息并广播通知 public override async Task ChatStream( IAsyncStreamReader<ChatMessage> requestStream, IServerStreamWriter<Notification> responseStream, ServerCallContext context) { // 将当前客户端加入广播列表 lock (_lock) { _clients.Add(responseStream); } try { // 持续读取客户端发送的消息 await foreach (var message in requestStream.ReadAllAsync()) { // 构造通知对象 var notification = new Notification { Type = "new_message", Payload = $"{{\"user\":\"{message.User}\",\"content\":\"{message.Content}\",\"timestamp\":{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}}}", Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }; // 广播给所有客户端(包括自己) lock (_lock) { foreach (var client in _clients) { // 异步发送,不等待 _ = client.WriteAsync(notification); } } Console.WriteLine($"收到消息: {message.User} - {message.Content}"); } } catch (Exception ex) { Console.WriteLine($"客户端断开连接: {ex.Message}"); } finally { // 移除断开的客户端 lock (_lock) { _clients.Remove(responseStream); } } }}### 1.3 配置服务端启动在Program.cs中配置gRPC服务,并启用gRPC-Web支持(用于浏览器客户端)。csharp// Program.csusing GrpcServer.Services;var builder = WebApplication.CreateBuilder(args);// 添加gRPC服务builder.Services.AddGrpc();// 添加gRPC-Web支持(必须)builder.Services.AddGrpcWeb(o => o.GrpcWebEnabled = true);var app = builder.Build();// 启用gRPC-Web中间件app.UseGrpcWeb();// 映射gRPC服务app.MapGrpcService<ChatServiceImpl>().EnableGrpcWeb();// 添加静态文件支持(用于提供HTML客户端)app.UseDefaultFiles();app.UseStaticFiles();app.Run();## 2. 创建Web客户端Web客户端使用JavaScript通过gRPC-Web协议与服务端通信。这里我们使用@grpc/grpc-js和@grpc/proto-loader库(需要Node.js环境打包,或直接在浏览器中使用CDN)。### 2.1 安装依赖bash# 初始化项目npm init -y# 安装gRPC-Web客户端库npm install @grpc/grpc-js @grpc/proto-loader### 2.2 编写HTML客户端创建一个简单的HTML页面,实现消息发送和实时接收。html<!-- wwwroot/index.html --><!DOCTYPE html><html lang="zh-CN"><head> <meta charset="UTF-8"> <title>gRPC实时推送演示</title> <style> #messages { height: 400px; overflow-y: scroll; border: 1px solid #ddd; padding: 10px; } .message { margin-bottom: 10px; } .user { font-weight: bold; color: #007bff; } .time { color: #666; font-size: 0.8em; } </style></head><body> <h1>gRPC实时聊天</h1> <div id="messages"></div> <div> <input type="text" id="userInput" placeholder="用户名" value="User" /> <input type="text" id="messageInput" placeholder="输入消息..." /> <button onclick="sendMessage()">发送</button> </div> <!-- 引入gRPC-Web库 --> <script src="https://unpkg.com/@@grpc/grpc-js@@1.10.0/build/grpc.js"></script> <script src="https://unpkg.com/@@grpc/proto-loader@@0.7.10/build/index.js"></script> <script> // 定义gRPC连接 const host = 'http://localhost:5000'; // 服务端地址 const protoFile = 'chat.proto'; // 需要服务端提供proto文件 // 加载proto定义 const packageDefinition = grpc.loadSync(protoFile, { keepCase: true, longs: String, enums: String, defaults: true, oneofs: true }); const proto = grpc.loadPackageDefinition(packageDefinition).chat; // 创建客户端 const client = new proto.ChatService(host, grpc.credentials.createInsecure()); // 建立双向流连接 const call = client.chatStream(); // 接收服务端推送的通知 call.on('data', function(notification) { const payload = JSON.parse(notification.payload); const messagesDiv = document.getElementById('messages'); const msgElement = document.createElement('div'); msgElement.className = 'message'; msgElement.innerHTML = ` <span class="user">${payload.user}</span> <span class="time">${new Date(payload.timestamp).toLocaleTimeString()}</span> <div>${payload.content}</div> `; messagesDiv.appendChild(msgElement); messagesDiv.scrollTop = messagesDiv.scrollHeight; }); // 处理错误和关闭事件 call.on('error', function(err) { console.error('gRPC错误:', err); }); call.on('end', function() { console.log('连接关闭'); }); // 发送消息函数 function sendMessage() { const user = document.getElementById('userInput').value || '匿名'; const content = document.getElementById('messageInput').value; if (!content) return; const message = { user: user, content: content, timestamp: Date.now() }; // 通过gRPC流发送消息 call.write(message); document.getElementById('messageInput').value = ''; } // 按回车键发送 document.getElementById('messageInput').addEventListener('keypress', function(e) { if (e.key === 'Enter') { sendMessage(); } }); </script></body></html>## 3. 运行与测试### 3.1 启动服务端在服务端项目目录下执行:bashcd GrpcServerdotnet run服务端将在http://localhost:5000启动。### 3.2 访问Web客户端在浏览器中打开http://localhost:5000,你会看到聊天界面。打开两个浏览器窗口分别输入不同用户名,发送消息后,所有窗口都会实时收到推送。### 3.3 测试效果- 在窗口1输入用户A和消息Hello,gRPC!- 在窗口2输入用户B和消息收到!- 两个窗口会立即显示对方发送的消息,延迟通常在毫秒级。## 4. 关键点解析### 4.1 gRPC-Web的作用浏览器原生不支持HTTP/2和gRPC的二进制传输,因此需要使用gRPC-Web协议进行适配。服务端通过EnableGrpcWeb()中间件将gRPC转换为gRPC-Web格式,使得浏览器可以正常通信。### 4.2 双向流推送的优势-低延迟: 服务端可以立即推送数据,无需客户端轮询。-节省带宽: 只在有数据时传输,避免了HTTP长连接的头部开销。-强类型: 通过Protobuf定义数据结构,减少解析错误。### 4.3 生产环境注意事项- 使用gRPC.Web库(如Grpc.Net.Client.Web)替代手动加载proto。- 添加认证和授权机制(如JWT)。- 使用连接池管理大量客户端连接。- 考虑使用Redis或Kafka实现服务间推送广播。## 总结本文通过一个完整的聊天示例,演示了如何使用.NET Core(NetCore)实现gRPC服务端,并通过Web客户端(JavaScript)接收实时推送。我们涵盖了从Protobuf定义、服务端实现、客户端集成到实际运行测试的全过程。gRPC的实时推送能力不仅适用于聊天场景,还可以扩展到物联网数据上报、金融行情推送、多人协作编辑等需要低延迟、高吞吐的领域。结合.NET Core的高性能和跨平台特性,这一方案在微服务架构中具有极高的实用价值。希望这篇文章能帮助你快速上手gRPC实时推送技术,并在实际项目中灵活运用。如果有任何问题,欢迎在评论区交流讨论!
编程学习
技术分享
实战经验