【问题标题】:Cant choose the right networking solution for my Java app无法为我的 Java 应用程序选择正确的网络解决方案
【发布时间】:2011-01-26 05:33:36
【问题描述】:

我正在编写一个分布式 Java 应用程序,该应用程序将大量使用网络,并且需要快速

假设我有一个名为Widget 的类。小部件是在客户端创建的(很可能是 Swing 盒子),但需要在服务器端持久化并在所有其他连接的客户端之间共享/分发。所以,我需要一种方法来序列化 Widget 实例,将它们发送到服务器,服务器将在那里管理它们,并使用他们感兴趣的 Widget 中的状态更改来更新所有连接的客户端。(因此,一旦创建了 Widget 并将其发送到服务器-side,理论上它可以被任何其他客户端“拉下”和修改。

性能是必须的,所以这一定是二进制协议。也更喜欢非阻塞套接字,以及非常非常可扩展的东西。

因此,我将 RMI、NIO 和 Netty 视为可行的解决方案。如果我正确理解 Java 网络,那么一切似乎都表明 RMI 比 NIO 慢得多。我还听说可扩展性部门缺少 RMI。另一方面,NIO 为您提供了更大的灵活性,因此要复杂得多。 Netty 似乎拥有最好的文档,但似乎比 NIO 慢,并且可能无法完成我真正需要它做的事情。

对于小部件分发,我只是在寻找通过网络快速发送小部件的能力。不在乎使用什么协议。

有人愿意分享他们的想法/意见吗?

谢谢!

【问题讨论】:

    标签: java network-programming


    【解决方案1】:

    首先,RMI 和 NIO 是苹果对橙子;所以不要混淆不是替代品的东西。其次,确保性能真的很重要;以及什么样的性能(吞吐量和延迟通常是首选;或者可能是空间效率)。您可能高估了性能的重要性,因为对于好的解决方案,您更有可能受到网络性能的限制,而不是受端点 (CPU) 性能的限制。

    如果性能很重要,请查看jvm-serializers 以获得实际格式的性能比较。例如,Java 序列化用于 RMI。

    哦,顺便说一句,不要假设您必须使用二进制格式。这通常不是硬性要求;文本格式压缩得很好,更容易调试/故障排除,如果需要的话,还可以通过其他平台和语言进行处理。

    【讨论】:

    • StaxMan - 感谢您的意见。在理解 RMI 和 NIO 之间的区别时,我似乎遗漏了一些基本的东西。据我了解,两者都是基于套接字的。 NIO 允许您在 TCP 或 UDP 之上实现任何东西,而 RMI 似乎拥有自己的应用层协议,用于在网络上传输序列化对象。但这不只是归结为两种不同的基于套接字的协议吗?我在这里想念什么?除非术语“序列化”和“网络化”对象不意味着相同的东西......
    • NIO 是旧阻塞 I/O(“BIO”)的低级替代方案。 NIO 只允许以非阻塞方式访问套接字(和文件等)。 Netty 是一个让 NIO 更容易使用的库。 RMI 不仅实现了基于 tcp 的发送/接收的“黑匣子”,还实现了对象序列化和其他相关部分。使用 RMI 进行序列化确实包括从任何 Java 对象到 byte[] 并返回的完全序列化;我认为序列化在其他情况下还有其他含义?
    • 所以:基本上,RMI 实现了“你所需要的一切”,而且很难替换。 NIO(有或没有 Netty)是一个较低级别的构建块。您可以将数十种序列化方案中的任何一种与 NIO(或阻塞 I/O)一起使用。如果你喜欢 RMI 的想法,你可以考虑 RMI 替代 DiRMI,sourceforge.net/projects/dirmi,由亚马逊高级工程师编写;它“就像 RMI,只是更好”,解决了大多数已知的现有 RMI 问题。
    • Ahhhh....所以可以肯定地说,为了通过网络传递 Widget,必须首先将其序列化为字节,然后 RMI 使用 TCP 套接字(基于 NIO?)通过网络传递字节。然后,在另一端,RMI 具有将字节重构为 Java 对象的“黑盒”魔法。这是一个公平的评估吗?
    • 没错。 JDK 使用的 RMI 实现可能使用 NIO 或阻塞 i/o(可能是后者,因为 NIO 是在 RMI 之后添加的),但无论哪种方式它都基于套接字。
    【解决方案2】:

    你提到了 Netty。我会同意这一点。我对 Netty 的体验很棒。这是一个非常高效的库,具有可靠的文档和灵活性。

    它可以用二进制协议做任何你能想象到的事情,但它只做你需要的事情,所以它是轻量级的。它也可以很好地扩展。我已经成功地对一台服务器进行了负载测试,该服务器具有一个简单的作业,可为 200-300 个并发客户端维持超过 10k+ 的请求/秒。那是在相当标准的机架服务器上。

    有一点学习曲线,但 javadoc 是我见过的最好的解决这个障碍的一些。该项目正在积极开发中,项目负责人对问题和缺陷非常敏感。

    编辑:为了快速传输小部件,您可以查看协议缓冲区。它们对于通过网络对对象进行序列化/反序列化非常有效。

    【讨论】:

    • 感谢 rfreak!我会考虑到这一点——这些都是相当大的数字。另外,当我说这是一个使用分布式 Widget 对象的网络应用程序时,我是否正确使用了“分布式”这个短语?还是“序列化”、“分布式”或“网络化”有不同的含义?谢谢!
    【解决方案3】:

    你看过 JiniJavaspaces 吗?这是 RMI,所以可能不合适。但是基于空间的模式在分发对象、接收通知、以分布式方式更新等方面非常强大,您可以非常轻松地启动和运行一些东西。

    【讨论】:

    • Brian,谢谢你的建议 - 我今晚会去看看 Jini。
    【解决方案4】:

    Google 的 Protocol BuffersApache Thrift 都符合这些标准。

    它们是用于数据序列化的二进制协议,并且它们具有用于通过网络传递小部件的 RPC API,因此您不必重新发明轮子。

    【讨论】:

      猜你喜欢
      • 2014-04-08
      • 2017-08-21
      • 1970-01-01
      • 2021-05-29
      • 1970-01-01
      • 1970-01-01
      • 2011-05-20
      • 2020-09-15
      • 2013-10-24
      相关资源
      最近更新 更多