IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

深入浅出jcr之16 该死的RMI,我们需要HTTP+简单RPC协议

求贤若渴, 礼贤下士 2011-12-18 22:02:59 累计浏览 2,750 次
本机暂存

     从这篇文章开始,ahuaxuan不再详细描述jackrabbit中的实现原理,而是把注意力放在jackrabbit中做的不好的地方,不敢说是批判,但是有些技术上的决策错误还是值得拿出来讨论讨论的。其中一个就是jackrabbit的客户端和jackrabbit server的通信方式--RMI。围绕这个问题我们可以展开一系列的讨论。

     本文分为几个部分

     1 为什么要抛弃RMI

     2 为什么要选择基于HTTP的RPC协议

     3 展望未来

     RMI这个东西原理之前很多人搞不清楚,因为sun的RMI实现源码虽说开源了,但是却很难找到,很久之前,ahuaxuan经过一番折腾之后终于找到了它的源代码,翻了一下源代码也发现了一些问题,其中有一些概念上的定义和一般的场景相混淆,叫人很难理解那些配置的含义。但是这篇文章并不是想要批判sun的RMI的实现,如果有需要,ahuaxuan会写另外一篇文章来精要的描述一下sun的RMI的实现。

     那么今天的主题是什么?是jackrabbit中RMI的使用方式。RMI可以作为有状态通信的手段。而jackrabbit中也是这样用的,这意味着什么呢?

     当我们通过RMI拿到一个node时,然后遍历这个node的10个属性,会发生什么事情?

     client会通过RMI发生11个remote call到jackrabbit中,虽然我们只拿了一个node,但是却发送了11个请求,如果我们拿10个node,需要上百次请求。这还只是一个线程发起的,如果客户端上多个线程同一个时间发起类似的请求,那么10个线程就会发生上千次操作。这个是他妈多夸张的事情啊。

     在我的眼里,jcr其实和数据库的实现原理是类似的,在数据库操作中,我们也会遇到1+n的问题,我们要做的就是要避免这样的问题。我们需要的是争取在客户端指定需要返回的properties,然后一次返回,这样才能比较靠谱,客户端10个线程即使同时发生请求,那么也只会发生10次请求,和前面的1000次请求相比,减少了990次remote call,带来的性能提高是无可置疑的。

     那么要实现这样的效果,我们还是需要选择一种通信方式,是RMI吗,不是?为什么不是,因为sun的RMI实现在客户端的connection pool和服务器端的thread pool都太简单了,不过本文不会详细介绍这个问题,我们跳过RMI,来选择其他的通信方式。

     不用RMI,那么要不就是自定义协议,理论上是没有任何问题的,自定义协议的好处的可控性较强,而且可以根据业务的特性有效的降低字节数。减少带宽的消耗。它的问题是什么呢?开发周期较长,那么我们是否可以使用现成的协议呢?

     当然没有问题,最便捷的方式就是使用http协议,在http协议之上构造自己简单的RPC协议,这个步骤很简单,虽然很简单,但是能不做最好不做,那么是否有现成的技术呢。有的,hessian.

     这里的hessian不只是hessian的序列化算法,也包括hessian包中rpc框架,当然它的框架有很大的一个缺点,那就是短连接,任何一个rpc请求返回之后 URLConnection就关闭了,新的RPC请求必须重新打开一个Connection,所以作为一个高并发的客户端,我们必须支持connection pool, 有现成的吗?? 有的,我们可以使用HTTPClient,呵呵,怎么做呢,稍微看一下代码,我们会发现我们只需要重新写一个InvocationHandler接口的实现就行了,怎么实现呢,直接参考HessianProxy就可以了。整体的实现较为简单,ahuaxuan不一一赘述。

     当然这个只是客户端的,服务器端需要重新封装一些接口,比如getNodesByIds(),可以通过Node的id集合批量的进行操作。接着服务器端的这些接口需要交给客户端,客户端利用动态代理技术创建这些接口的实现类,调用接口的方法的实现会生成RPC协议需要的参数,必然类名,方法名,参数,以及它们在binary中的位置,这样服务器拿到这个协议数据之后就可以寻找到对于的目标类,然后调用对应的方法(并传入客户端传来的参数),这一切都完美了。一切细节都被屏蔽了。客户端只需要拿到服务器端发布的接口就可以了,然后。。。。呵呵呵呵。

     虽然在改造的过程中会遇到一些小小的问题(包括hessian包的一些小bug),但是这些小小的绊脚石并不能阻碍我们前进的脚步。

     这样原来有状态的通信的方式改成了无状态的方式,而且HTTPClient的连接池配置更为丰富。更重要的是降低了很多很多很多的remote call. 性能提高也称为了必然。

     当然这个是最好的方式吗,当然不是,最终,我们的目的是直接基于TCP打造我们的RPC协议,而不是基于HTTP的RPC协议,毕竟HTTP会传输很多我们不需要的字节,直接使用mina或者netty是毕竟合适的选择。当然这些又是后话了。

     也许你会问jackrabbit为什么没有这样做的,我相信它会的,它最终会这样做的。

同分类推荐文章

  1. 等了十年的 Go 链式管道,终于来了:seq 让你像写 Scala 一样写 Go (2026-06-25 18:38:18)
  2. Go 实验特性详解 (2026-06-21 10:05:27)
  3. amd64 微架构级别对 Go 程序性能提升多少? (2026-06-21 09:38:49)

查看更多 后端 文章 →

建议继续学习

  1. SmartSprites - 命令行形式的CSS Sprites生成器 (累计阅读 123,894)
  2. Linux大棚版Thrift入门教程 (累计阅读 24,504)
  3. Java开发岗位面试题归类汇总 (累计阅读 22,155)
  4. android 开发入门 (累计阅读 19,527)
  5. 浅析http协议、cookies和session机制、浏览器缓存 (累计阅读 17,444)
  6. 从输入 URL 到页面加载完成的过程中都发生了什么事情? (累计阅读 15,932)
  7. libcurl的使用总结(二) (累计阅读 15,083)
  8. 使用python爬虫抓站的一些技巧总结:进阶篇 (累计阅读 13,299)
  9. 我的PHP,Python和Ruby之路 (累计阅读 13,146)
  10. HashMap解决hash冲突的方法 (累计阅读 12,652)