没时间解释了, 快上车
通过 NuGet 获取 Zaabee.AspNetCoreProtobuf
Install-Package Zaabee.AspNetCoreProtobuf
在 Startup.cs 文件中修改 ConfigureServices 方法
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddMvc(options => { options.AddProtobufSupport(); });
- }
搞掂这时候你就可以通过 application/x-protobuf 的 content-type 来让 asp.net core 使用 protobuf 来进行序列化 / 反序列化
测试代码
在 asp.net core 项目中添加以下 DTO
- [ProtoContract]
- public class TestDto
- {
- [ProtoMember(1)] public Guid Id { get; set; }
- [ProtoMember(2)] public string Name { get; set; }
- [ProtoMember(3)] public DateTime CreateTime { get; set; }
- [ProtoMember(4)] public List<TestDto> Kids { get; set; }
- [ProtoMember(5)] public long Tag { get; set; }
- [ProtoMember(6)] public TestEnum Enum { get; set; }
- }
- public enum TestEnum
- {
- Apple,
- Banana,
- Pear
- }
新建一个 XUnit 项目, 通过 Nuget 引用 Microsoft.AspNetCore.TestHost, 建立一个测试类
- public class AspNetCoreProtobufTest
- {
- private readonly TestServer _server;
- private readonly HttpClient _client;
- public AspNetCoreProtobufTest()
- {
- _server = new TestServer(
- new webHostBuilder()
- .UseKestrel()
- .UseStartup<Startup>());
- _client = _server.CreateClient();
- }
- [Fact]
- public void Test()
- {
- // HTTP Post with Protobuf Response Body
- _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-protobuf"));
- var dtos = GetDtos();
- var stream = new MemoryStream();
- ProtoBuf.Serializer.Serialize(stream, dtos);
- HttpContent httpContent = new StreamContent(stream);
- // HTTP POST with Protobuf Request Body
- var responseForPost = _client.PostAsync("api/Values", httpContent);
- var result = ProtoBuf.Serializer.Deserialize<List<TestDto>>(
- responseForPost.Result.Content.ReadAsStreamAsync().Result);
- Assert.True(CompareDtos(dtos,result));
- }
- private static bool CompareDtos(List<TestDto> lstOne, List<TestDto> lstTwo)
- {
- lstOne = lstOne ?? new List<TestDto>();
- lstTwo = lstTwo ?? new List<TestDto>();
- if (lstOne.Count != lstTwo.Count) return false;
- for (var i = 0; i < lstOne.Count; i++)
- {
- var dtoOne = lstOne[i];
- var dtoTwo = lstTwo[i];
- if (dtoOne.Id != dtoTwo.Id || dtoOne.CreateTime != dtoTwo.CreateTime || dtoOne.Enum != dtoTwo.Enum ||
- dtoOne.Name != dtoTwo.Name || dtoOne.Tag != dtoTwo.Tag || !CompareDtos(dtoOne.Kids, dtoTwo.Kids))
- return false;
- }
- return true;
- }
- private static List<TestDto> GetDtos()
- {
- return new List<TestDto>
- {
- new TestDto
- {
- Id = Guid.NewGuid(),
- Tag = long.MaxValue,
- CreateTime = DateTime.Now,
- Name = "0",
- Enum = TestEnum.Apple,
- Kids = new List<TestDto>
- {
- new TestDto
- {
- Id = Guid.NewGuid(),
- Tag = long.MaxValue - 1,
- CreateTime = DateTime.Now,
- Name = "00",
- Enum = TestEnum.Banana
- },
- new TestDto
- {
- Id = Guid.NewGuid(),
- Tag = long.MaxValue - 2,
- CreateTime = DateTime.Now,
- Name = "01",
- Enum = TestEnum.Pear
- }
- }
- },
- new TestDto
- {
- Id = Guid.NewGuid(),
- Tag = long.MaxValue - 3,
- CreateTime = DateTime.Now,
- Name = "1",
- Enum = TestEnum.Apple,
- Kids = new List<TestDto>
- {
- new TestDto
- {
- Id = Guid.NewGuid(),
- Tag = long.MaxValue - 4,
- CreateTime = DateTime.Now,
- Name = "10",
- Enum = TestEnum.Banana
- },
- new TestDto
- {
- Id = Guid.NewGuid(),
- Tag = long.MaxValue - 5,
- CreateTime = DateTime.Now,
- Name = "11",
- Enum = TestEnum.Pear
- }
- }
- }
- };
- }
- }
为什么要用 protobuf?
因为快在我们这边使用业务数据的测试中, protobuf 的序列化 / 反序列化性能大概是 Json.net 的三倍, 序列化后的体积大概只有 Json 的二分之一, 这可以在相当程度上提高 webapi 的吞吐性能
另外就是 Json 对于浮点数的处理存在精度丢失, 因为 JS 的 number 类型的安全整数是 53 位当我们使用雪花算法来提供全局递增 ID 时会因为精度丢失导致重复主键而且情况不仅如此, 由于同样原因传递 DateTime 类型也会因为毫秒不一致导致时间匹配错误一般的解决方法是使用字符串传递, 不过这毕竟属于偏方并没有从根源上解决问题, 因此我们还是直接使用 protobuf 来处理
protobuf 的缺点
DTO 层必须引用 protobuf-net 来添加特性, 这在一定程度上导致了代码的侵入基本上 DTO 属于 POCO, 依赖第三方包的话总觉得有点不贞洁另外就是 protobuf 序列化后的数据不具有可视化, 因此如果是使用消息队列或者请求监控的地方, 就要综合考虑 protobuf 是否适合使用场景
原理
asp.net core 是基于中间件方式来实现, 其自带默认的 JsonFormater(基于 Json.net),asp.net core 会根据 content type 来选择对应的 Formater 来处理对象的序列化, 当中包括 InputFormatter(反序列化) 和 OutputFormatter(序列化) 因此除了 protobuf, 我们还可以添加或者替换其它的序列化方式, 例如使用 Jil 来代替 Json.net 来提高 Json 性能
来源: https://www.cnblogs.com/Mutuduxf/p/8457011.html