NATS.Net序列化完全攻略:JSON、ProtoBuf与自定义序列化器一网打尽
【免费下载链接】nats.netThe official C# Client for NATS项目地址: https://gitcode.com/gh_mirrors/na/nats.net
NATS.Net 是 NATS 官方出品的 C# 客户端库,而序列化是使用它的第一道关卡:消息在网络上传输的都是字节,如何优雅地把 .NET 对象变成字节、再变回来,直接决定了你的代码简洁度和性能上限。这篇 NATS.Net 序列化攻略将带你快速掌握 JSON、ProtoBuf 和自定义序列化器的完整用法,新手也能照着做。
一、NATS.Net 序列化体系速览:三层自动适配
NATS.Net 的序列化设计非常聪明——它默认会按"类型自动选择"最合适的序列化器,你可以完全无感地使用。它的核心接口定义在 INatsSerialize.cs,只有两个方法:
Serialize(IBufferWriter<byte>, T):把对象写入缓冲区Deserialize(ReadOnlySequence<byte>):从字节还原对象
默认的NatsClient内置了一条序列化器链(见 NatsClientDefaultSerializer.cs):
| 消息类型 | 自动使用的序列化器 | 效果 |
|---|---|---|
byte[]、Memory<byte>、ReadOnlyMemory<byte> | 原始字节序列化器 | 零拷贝直通,最快 |
string、int、long、Guid、DateTime、bool等 | UTF-8 原始类型序列化器 | 直接以文本传输,可读性好 |
| 其他任意复杂对象 | JSON 序列化器 | 自动序列化为 JSON |
这意味着:你什么都不用配,直接发布一个对象就能用 JSON 收发。这套"默认即 JSON"的设计,让 NATS.Net 用起来像 Redis 客户端一样简单。
二、最快上手方式:NATS.Net JSON 序列化三步走
JSON 是绝大多数场景的首选。NATS.Net 把 JSON 序列化做到了"开箱即用",你只需三步:
- 安装
NATS.Net包(已包含NATS.Client.Serializers.Json序列化器) - 创建
NatsClient连接 - 直接
PublishAsync/SubscribeAsync发布和订阅你的模型
参考官方示例 Example.Core.PublishModel/Program.cs,发布一个对象只需一行:
await using var connection = new NatsConnection(options); await connection.PublishAsync(subject, new Bar { Id = i, Name = "Baz" });订阅端同样简洁:
await foreach (var msg in connection.SubscribeAsync<Bar>("bar.*")) { Console.WriteLine($"{msg.Data.Id}: {msg.Data.Name}"); }整个流程中你几乎看不到任何序列化代码,NATS.Net 已默默替你完成了 JSON 编码与解码。
三、显式配置 JSON 序列化器:控制选项与行为
默认 JSON 序列化器会自动忽略null值写入。如果你需要自定义 JSON 选项(如命名策略、枚举转字符串等),可以显式指定NatsJsonSerializerRegistry:
var options = NatsOpts.Default with { SerializerRegistry = NatsJsonSerializerRegistry.Default, }; await using var connection = new NatsConnection(options);NatsOpts.SerializerRegistry就是全局序列化器的挂载点,见 NatsOpts.cs。而NatsJsonSerializer的实现位于 NatsJsonSerializer.cs,它基于System.Text.Json,复用了线程静态的Utf8JsonWriter来减少分配,性能表现相当出色。
💡 提示:反射式 JSON 序列化不适合 Native AOT 场景,AOT 部署请用下面的源码生成方案。
四、Native AOT 场景:使用源码生成 JSON 序列化
如果你的应用要发布为 Native AOT(原生单文件),反射式 JSON 会失效。NATS.Net 为此提供了基于JsonSerializerContext的源码生成序列化器NatsJsonContextSerializerRegistry,同样定义在 INatsSerialize.cs 中:
var options = NatsOpts.Default with { SerializerRegistry = new NatsJsonContextSerializerRegistry(MyJsonContext.Default), };配合[JsonSerializable(typeof(MyModel))]标注的生成上下文,即可在 AOT 下享受无反射、高性能的 JSON 序列化。官方示例 Example.NativeAot 展示了完整用法。
五、ProtoBuf 集成实战:NATS.Net + Google.Protobuf
追求极致性能或跨语言互通时,ProtoBuf 是比 JSON 更优的选择。NATS.Net 没有绑定任何特定二进制格式,你可以很自然地接入 ProtoBuf。官方示例 Example.ProtoBufMessages 给出了标准姿势:
- 编写
.proto文件(见 greeting.proto):
syntax = "proto3"; message Greeting { int32 id = 1; string name = 2; }- 在 Example.ProtoBufMessages.csproj 中引入
Google.Protobuf和Grpc.Tools并声明 Protobuf 编译项:
<ItemGroup> <PackageReference Include="Google.Protobuf" Version="3.29.3" /> <PackageReference Include="Grpc.Tools" Version="2.69.0" /> <Protobuf Include="**\*.proto" GrpcServices="none" /> </ItemGroup>- 发布时用
Greeting.ToByteArray()得到字节数组,订阅端用Greeting.Parser.ParseFrom(msg.Data)还原。因为字节数组走的是原生序列化通道,几乎没有额外开销。
六、自定义序列化器完整指南:实现 INatsSerializer 接口
当 JSON、ProtoBuf 都不满足需求时(比如 MessagePack、自定义加密、压缩格式),你可以实现自己的序列化器。核心是继承INatsSerializer<T>接口并实现两个方法,然后通过NatsSerializerBuilder<T>串成链:
public class MySerializer<T> : INatsSerializer<T> { public void Serialize(IBufferWriter<byte> bufferWriter, T value) { // 你的编码逻辑 } public T? Deserialize(in ReadOnlySequence<byte> buffer) { // 你的解码逻辑 } public INatsSerializer<T> CombineWith(INatsSerializer<T> next) => new MySerializer<T>(); }链式构建时,序列化器会按加入的逆序组合,先尝试链头的类型,不支持再向后传递(参考 INatsSerialize.cs 中NatsSerializerBuilder<T>.Build()的实现)。这样你就能实现"原始类型走最快路径、复杂对象走 JSON"的分级策略。
七、按消息粒度指定序列化器:更精细的控制
除了全局注册表,NATS.Net 还允许你在单条消息级别指定序列化器。NatsClient的发布与订阅方法都暴露了可选的 serializer 参数,见 NatsClient.cs:
// 发布时指定 await client.PublishAsync(subject, data, serializer: mySerializer); // 订阅时指定 await foreach (var msg in client.SubscribeAsync<T>(subject, serializer: myDeserializer)) { }这条特性让同一个连接可以同时承载不同格式的消息流,特别适合消息网关或协议适配场景。
八、序列化性能与选型建议
最后给出一份 NATS.Net 序列化选型清单:
- 追求极致吞吐、传输二进制:直接发
byte[]/Memory<byte>,走原始字节通道,零序列化开销; - 开发效率优先、调试友好:默认 JSON,看日志一眼就懂,推荐 90% 的业务场景;
- 跨语言互通、追求小体积:ProtoBuf / MessagePack 等自定义二进制序列化器;
- Native AOT 部署:务必使用源码生成的
NatsJsonContextSerializerRegistry,否则启动即崩; - 混合场景:用
NatsSerializerBuilder<T>构建链式序列化器 + 按消息粒度覆盖。
NATS.Net 的序列化设计把"易用"和"性能"平衡得相当好:默认开箱即用,进阶时每一层都可替换、可组合。希望这份 NATS.Net 序列化攻略能帮你少踩坑,把精力留给业务本身。动手试试吧——先从克隆 NATS.Net 仓库(git clone https://gitcode.com/gh_mirrors/na/nats.net)跑一遍 examples 目录下的官方示例开始,你会很快找到手感。🚀
【免费下载链接】nats.netThe official C# Client for NATS项目地址: https://gitcode.com/gh_mirrors/na/nats.net
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考