基于 .NET 8.0 gRPC通讯架构设计讲解,客户端+服务端

news/2025/2/8 20:46:52/

目录

1.简要说明

2.服务端设计

2.1 服务端创建

2.2 服务端设计

2.3 服务端业务模块

3.客户端设计-控制台

4.客户端设计-Avalonia桌面程序

5.客户端设计-MAUI安卓端程序


1.简要说明

gRPC 一开始由 google 开发,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统

项目下载地址:https://download.csdn.net/download/rotion135/90342675

整体架构设计图

解决方案预览

2.服务端设计

2.1 服务端创建

新建项目,搜索grpc 选择下图中的项目,创建;

框架最低版本支持.NET 8.0

2.2 服务端设计

先说下几个重要的文件:

launchSettings.json  部署路径等先关信息的配置文件

appsettings.json   项目设置相关配置文件

手动添加:

      "Microsoft.AspNetCore.Hosting": "Information","Microsoft.AspNetCore.Routing.EndpointMiddleware": "Information",

greet.proto  通讯交互的模型设计,以及命名空间

收发消息的接口定义等,添加完成后记得保存,重新生成一下

服务类定义,还有收发消息方法重写

寻找对应的服务以及调用的方法,用的反射的机制

参数传过来 ServerName 方法Method  以及入参 Args

从容器中寻找服务,获取到实例后,调用Method,最后返回结果

  public class GreeterService : Greeter.GreeterBase{private readonly ILogger<GreeterService> _logger;public GreeterService(ILogger<GreeterService> logger){_logger = logger;}public override Task<MessageResult> SendMessage(LSRequest request, ServerCallContext context){return GetResponse(request);}private async Task<MessageResult> GetResponse(LSRequest request){return await Task.Run(() =>{ResponseModel response = new ResponseModel();try{SendModel send = JsonConvert.DeserializeObject<SendModel>(request.Json);if (send == null){response.IsSuccess = false;response.Message = "Request cannot be null";}else{if (string.IsNullOrEmpty(send.ServerName) || string.IsNullOrEmpty(send.Method)){response.IsSuccess = false;response.Message = "ServerName or Method cannot be null";}else{response.RequestID = send.RequestID;// 根据服务名称,寻找对应的服务var service = BusinessModules.IocContainer.Get<IService>(send.ServerName);if (service != null){// 使用反射调用方法MethodInfo methodInfo = null;if (send.Args != null && send.Args.Length > 0){methodInfo = service.GetType().GetMethod(send.Method, send.Args.Select(arg => arg.GetType()).ToArray());}else{methodInfo = service.GetType().GetMethod(send.Method, types: new List<Type>().ToArray());}if (methodInfo != null){try{var res = methodInfo.Invoke(service, send.Args); // 执行方法response.IsSuccess = true;response.Content = JsonConvert.SerializeObject(res);}catch (Exception ex){LogOperate.Error("Method invocation failed", ex);response.IsSuccess = false;response.Message = ex.Message;}}else{response.IsSuccess = false;response.Message = "Method not found";}}else{response.IsSuccess = false;response.Message = "Server not found";}}}}catch (Exception ex){LogOperate.Error("GetResponse 发生异常", ex);response.IsSuccess = false;response.Message = ex.Message;}return new MessageResult(){Json = JsonConvert.SerializeObject(response)};});}}

在程序运行时,将服务注入

一些业务相关的服务启动,用的BusinessModules来管理,下面会介绍。

2.3 服务端业务模块

业务模块,用了我自己写的IOC容器来管理

定义服务,继承IService

业务模块启动:

     /// <summary>/// 模块启动/// </summary>public static void OnStart(){try {IEnumerable<Type> types = GetService();if (types != null && types.Count() > 0){foreach (Type type in types){string serviceName = type.Name;// 获取 ServiceNameAttribute 特性var attribute = type.GetCustomAttribute<ServiceNameAttribute>();if (attribute != null) {serviceName = attribute.Name;}//注册平台 基于IService的服务平台_iocBuilder.RegisterType(type,serviceName,LifeTimeType.Singleton);}}//创建容器IocContainer = _iocBuilder.Build();//获取所有注册的服务,基于IService的实现//然后调用服务的启动方法var services = IocContainer.GetAllService();foreach (var service in services){try{service.OnStart();}catch (Exception ex){LogOperate.Start($"启动容器中的服务发生异常,\r\n" + ex.ToString());}}}catch(Exception  ex){LogOperate.Error("BusinessModules-OnStart", ex);}}

业务模块结束:

     /// <summary>/// 模块结束/// </summary>public static void OnStop() {try{var services = IocContainer.GetAllService();foreach (var service in services){try{service.OnStop();}catch (Exception ex){LogOperate.Start($"停止容器中的服务发生异常,\r\n" + ex.ToString());}}}catch (Exception ex){LogOperate.Error("BusinessModules-OnStop", ex);}}

3.客户端设计-控制台

客户端设计可以多种方式,项目初始化时,需要Nuget引用下面三个包:

Google.Protobuf

Grpc.Net.Client

Grpc.Tools

添加 Protos 文件夹,添加文件greet.proto

除了命名空间修改为当前项目的之外,其余的与服务中的文件一致

运行时,创建链接,调用服务中的方法

using var channle = GrpcChannel.ForAddress("http://127.0.0.1:5237");var client = new Greeter.GreeterClient(channle);
SendModel send = new SendModel();
send.RequestID = Guid.NewGuid().ToString();
send.ServerName = "Device";
send.Method = "GetDeviceInfo";
//send.Args = new object[1];
//send.Args[0] = "1231";
var replay = await client.SendMessageAsync(new LSRequest() { Json = JsonConvert.SerializeObject(send) });
Console.WriteLine("Response:" + replay.Json);
Console.ReadKey();

4.客户端设计-Avalonia桌面程序

Avalonia 创建项目

同样需要添加三个包

同样需要添加 Protos 文件夹,添加文件greet.proto

除了命名空间修改为当前项目的之外,其余的与服务中的文件一致

客户端的设计我在这里就不多说了,可以看我的其他文章,或者下载源码来查看

这里边封装了一个gRPC的客户端类

    public class GRPC_Control{private string url;private Greeter.GreeterClient client;private GrpcChannel channle;public GRPC_Control(string _url){url = _url;}public BaseResult Connect(){//"http://localhost:5237"channle = GrpcChannel.ForAddress(url);client = new Greeter.GreeterClient(channle);return BaseResult.Successed;}public BaseResult SendMessage(string service, string method, object[] args = null){try{SendModel send = new SendModel();send.RequestID = Guid.NewGuid().ToString();send.ServerName = service;send.Method = method;send.Args = args;var replay = client.SendMessage(new LSRequest() { Json = JsonConvert.SerializeObject(send) });ResponseModel response = JsonConvert.DeserializeObject<ResponseModel>(replay.Json);if (response.IsSuccess){return JsonConvert.DeserializeObject<BaseResult>(response.Content);}else{return new BaseResult(false, response.Message);}}catch (Exception ex){LogOperate.Error("SendMessage", ex);return new BaseResult(false, ex.Message);}}public async Task<BaseResult> SendMessageAsync(string service, string method, object[] args = null){return await Task.Run(async () =>{try{SendModel send = new SendModel();send.RequestID = Guid.NewGuid().ToString();send.ServerName = service;send.Method = method;send.Args = args;var replay = await client.SendMessageAsync(new LSRequest() { Json = JsonConvert.SerializeObject(send) });ResponseModel response = JsonConvert.DeserializeObject<ResponseModel>(replay.Json);if (response.IsSuccess){return JsonConvert.DeserializeObject<BaseResult>(response.Content);}else{return new BaseResult(false, response.Message);}}catch (Exception ex){LogOperate.Error("SendMessageAsync", ex);return new BaseResult(false, ex.Message);}});}}

调用方式:

 case "Connect":if (gRPC == null){gRPC = new GRPC_Control(Url);gRPC.Connect();}VM_MainWindow.Instance.Popup("连接成功");break;case "Send":if (gRPC != null){var res= gRPC.SendMessage(Service, Method);Respone=JsonConvert.SerializeObject(res);}break;

5.客户端设计-MAUI安卓端程序

创建MAUI 项目,MAUI具体的使用可以参考官方文档,这里边就不展开说了

同样也是需要引用三个包

同样需要添加 Protos 文件夹,添加文件greet.proto

除了命名空间修改为当前项目的之外,其余的与服务中的文件一致

封装的gRPC客户端类与Avalonia的一致

如果对此架构感兴趣,欢迎下载源码参考参考,如有更好的建议,欢迎评论区提出


http://www.ppmy.cn/news/1570408.html

相关文章

用Python获取股票数据并实现未来收盘价的预测

获取数据 先用下面这段代码获取上证指数的历史数据&#xff0c;得到的csv文件数据&#xff0c;为后面训练模型用的 import akshare as ak import pandas as pd# 获取上证指数历史数据 df ak.stock_zh_index_daily(symbol"sh000001")# 将数据保存到本地CSV文件 df.…

前端知识自检

CSS lang 伪类 :lang 伪类使你有能力为不同的语言定义特殊的规则 <style> q:lang(no) {quotes: "~" "~"; } </style> </head><body> <p>Some text <q lang"no">A quote in a paragraph</q> Some te…

【Uniapp-Vue3】z-paging插件组件实现触底和下拉加载数据

一、下载z-paing插件 注意下载下载量最多的这个 进入Hbuilder以后点击“确定” 插件的官方文档地址&#xff1a; https://z-paging.zxlee.cn 二、z-paging插件的使用 在文档中向下滑动&#xff0c;会有使用方法。 使用z-paging标签将所有的内容包起来 配置标签中的属性 在s…

5-Scene层级关系

Fiber里有个scene是只读属性&#xff0c;能从fiber中获取它属于哪个场景&#xff0c;scene实体中又声明了fiber&#xff0c;fiber与scene是互相引用的关系。 scene层级关系 举例 在unity.core中的EntityHelper中&#xff0c;可以通过entity获取对应的scene root fiber等属性…

IOS开发日志-ios新建项目后-将storyboard去掉,版本调整为IOS13以下

目标IOS版本12&#xff0c;Xcode 16.2&#xff0c;记录ios新建项目后&#xff0c;如何将故事板storyboard和SceneDelegate 文件去掉&#xff0c;调整为代码开发。 创建后的项目中包含SceneDelegate&#xff0c;SceneDelegate 是 iOS 13 引入的类&#xff0c;用于管理应用程序的…

Idea 2024.3 使用CodeGPT插件整合Deepseek

哈喽&#xff0c;大家好&#xff0c;我是浮云&#xff0c;最近国产大模型Deepseek异常火爆&#xff0c;作为程序员我也试着玩了一下&#xff0c;首先作为简单的使用&#xff0c;大家进入官网&#xff0c;点击开始对话即可进行简单的聊天使用&#xff0c;点击获取手机app即可安装…

结合R语言、ArcGIS Pro、ChatGPT+生态学模型(PLUS模型、InVEST模型)的生态系统服务的多情景模拟预测及其应用

随着全球城市化进程的加速与人类活动的频繁&#xff0c;土地利用及生态系统服务面临巨大的压力&#xff0c;水土流失、植被退化、生物多样性丧失等环境问题日益严重。如何在土地供需矛盾中维持生态安全、优化土地利用模式&#xff0c;成为当前生态学与土地规划领域的研究重点。…

线性代数于工程应用中的实践:以代码实例拆解相似性度量问题的求解逻辑

相似性度量 目录 相似性度量 1.欧氏距离 2.余弦相似度 3.两者区别 4.应用实例 &#xff08;1&#xff09;评估用户消费能力&#xff08;欧式距离&#xff09; &#xff08;2&#xff09;人群聚类&#xff08;余弦相似度&#xff09; 1.欧氏距离 欧氏距离是一种常用的距离…