mirror of
https://github.com/nspcc-dev/neofs-api-go.git
synced 2026-03-01 04:28:56 +00:00
Transport of stably serialized messages over gRPC #68
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @cthulhu-rider on GitHub (Mar 10, 2022).
Context
In current implementation we define type per message in NeoFS API in order to:
gRPClibGiven the need to serialize messages for signatures and the like, we can try to skip the extra conversion+serialization step (
ToGRPCMessagemethods) of thegRPClibrary utilities and pass the messages directly in binary form (our serialization follows Protocol Buffers).Proposal
Research direct transmission of message types on the example of some request and pay attention on the optimality criterion:
It is worth mentioning that the results directly depend on the selected versions of the libraries: current and
gRPC.For experimentation, I propose to implement a test scenario based on a fake connection (
net.Conn), which will allow you to calculate the amount of transmitted traffic (at least from the application side).@fyrchik commented on GitHub (Mar 12, 2022):
This will definitely lower the memory consumption.
The simplest way to gain control over what is transmitted over wire is to implement all methods from https://github.com/protocolbuffers/protobuf-go/blob/master/runtime/protoiface/methods.go#L17 . I am not sure that this methods are always called instead of the default implementation, though. This helps to transmit stably-serialized messages. However there is still a need for
ProtoReflectmethod and there are someSuper-trickycomments for the current implementation https://github.com/protocolbuffers/protobuf-go/blob/master/internal/impl/pointer_unsafe.go#L144 (MessageStateOfis called fromProtoReflect).As for having some interface for transmitting raw bytes, I am not sure this is possible at all, without reimplementing parts of gRPC from scratch.
Another approach is to implement stable marshalers directly on protobuf-generated structures. I have implemented simple protobuf plugin for generating them https://github.com/fyrchik/neofs-api-go/tree/marshal . Here we lose the benefit (arguable) of not tying the transport logic to gRPC, though I am not sure I understand what it means. However, it is easily extendable, fully-automatic and can help to enforce consistent naming.
The downside is that types are not so rich, but we don't have many places where types inferred from
*.protofiles are inconvenient (the only case that comes to mind is that we useuint32for enums).protoc-gen-goimplementation is not bigprotocolbuffers/protobuf-go@fb30439f55/cmd/protoc-gen-go, so we can even fork it and add necessary code right there (stable marshaling,uint32for enums, pointer-less slices) without an additional plugin.@alexvanin commented on GitHub (Mar 17, 2022):
That is very nice! I propose to test this approach in protobuf messages of
controlservice in NeoFS Node. This service is not a part of the API so it can be a good place to test new structures generated by forkedprotoc-gen-gowithout affecting core protocol.