gpt4 book ai didi

java - 在 gRPC 中使用直接类以避免数据复制

转载 作者:太空宇宙 更新时间:2023-11-03 14:46:21 30 4
gpt4 key购买 nike

我们希望避免gRPC通信中的数据拷贝。

我在 proto 文件中有以下(不是真实的)示例:

message Person
{
string id = 1;
string Name = 2;
string Address = 3;
}

message PersonId
{
required string id = 1;
}

service PersonService
{
rpc GetPersonById( PersonId ) returns Person;
}

而且效果很好。但是当我实现它时,我将所有数据复制到请求中:

class PersonServiceImpl : PersonService.MaterialServiceBase
{
public override Task<Person> GetPersonById( PersonId request, ServerCallContext context )
{
Datamodel.Person person = GetPersonForDatabaseAsync(request.Id).Result;

Task.FromResult( new Person() {
Id = person.Id,
Name = person.Name,
Address = person.Address
} );
}
}

但是,如果我们避免数据复制,那将是非常棒的,因为当我们向 Person 添加新成员时,它既慢又危险。完美的代码如下:

    public override Task<Person> GetPersonById( PersonId request, ServerCallContext context )
{
return GetPersonForDatabaseAsync(request.Id);
}

这可能吗?

我们检查了性能,25% 的时间用于编码和解码,尤其是在具有嵌套类型(例如 Huge Orders)的大型类型上。

我添加了java标签,因为它也是Java环境中的相关问题。

因评论而编辑:

namespace Datamodel
{
class Person
{
string Id { get; set; }
string Name { get; set; }
string Address { get; set; }
}
}

所以问题是,从另一个角度来看:我应该如何更改 Datamodel.Person 以使其与 gRPC 响应兼容。

最佳答案

不幸的是,这是不可能的,因为 protobuf 代码生成。所有成员和函数都是硬编码的。

如果 gRPC 提供了使用接口(interface)而不是直接成员定义消息类的可能性,那就太好了。该接口(interface)将包含所有成员和一个创建函数。

所以生成的代码是这样改的:

[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom( pb::CodedInputStream input )
{
uint tag;
while ( ( tag = input.ReadTag() ) != 0 )
{
switch ( tag )
{
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom( _unknownFields, input );
break;
case 10:
{
Id = input.ReadString();
break;
}
case 18:
{
Name = input.ReadString();
break;
}
}
}
}

对此:

[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom( pb::CodedInputStream input )
{
uint tag;
while ( ( tag = input.ReadTag() ) != 0 )
{
switch ( tag )
{
default:
Instance.UnknownFields = pb::UnknownFieldSet.MergeFieldFrom( Instance.UnknownFields, input );
break;
case 10:
{
Instance.Id = input.ReadString();
break;
}
case 18:
{
Instance.Name = input.ReadString();
break;
}
}
}
}

其中 Instance 是从 protofile 生成的接口(interface)的实现:

public interface IPerson
{
private pb::UnknownFieldSet UnknownFields;
string Id { get; set; }
string Name { get; set; }
}

如果我的 Datamodel.Person 实现了这个接口(interface),并且生成的 Person 消息通过这个 IPerson 接口(interface)存储和检索数据,那么我们可以避免datacopy,gRPC的使用会更快25%。

我认为这对 gRPC 来说是一个巨大的优势也许 Jon Skeet可以做到。当我们有清晰的概念时,我可以对 c、c++ 和 c# 进行更改。

顺便说一下,这将是 gRPC 向前迈出的一大步,因为这是人们使用 REST 而不是它的原因之一。在 REST 世界中,可以使用 JSON Serialize 将数据直接检索到 Datamodel 结构。通过 Deserialize,他们可以直接发送结构。

它必须是protobuf文件中的一个新选项,并且在所有支持接口(interface)的语言中都是可能的。

关于java - 在 gRPC 中使用直接类以避免数据复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54019930/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com