(六)分布式通信----MessagePack序列化
==>>点击查看本系列文章目录
1. .Net Core的序列化方式
1.1 json.Net
常用的工具包,如Newtonsoft.Json, 它是基于json格式的序列化和反序列化的组件
json.net 有以下优点:
侵入性:可以不添加attribute,就能进行序列化操作
灵活性:可以灵活性配置,比如允许被序列化的成员自定义名字,屏蔽的非序列化属性成员
可读性: 数据格式比较简单, 易于读写
依赖性:可以序列化成JObject,无需依赖对象进行序列化和泛型化。
1.2 protobuf
它是基于二进制格式的序列化和反序列化的组件
protobuf 有以下优点:
性能高 : 序列化后体积相比Json和XML很小,适合RPC二进制传输
跨语言:支持跨平台多语言
兼容性:消息格式升级和兼容性还不错
速度快 :序列化反序列化速度很快,快于Json的处理速度
1.3 messagepack
它是基于二进制格式的序列化和反序列化的组件
messagepack有以下优点:
性能高:序列化后体积相比Json和XML很小,适合RPC二进制传输
跨语言:支持跨平台多语言
兼容性:消息格式升级和兼容性还不错
速度快 :序列化反序列化速度很快,快于Json的处理速度
messagepack不管是小数据量还是大数据量都保持比较稳定的性能,本文中使用messagepack序列化方式。
2. 项目编码及设计模式
如下是文件结构:

2.1 工厂模式
抽象接口 工厂负责创建编码器和解码器
1.工厂
/// <summary>
/// 一个抽象的传输消息编解码器工厂。
/// </summary>
public interface ITransportMessageCodecFactory
{
/// <summary>
/// 获取编码器。
/// </summary>
/// <returns>编码器实例。</returns>
ITransportMessageEncoder GetEncoder(); /// <summary>
/// 获取解码器。
/// </summary>
/// <returns>解码器实例。</returns>
ITransportMessageDecoder GetDecoder();
}
2.编码器
/// <summary>
/// 编码器
/// </summary>
public interface ITransportMessageEncoder
{
byte[] Encode(TransportMessage message);
}
3.解码器
/// <summary>
/// 解码器
/// </summary>
public interface ITransportMessageDecoder
{
TransportMessage Decode(byte[] data);
}
实现类 工厂、编码器、解码器为MessagePack的实现
1.工厂
public sealed class MessagePackTransportMessageCodecFactory : ITransportMessageCodecFactory
{
#region Field
private readonly ITransportMessageEncoder _transportMessageEncoder = new MessagePackTransportMessageEncoder();
private readonly ITransportMessageDecoder _transportMessageDecoder = new MessagePackTransportMessageDecoder();
#endregion Field #region Implementation of ITransportMessageCodecFactory /// <inheritdoc />
/// <summary>
/// 获取编码器
/// </summary>
/// <returns></returns>
public ITransportMessageEncoder GetEncoder()
{
return _transportMessageEncoder;
} /// <inheritdoc />
/// <summary>
/// 获取解码器
/// </summary>
/// <returns></returns>
public ITransportMessageDecoder GetDecoder()
{
return _transportMessageDecoder;
}
#endregion Implementation of ITransportMessageCodecFactory
}
2.编码器
public sealed class MessagePackTransportMessageEncoder : ITransportMessageEncoder
{
#region Implementation of ITransportMessageEncoder public byte[] Encode(TransportMessage transportMessage)
{
MessagePackTransportMessage messagePackTransportMessage = new MessagePackTransportMessage(transportMessage);
return MessagePackSerializer.Serialize(messagePackTransportMessage);
} #endregion Implementation of ITransportMessageEncoder
}
3.解码器
public sealed class MessagePackTransportMessageDecoder : ITransportMessageDecoder
{
#region Implementation of ITransportMessageDecoder public TransportMessage Decode(byte[] data)
{
MessagePackTransportMessage messagePackTransportMessage = MessagePackSerializer.Deserialize<MessagePackTransportMessage>(data);
return messagePackTransportMessage.GetTransportMessage();
} #endregion Implementation of ITransportMessageDecoder
}
2.2 装饰器模式
高层的消息模型:
public class TransportMessage
{
/// <summary>
/// 消息Id。
/// </summary>
public string Id { get; set; } /// <summary>
/// 消息内容。
/// </summary>
public object Content { get; set; } /// <summary>
/// 内容类型。
/// </summary>
public string ContentType { get; set; }
}
由于MessagePack序列化方式具有侵入性,需要添加 MessagePackObjectAttribute 和 KeyAttribute 特性,因此需要对 TransportMessage 做装饰:
using MessagePack;
[MessagePackObject]
public class MessagePackTransportMessage
{
private TransportMessage _transportMessage;
public MessagePackTransportMessage(): this(new TransportMessage())
{
}
public MessagePackTransportMessage(TransportMessage transportMessage)
{
this._transportMessage = transportMessage;
}
public TransportMessage GetTransportMessage()
{
return _transportMessage;
}
/// <summary>
/// 消息Id。
/// </summary>
[Key()]
public string Id
{
get { return _transportMessage.Id; }
set { _transportMessage.Id = value; }
}
/// <summary>
/// 消息内容。
/// </summary>
[Key()]
public object Content
{
get { return _transportMessage.Content; }
set { _transportMessage.Content = value; }
}
/// <summary>
/// 内容类型。
/// </summary>
[Key()]
public string ContentType
{
get { return _transportMessage.ContentType; }
set { _transportMessage.ContentType = value; }
}
}
2.3 依赖注入
Autofac 是一个依赖注入工具包,比.net Core 原始的依赖注入拥有更完善的功能,中文官方文档:https://autofaccn.readthedocs.io/zh/latest/index.html
using Autofac;
public static class ContainerBuilderExtensions
{
/// <summary>
/// 使用messagepack编码解码方式
/// </summary>
/// <param name="builder"></param>
/// <returns></returns>
public static ContainerBuilder UseMessagePackCodec(this ContainerBuilder builder)
{
builder.RegisterType(typeof(MessagePackTransportMessageCodecFactory)).As(typeof(ITransportMessageCodecFactory)).SingleInstance();
return builder;
}
}
2.4 单元测试
端到端的测试,同时测试编码和解码
using MessagePack;
using Microsoft.VisualStudio.TestTools.UnitTesting; [TestClass]
public class MessagePackTest
{
[TestMethod]
public void TestCodec()
{
Person person = new Person
{
Name = "张宏伟",
Age =
};
TransportMessage transportMessage = new TransportMessage
{
Id = "",
ContentType = "Person",
Content = person
};
MessagePackTransportMessageCodecFactory factory = new MessagePackTransportMessageCodecFactory();
ITransportMessageEncoder encoder = factory.GetEncoder();
ITransportMessageDecoder decoder = factory.GetDecoder();
byte[] vs = encoder.Encode(transportMessage);
TransportMessage message =decoder.Decode(vs);
Assert.AreEqual(message.Id, "");
Assert.AreEqual(message.ContentType, "Person");
Assert.AreEqual(((object[])message.Content)[].ToString(), "张宏伟" );
Assert.AreEqual(((object[])message.Content)[].ToString(), "");
} [MessagePackObject]
public class Person
{
[Key()]
public string Name { get; set; }
[Key()]
public int Age { get; set; }
}
}
(六)分布式通信----MessagePack序列化的更多相关文章
- CRL快速开发框架系列教程六(分布式缓存解决方案)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- Hadoop阅读笔记(六)——洞悉Hadoop序列化机制Writable
酒,是个好东西,前提要适量.今天参加了公司的年会,主题就是吃.喝.吹,除了那些天生话唠外,大部分人需要加点酒来作催化剂,让一个平时沉默寡言的码农也能成为一个喷子!在大家推杯换盏之际,难免一些画面浮现脑 ...
- spring boot / cloud (十六) 分布式ID生成服务
spring boot / cloud (十六) 分布式ID生成服务 在几乎所有的分布式系统或者采用了分库/分表设计的系统中,几乎都会需要生成数据的唯一标识ID的需求, 常规做法,是使用数据库中的自动 ...
- axis实现webservices分布式通信
分布式通信原理 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2ZsMjAxMjEzMTQ=/font/5a6L5L2T/fontsize/400/fil ...
- 10.axis实现webservices分布式通信
转自:https://www.aliyun.com/jiaocheng/310112.html 分布式通信原理 基本原理:stub和skeleton作为客户端和服务端传输的中介,stub和skelet ...
- dotnet 使用 MessagePack 序列化对象
和很多序列化库一样,可以通过 MessagePack 序列化和反序列化,和 json 相比这个库提供了二进制的序列化,序列化之后的内容长度比 json 小很多 这个库能序列的内容不多,大多数时候建议使 ...
- 4.7 ROS分布式通信
4.7 ROS分布式通信 ROS是一个分布式计算环境.一个运行中的ROS系统可以包含分布在多台计算机上多个节点.根据系统的配置方式,任何节点可能随时需要与任何其他节点进行通信. 因此,ROS对网络配置 ...
- SignalR 中使用 MessagePack 序列化提高 WebSocket 通信性能
It's like JSON.but fast and small. MessagePack is an efficient binary serialization format. It lets ...
- (七)分布式通信----Netty实现NIO通信
目录 1. 消息监听器 2. 指令执行器 3. 消息发送器 4. 客户端工厂 5. 序列化工具 6. 通信主机 项目文件结构图 通信主机: 1. 消息监听器(黄色框) 这部分由 Netty 实现,Ne ...
随机推荐
- AIX7.1安装zabbix_agent3.4
1.在zabbix官网https://www.zabbix.com/download下载Zabbix pre-compiled agents 2.Zabbix pre-compiled agents安 ...
- 解决Oracle.DataAccess.Client.OracleConnection”的类型初始值设定项引发异常。
解决Oracle.DataAccess.Client.OracleConnection”的类型初始值设定项引发异常. 这个问题他们说是oracle的版本问题 但是好像不是...(我感觉VS版本问题,我 ...
- 【iOS】Receiver type 'XXX' for instance message is a forward declaration
今天遇到这个错误.刚开始字体太大,没显示全,后来调小字体之后看到了完整提示信息: 之后就忽然想起没引入相关的类,添加 #import "RDVTabBarItem.h" 就行了.
- angularjs通信以及postmessage与iframe通信
这篇文章是用markdown工具写的,有需要的可以使用vscode打开 # angularjs 控制器.组件之间的通信 ## 一.基于事件的方式 此方式下,主要通过 angularjs 内置指令` ...
- IDEA 控制台输出日志无法grep
不知从何时开始,我的IDEA控制台无法直接使用Grep插件来过滤输出日志了,这个插件真的挺好用的,不知道是升级后造成的还是我自己设置错误,反正在控制台右键无法打开grep来过滤: 在我开发过程中需要这 ...
- Bean Validation完结篇:你必须关注的边边角角(约束级联、自定义约束、自定义校验器、国际化失败消息...)
每篇一句 没有任何技术方案会是一种银弹,任何东西都是有利弊的 相关阅读 [小家Java]深入了解数据校验:Java Bean Validation 2.0(JSR303.JSR349.JSR380)H ...
- How to check all timestamps of a file
A friend of mine she asked me how to check all timestamps of a file on an NTFS volume. She did not h ...
- Android 属性动画实战
什么是属性动画? 属性动画可以通过直接更改 View 的属性来实现 View 动画.例如: 通过不断的更改 View 的坐标来实现让 View 移动的效果: 通过不断的更改 View 的背景来实现让 ...
- 02、Java的lambda表达式和JavaScript的箭头函数
前言 在JDK8和ES6的语言发展中,在Java的lambda表达式和JavaScript的箭头函数这两者有着千丝万缕的联系:本次试图通过这篇文章弄懂上面的两个"语法糖". 简介 ...
- Linux下,为应用程序添加桌面图标(ubuntu18.4)
一.桌面图标位置 Lniux下桌面图标储存路径为:/usr/share/applications 二.桌面图标格式 所有桌面图标格式均为desktop,即名为XXX.desktop 三.编辑内容(常用 ...