亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

如何為asp.net core添加protobuf支持詳解

 更新時(shí)間:2018年02月25日 15:00:42   作者:Mutuduxf  
這篇文章主要給大家介紹了關(guān)于如何為asp.net core添加protobuf支持的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。

前言

在一些性能要求很高的應(yīng)用中,使用protocol buffer序列化,優(yōu)于Json。而且protocol buffer向后兼容的能力比較好。

由于Asp.net core 采用了全新的MiddleWare方式,因此使用protobuf序列化,只需要使用Protobuf-net修飾需要序列化的對象,并在MVC初始化的時(shí)候增加相應(yīng)的Formatter就可以了。

沒時(shí)間解釋了,快上車。

通過NuGet獲取Zaabee.AspNetCoreProtobuf

Install-Package Zaabee.AspNetCoreProtobuf

在Startup.cs文件中修改ConfigureServices方法

public void ConfigureServices(IServiceCollection services)
{
  services.AddMvc(options => { options.AddProtobufSupport(); });
}

搞掂……這時(shí)候你就可以通過application/x-protobuf的content-type來讓asp.net core使用protobuf來進(jìn)行序列化/反序列化。

測試代碼

在asp.net core項(xiàng)目中添加以下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
}

新建一個(gè)XUnit項(xiàng)目,通過Nuget引用Microsoft.AspNetCore.TestHost,建立一個(gè)測試類

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?

因?yàn)榭臁谖覀冞@邊使用業(yè)務(wù)數(shù)據(jù)的測試中,protobuf的序列化/反序列化性能大概是Json.net的三倍,序列化后的體積大概只有Json的二分之一,這可以在相當(dāng)程度上提高webapi的吞吐性能。

另外就是Json對于浮點(diǎn)數(shù)的處理存在精度丟失,因?yàn)镴S的number類型的安全整數(shù)是53位。當(dāng)我們使用雪花算法來提供全局遞增ID時(shí)會(huì)因?yàn)榫葋G失導(dǎo)致重復(fù)主鍵。而且情況不僅如此,由于同樣原因傳遞DateTime類型也會(huì)因?yàn)楹撩氩灰恢聦?dǎo)致時(shí)間匹配錯(cuò)誤。一般的解決方法是使用字符串傳遞,不過這畢竟屬于偏方并沒有從根源上解決問題,因此我們還是直接使用protobuf來處理。

protobuf的缺點(diǎn)

DTO層必須引用protobuf-net來添加特性,這在一定程度上導(dǎo)致了代碼的侵入?;旧螪TO屬于POCO,依賴第三方包的話總覺得有點(diǎn)不貞潔……另外就是protobuf序列化后的數(shù)據(jù)不具有可視化,因此如果是使用消息隊(duì)列或者請求監(jiān)控的地方,就要綜合考慮protobuf是否適合使用場景。

原理

asp.net core是基于中間件方式來實(shí)現(xiàn),其自帶默認(rèn)的JsonFormater(基于Json.net),asp.net core會(huì)根據(jù)content type來選擇對應(yīng)的Formater來處理對象的序列化,當(dāng)中包括InputFormatter(反序列化)和OutputFormatter(序列化)。因此除了protobuf,我們還可以添加或者替換其它的序列化方式,例如使用Jil來代替Json.net來提高Json性能。

以上實(shí)現(xiàn)以及Demo和測試的源代碼已放到 GitHub 上。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

最新評論