在阅读Netty教程时,我发现了一个简单的 描述 如何整合Netty和 Google协议缓冲区. 。我已经开始研究其示例(因为文档中没有更多信息),并写了一个简单的应用程序,例如本地时间应用程序。但是,此示例是在管道事实类中使用静态初始化,例如:

import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.protobuf.ProtobufDecoder;
import org.jboss.netty.handler.codec.protobuf.ProtobufEncoder;
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;

import static org.jboss.netty.channel.Channels.pipeline;

/**
 * @author sergiizagriichuk
 */
class ProtoCommunicationClientPipeFactory implements ChannelPipelineFactory {

    public ChannelPipeline getPipeline() throws Exception {
        ChannelPipeline p = pipeline();
        p.addLast("frameDecoder", new ProtobufVarint32FrameDecoder());
        p.addLast("protobufDecoder", new ProtobufDecoder(Communication.DataMessage.getDefaultInstance()));

        p.addLast("frameEncoder", new ProtobufVarint32LengthFieldPrepender());
        p.addLast("protobufEncoder", new ProtobufEncoder());

        p.addLast("handler", new ProtoCommunicationClientHandler());
        return p;
    }

}

(请看一下线 p.addLast("protobufDecoder", new ProtobufDecoder(Communication.DataMessage.getDefaultInstance()));),只能创建一个工厂(据我所知) ClientBootstrap 我的意思是 bootstrap.setPipelineFactory() 方法。因此,在这种情况下,我可以使用 发送给服务器的消息和 从服务器接收的消息对我不利,我认为不仅对我:(我只能使用一个连接或从一个连接中使用不同的消息?也许我可以创建一些 protobufDecoder 像这样

p.addLast("protobufDecoder", new ProtobufDecoder(Communication.DataMessage.getDefaultInstance()));
p.addLast("protobufDecoder", new ProtobufDecoder(Communication.TestMessage.getDefaultInstance()));
p.addLast("protobufDecoder", new ProtobufDecoder(Communication.SrcMessage.getDefaultInstance()));

还是其他技术?非常感谢。

有帮助吗?

解决方案

我找到了Netty的作者 Google组 并了解我必须更改架构或写自己的解码器,因此,开始思考哪种方法会变得轻松,更好。

其他提示

如果您要编写自己的编解码器,则可能需要考虑实现自定义数据对象的外部化接口。

  • 可序列化是低功能的,但性能最差(序列化)。
  • Protobuf是努力和绩效之间的良好权衡(需要.proto维护)
  • 外部化是高度的努力,但最佳性能(自定义最小编解码器)

如果您已经知道您的项目必须像山山羊一样扩展,那么您可能必须走上艰难的道路。 Protobuf不是银弹。

从理论上讲,这可以通过修改每个传入消息的管道以适合传入消息来完成。看一下 端口统一 Netty中的示例。

序列将是:
1)在框架解码器或另一个“解码器decodecoder”中,您检查了传入消息的消息类型
2)动态修改管道,如示例所示

但是,为什么不使用不同的连接并遵循此顺序:
1)仅根据传入消息添加管道中的其他解码器。
2)添加 相同的 通道上游处理程序作为管道中的最后一个处理程序的实例,这样,所有消息都被路由到同一实例,这几乎就像拥有一个连接一样。

问题在于,没有办法以二进制格式将两个不同的Protobuf消息彼此不同。但是有一种方法可以在Protobuf文件中解决:

message AnyMessage {
    message DataMessage { [...] }
    optional DataMessage dataMessage = 1;
    message TestMessage { [...] }
    optional TestMessage testMessage = 2;
    message SrcMessage { [...] }
    optional SrcMessage srcMessage = 3;
}

未设置的可选字段没有生产开销。此外,您可以添加枚举,但这只是一个奖励。

该问题不是净限制或编码器/解码器的限制。问题在于,Google协议缓冲区仅提供了一种序列化/应对对象的方法,但没有提供协议。它们具有某种RPC实现为标准分发的一部分,但是如果您尝试实现其RPC协议,则最终将获得3层间接。我在一个项目之一中所做的是定义一个基本上是消息联合的消息。此消息包含一个类型的字段,另一个字段是实际消息。您仍然会以2个间接层的方式最终出现,但不会3。这样,Netty的示例将适用于您,但是正如上一篇文章中所述,您必须在业务逻辑处理程序中投入更多逻辑。

您可以使用消息隧道来将各种类型的消息作为单一消息中的有效负载发送。希望有帮助

经过长期的研究和痛苦...我想到了将消息组成的想法中的一个包装器消息。在该消息中我使用 一个 关键要限制允许对象的数量 只有一个。结帐示例:

message OneMessage {
    MessageType messageType = 1;

    oneof messageBody {
        Event event = 2;
        Request request  = 3;
        Response response = 4;
    }

    string messageCode = 5; //unique message code
    int64 timestamp = 6; //server time
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top