java如何最好地指定与Netty一起使用的Protobuf(最好使用内置Protobuf支持)
我在protocol buffers中指定了一个协议。传输层正在利用Netty的协议缓冲区支持——重要的是,Netty的ProtobufDecoder只接受一种类型的MessageLite
现在,我想通过这个通道发送各种不同的消息类型,每个子类型都有与之相关的结构化信息。协议缓冲区没有继承机制,所以我使用一种组合。我不确定我是否用正确的方法来做这件事
我的方法是使用枚举对不同的事件进行分类,并使用可选成员封装它们的差异。请参见下面我的.proto
,为了清晰起见,我对其进行了简化
我的问题是接收代码需要在EventType之间建立关联。ERROR和ErrorEventDetail。这感觉有点笨拙
简化的Events.proto
:
package events;
option java_package = "com.example";
option java_outer_classname = "EventProtocol";
message Event {
enum EventType {
START = 0;
DELEGATE = 1;
ERROR = 2;
STOP = 3;
}
required events.Event.EventType event_type = 1 [default = START];
required int32 id = 2;
required int64 when = 3;
optional StartEventDetail start_event_detail = 4;
optional DelegateEventDetail delegate_event_detail = 5;
optional ErrorEventDetail error_event_detail = 6;
optional StopEventDetail stop_event_detail = 7;
}
message StartEventDetail {
required string object_name = 1;
}
message DelegateEventDetail {
required int32 object_id = 2;
required string task = 3;
}
message ErrorEventDetail {
required string text = 1;
required int32 error_code = 2;
optional Event cause = 3;
}
message StopEventDetail {
required int32 object_id = 2;
}
这是最优的吗?
我是否会更好地使用extends,或者使用enum
的其他用法
甚至,我应该创建一个全新的OneToOneDecoder,它可以通过某种头来识别消息类型吗?我可以这么做,但我不想
谢谢
# 1 楼答案
看起来你们已经非常接近/已经在使用谷歌的protobufs技术之一,叫做Union Types
要点是你有一个专用的
type
字段,你可以“打开”它来知道要获取哪条消息:其中,Foo、Bar和Baz可以在其他文件中定义为单独的消息。您可以打开类型来获取实际的有效负载(它是Scala,但您可以用Java的
switch
做同样的事情):# 2 楼答案
另一种方法是使用protobuf支持的扩展机制。我在联合类型太大的情况下使用这种方法
# 3 楼答案
我最初使用扩展机制解决了同样的问题,我记录了here
但我发现Java中处理扩展所需的代码非常难看和冗长,所以我切换到前面描述的Union方法。由于生成的Java代码提供了一种一次性获取和构建每条消息的方法,因此代码更加简洁
我使用两种机制来决定提取哪个可选消息。当需要性能时,我使用另一个答案中描述的switch方法,当性能不是问题并且我不想维护switch语句时,我使用反射方法,我只为每条消息创建一个句柄(消息)。下面给出了反射方法的一个示例,在我的例子中,java包装器是一个名为Commands的类,由Netty为我解码。它首先尝试找到一个将特定消息作为参数的处理程序,如果失败,它将使用camel case名称调用一个方法。为此,枚举必须是camel case消息的下划线名称