欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

前言

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

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

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

通過(guò)NuGet獲取Zaabee.AspNetCoreProtobuf

Install-Package Zaabee.AspNetCoreProtobuf

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

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

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

測(cè)試代碼

在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)目,通過(guò)Nuget引用Microsoft.AspNetCore.TestHost,建立一個(gè)測(cè)試類

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ù)的測(cè)試中,protobuf的序列化/反序列化性能大概是Json.net的三倍,序列化后的體積大概只有Json的二分之一,這可以在相當(dāng)程度上提高webapi的吞吐性能。

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

protobuf的缺點(diǎn)

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

原理

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

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

總結(jié)

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

相關(guān)文章

最新評(píng)論