自己动手,写一个分布式系统(附c#代码示例)
2018-09-24 19:34
896 查看
分布式系统有很多成熟的解决方案。如:微软的WCF。WCF太过于复杂,配置也麻烦。其实可以自己动手设计一个小的分布式系统。系统的原理完全在自己掌握之中,可以根据业务随机而变。这里展示远程调用最核心最基本的处理逻辑,其实远程调用并不复杂神秘。
分布式系统其实是数据流的交换。数据必须快速的从一段传送到另一端,否则系统性能就大打折扣。对于.net,本人设计一个非常优化易于使用的网络库(EasyNetMessage)。使用该库,不需要关心底层细节,所有处理对象是string、byte;发送时,不需要处理分包(几十M的数据也可以一次发送);收包时,不需要处理粘包。本文所示例代码,就是基于该网络库。本文章实例代码见底部。
实现目标
实现一个非常简单的应用 internal int AddCall(int value1, int value2);就是两个整数相加。调用过程和本地完全一样,只是执行加法操作是在远程服务器实现的。操作非常简单,但是揭示了远程调用的核心处理流程。
处理过程:
a) 数据发送
每次函数调用必须有一个唯一标识CallId,这个也是发包的唯一标识;服务端处理完后,返回的结果也带有此标识。通过此标识,将发送端数据和返回数据关联起来了。
发送完数据后,客户端线程要挂起,等待服务器端的处理结果。线程挂起使用ManualResetEvent。并建立起CallId与ManualResetEvent的对应关系。当数据返回时,就能找到对应的ManualResetEvent。
b)数据返回
数据返回后的处理是在另一个线程。数据返回后,先根据CallId查找对应的ManualResetEvent;如果找不到,有可能服务器处理太慢,超时了。
先将返回结果存储到哈希数组中,key为CallId。再调用ManualResetEvent的Set函数,唤醒调用端线程。调用端线程根据CallId到哈希表中获取结果。
进一步说明:可以在此基础上,进一步扩展。开发出类似Redis的内存库。客户端的调用也不一定是同步 ,可以采用异步回调的方式处理。其实如果知道处理的原理,可以根据自己的业务做裁剪。只有知其所以然,才能开发出最符合自己业务的系统,才可能进一步优化。
实例代码 https://download.csdn.net/download/qq_29939347/10684858 (代码已上传,但是需要审核,最近可能无法下载)
分布式系统其实是数据流的交换。数据必须快速的从一段传送到另一端,否则系统性能就大打折扣。对于.net,本人设计一个非常优化易于使用的网络库(EasyNetMessage)。使用该库,不需要关心底层细节,所有处理对象是string、byte;发送时,不需要处理分包(几十M的数据也可以一次发送);收包时,不需要处理粘包。本文所示例代码,就是基于该网络库。本文章实例代码见底部。
实现目标
实现一个非常简单的应用 internal int AddCall(int value1, int value2);就是两个整数相加。调用过程和本地完全一样,只是执行加法操作是在远程服务器实现的。操作非常简单,但是揭示了远程调用的核心处理流程。
处理过程:
a) 数据发送
每次函数调用必须有一个唯一标识CallId,这个也是发包的唯一标识;服务端处理完后,返回的结果也带有此标识。通过此标识,将发送端数据和返回数据关联起来了。
发送完数据后,客户端线程要挂起,等待服务器端的处理结果。线程挂起使用ManualResetEvent。并建立起CallId与ManualResetEvent的对应关系。当数据返回时,就能找到对应的ManualResetEvent。
//callid与事件关联 Dictionary<int, ManualResetEvent> _callEventGroup = new Dictionary<int, ManualResetEvent>(); //callId与返回结果关联 Dictionary<int, NetCallAddAck> _callResultGroup = new Dictionary<int, NetCallAddAck>(); internal int AddCall(int value1, int value2) { //组织发送包 NetCallAdd add = new NetCallAdd(); add.Value1 = value1.ToString(); add.Value2 = value2.ToString(); MonitorClient client = GetCurAppClient(); if (client == null) throw new Exception("socket未连接!"); //生成线程事件,并与CallId关联 ManualResetEvent callEvent = new ManualResetEvent(false); lock (_callEventGroup) { _callEventGroup.Add(add.CallId, callEvent); } //发送数据 EN_SendDataResult result = _netServer.SendData(client.ClientSocket, add.ToEasyMessage().ToNetPacket()); if (result != EN_SendDataResult.ok) { lock (_callEventGroup) { _callEventGroup.Remove(add.CallId); } throw new Exception("网络发送异常!"); } //等待结果 callEvent.WaitOne(3000); _callEventGroup.Remove(add.CallId); //查看结果集 lock (_callResultGroup) { if (_callResultGroup.ContainsKey(add.CallId)) { NetCallAddAck ack = _callResultGroup[add.CallId]; return int.Parse(ack.Result); } } throw new Exception("没有返回结果!"); }
b)数据返回
数据返回后的处理是在另一个线程。数据返回后,先根据CallId查找对应的ManualResetEvent;如果找不到,有可能服务器处理太慢,超时了。
先将返回结果存储到哈希数组中,key为CallId。再调用ManualResetEvent的Set函数,唤醒调用端线程。调用端线程根据CallId到哈希表中获取结果。
internal void OnRcvAck(NetCallAddAck addAck) { //根据callid找到事件 ManualResetEvent callEvent = null; lock (_callEventGroup) { if (!_callEventGroup.ContainsKey(addAck.CallId)) return; callEvent =_callEventGroup[addAck.CallId]; } //结果存放到哈希表中 lock (_callResultGroup) { _callResultGroup.Remove(addAck.CallId); _callResultGroup.Add(addAck.CallId, addAck); } //设置事件为有信号,调用方挂起的线程可以继续执行 callEvent.Set(); }
进一步说明:可以在此基础上,进一步扩展。开发出类似Redis的内存库。客户端的调用也不一定是同步 ,可以采用异步回调的方式处理。其实如果知道处理的原理,可以根据自己的业务做裁剪。只有知其所以然,才能开发出最符合自己业务的系统,才可能进一步优化。
实例代码 https://download.csdn.net/download/qq_29939347/10684858 (代码已上传,但是需要审核,最近可能无法下载)
相关文章推荐
- 为自己的C# ORM 写一个代码自动生成器
- 自己动手安装一个纯净的Window7系统全过程分享
- 新灵感站族管理系统 API接口 (ASP.NET C#)示例下载及代码说明
- 给大家提供一个C#2.0的网站后台文章上传与前台显示的代码!呵呵!fckeditor大家自己调哦!
- 通过Mesos、Docker和Go,使用300行代码创建一个分布式系统
- C#教程之自己动手写映射第七节[总结与代码下载]
- 自己动手写一个推荐系统
- 系统多种资源文件代码示例(例如一个系统同时具有中文简体,中文繁体,英文,日文等不同资源文件)(示例代码下载)
- C# 一个自己写的树结构代码(1)
- 自己动手写一个推荐系统
- [转]通过Mesos、Docker和Go,使用300行代码创建一个分布式系统
- Asp.net 在网页编写C#代码示例-- 一个简单的web MsSql 命令执行环境
- 最近项目中有遇到报表数据入库的情况,数据量说大不大,说小又赖得自己手动敲!于是自己动手写了一个入库的,下面直接上代码,如有同样的,请联系我删除此文
- 自己动手制作(DIY)一个Mini-Linux系统
- C#编写一个自己输入内容的代码
- 分布式编程->Remoting的一个代码示例(借助Remoting实现发送信息功能)
- 自己动手写中文分词解析器完整教程,并对出现的问题进行探讨和解决(附完整c#代码和相关dll文件、txt文件下载)
- C# 创建、部署和调用WebService的简单示例 webservice 可以用于分布式应用程序之间的交互,和不同程序之间的交互。 概念性的东西就不说太多,下面开始创建一个简单的webservi
- 分布式编程->Remoting的一个代码示例(借助Remoting实现发送信息功能)
- 通用权限管理系统组件 (GPM - General Permissions Manager) 自己动手只能写一个轻量级的权限系统了功能也不强大,这不是白白流血流汗吗?