TinyRMI---RMI的封装、扩展及踩到的坑的解决

在Tiny的并行计算中,引用了远程方法调用工程,就是这里说的TinyRMI,当时在写测试用例的时候,只是在单机进行了测试,一切安好,但是Dawn在使用时,在多机进行试用,结果就出现了问题,最后花了不下一人周,才解决了Dawn发现的问题,最终解决了问题,也发现了RMI中的一些坑。可能有的人已经走过了,有的人如果没有碰到,也可能会掉同样的坑,因此把它成文,以飨读者,避免上同样的当。

此文的形成离不开Dawn的深入测试与分析,在此表示深深感谢!

功能需求

期望对Jdk中的Rmi进行一定的封装提供以下特性:

  • 支持本地对象注册与注销
  • 支持远程对象注册与注销
  • 支持断线重连 由于网络故障,导致连接断开,在网络故障恢复之后,可以继续正常访问 由于RmiServerLocal停止,重新启动后,客户端注册的对象要继续可以正常访问 由于RmiServerRemote停止 ,重新启动后,客户端注册的对象需要重新注册
  • 支持对象校验 如果某些对象已经失效,服务器端可以把它从注册表去除,以避免别人拿到失效的对象

接口设计

可以看到RmiServer是继承了Serializable和Remote接口的一个接口,它提供了注册对象及取消注册对象的多个方法。当然也提供了一些辅助方法,看起来还是非常简单的。

另外还有一个辅助接口Verifiable,对于加入的远程对象,如果实现了此接口,则可以对其有效性进行验证,如果已经失效,将被自动从注册无中去除。

  1. /**
  2. * 是否可验证,实现了此接口的类,可以进行校验
  3. */
  4. public interface Verifiable {
  5. /**
  6. * 校验,如果校验时不出现异常,就表示是OK的
  7. *
  8. * @throws RemoteException
  9. */
  10. void verify() throws RemoteException;
  11. }

复制代码

当然,要加入到RmiServer中,也要有一定的约束,因此设定了接口RemoteObject

  1. public interface RemoteObject extends Serializable, Remote {
  2. }

复制代码

好的,至此为止,接口就算设计完了。 代码实现

第一版代码实现,偶预想的非常简单,如何获取Registry作为一个抽象方法由子类实现,其它都是针对Registry进行的操作,就放在抽象类中实现,分分钟写好,然后本地测试通过,洋洋自得中,却蒙蒙然不知犯下了严重的错误.....

在单机环境下,测试都是好的,不管是RMI自己的测试用例还是复用它的并行计算工程。

但是Dawn在使用的时候,采用了Linux机器两个物理机进行测试,问题出现了,错误信息如下:

  1. java.rmi.AccessException: Registry.Registry.bind disallowed; origin / 192.168.xxx.xxx is non-local host

复制代码

我们用物理的两台计算机进行测试,也有同样的问题。

于是Baidu、谷歌都用上了,查找了终于找到原因:

Registry只有本地的才可以对注册表进行修改,远程的只能用来查看。

于是把RmiServerLocal作为一个远程对象提供出来,让RmiServerRemote来调用,心想这样总可以了吧??但是还是不行,还是同样的问题。

仔细阅读JavaDoc文档和找到的一些材料,才理解了,这个bind过程只能在RmiServerLocal所在的机器中执行,即使是通过远程服务调用,它还是认为是在RmiServerRemote中调用的......这尼玛的坑爹了,这个RMI这么难用,设计者知道么?

这次改进,远程机注册的时候,只是添加到RmiServerLocal中的一个Queue中,然后在RmiServerLocal所在机器开一个扫描线程,来进行bind,unbind操作,这样总保证是在Local中执行了。

测试一下,确实OK了......还没有高兴半下,Dawn报过来,又出问题了。

Windows作Server,Linux做客户端的时候是OK的,但是Linux只要做服务器端就还是不行。

继续查找原因,看到资料说是因为Linux查找到IP与外部访问的IP不对应导致,需要修改/etc/hosts文件中的127.0.0.1到外部方面的IP地址。

修改之后,问题得到解决。

测试过程

初步跑通之后,接下来就是各种各样的测试及各种各样的问题。

由于采用了异步注册的关系,导致注册时间过后一小段时间才可以访问注册到的对象。

有对象访问冲突问题,等等等等,总之就是测了改,改了测,最后终于修正完毕,终于有一个稳定的可用的版本出现了。

最后,由于原来的设想的代码共用基本上没有复用的价值了,因此RmiServerLocal和RmiServerRemote都是各自的实现,不再有共同的基类。

经验总结

  • 测试用例的编写一定要充分覆盖。
  • 涉及到网络方面的测试,不能仅在本地测试通过就可以,一定要用真实的环境进行测试。
  • 不同的操作系统处理还是有一些不同,不要太迷信Java的一次编写到处使用,事实是到处可以跑,在大多数情况下也是可以正确的跑的,但是有些外部条件不同,可能会导致故障的出现。

关于RMI:

  • 如果是客户端仅调用服务器端提供的对象,那么是非常简单的。
  • 如果是客户端也要向服务器注册远程对象,那么就需要采用异步的方式,搞一下注册或注销队列。

代码本身不复杂,需要的同学,请自行查看源代码。

https://git.oschina.net/tinyframework/tiny/tree/master/framework/org.tinygroup.rmi

时间: 2024-10-10 06:33:34

TinyRMI---RMI的封装、扩展及踩到的坑的解决的相关文章

【转载】Fragment 全解析(1):那些年踩过的坑

http://www.jianshu.com/p/d9143a92ad94 Fragment系列文章:1.Fragment全解析系列(一):那些年踩过的坑2.Fragment全解析系列(二):正确的使用姿势3.Fragment之我的解决方案:Fragmentation 本篇主要介绍一些最常见的Fragment的坑以及官方Fragment库的那些自身的BUG,这些BUG在你深度使用时会遇到,比如Fragment嵌套时或者单Activity+多Fragment架构时遇到的坑.如果想看较为实用的技巧,

Fragment全解析系列(一):那些年踩过的坑

Fragment系列文章:1.Fragment全解析系列(一):那些年踩过的坑2.Fragment全解析系列(二):正确的使用姿势3.Fragment之我的解决方案:Fragmentation 本篇主要介绍一些最常见的Fragment的坑以及官方Fragment库的那些自身的BUG,这些BUG在你深度使用时会遇到,比如Fragment嵌套时或者单Activity+多Fragment架构时遇到的坑.如果想看较为实用的技巧,请直接看第二篇 Fragment是可以让你的app纵享丝滑的设计,如果你的a

我用select做多路复用踩到的坑

既然说是用select踩到的坑,那么就先直接贴一段使用select的代码上来瞅一下: bool SocketAction(int fd, const char* buf, size_t len, uint64_t milli_expire) { struct timeval tv; tv.tv_sec = milli_expire / 1000; tv.tv_usec = (milli_expire % 1000) * 1000; fd_set rd_set, wt_set; FD_ZERO(&

[转至云风的博客]谈谈陌陌争霸在数据库方面踩过的坑( Redis 篇)

« 谈谈陌陌争霸在数据库方面踩过的坑(芒果篇) | 返回首页 | linode 广告时间 » 谈谈陌陌争霸在数据库方面踩过的坑( Redis 篇) 注:陌陌争霸的数据库部分我没有参与具体设计,只是参与了一些讨论和提出一些意见.在出现问题的时候,也都是由肥龙.晓靖.Aply 同学判断研究解决的.所以我对 Redis 的判断大多也从他们的讨论中听来,加上自己的一些猜测,并没有去仔细阅读 Redis 文档和阅读 Redis 代码.虽然我们最终都解决了问题,但本文中说描述的技术细节还是很有可能与事实相悖

产品新人的我,曾在初创公司踩过这些坑

要踩够多少坑,才能成为一个合格的产品经理--我,是一枚硬件研发转型的产品经理.2016年进入一家智能硬件初创公司,至今一年半,没有成功的产品经历,只有踩过的一个又一个的坑. 一.公司背景介绍 公司是以技术起家,公司创始人是在学校孵化产品原型,在这一块有技术积累,参加创业大赛拿到风投后,快速推出产品上市.我加入时,公司注册半年,人数30左右,一代产品刚上市.公司除了一个产品总监,没有其它产品人员,产品总监也是研发转型. 坑点:对于产品新人,找个有人能带你的团队,事半功倍. 一定要重视这点,重要的事

ng-zorro-antd中踩过的坑

ng-zorro-antd中踩过的坑 前端项目中,我们经常会使用阿里开源的组件库:ant-design,其提供的组件已经足以满足多数的需求,拿来就能直接用,十分方便,当然了,有些公司会对组件库进行二次封装,改造成极具自家风格的产品. 在本系列的文章中,不谈高大上的东西,不深究底层源码,只分享一些项目中遇到的小问题. 表格(table) --师傅以为是组件库的bug,没想到-- 不知道正在阅读本文的读者有没有经历过: 在使用 <nz-table></nz-table> 的时候,删除表

vue03----生命周期、nextTick()、ref、filter、computed、vue中异步请求渲染问题(swiper不轮播)(在开发过程中遇到什么问题、踩过的坑)

### 1.vue的组件和实例都有生命周期,而且是一样的 生命周期:(组件从创建到销毁的过程) 创建 挂载 更新 销毁 组件到达某一个阶段就会自动触发某一些函数,这个函数就叫生命周期的钩子函数. 创建:组件创建的时候触发 beforeCreate created     组件刚创建的数据请求 挂载:创建完成挂载前后触发 beforeMount mounted     DOM的初始化操作 更新:数据发生改变的时候触发 beforeUpdate updated     数据的变化监听,尽量不要在这里

《C++之那些年踩过的坑(附录一)》

C++之那些年踩过的坑(附录一) 作者:刘俊延(Alinshans) 本系列文章针对我在写C++代码的过程中,尤其是做自己的项目时,踩过的各种坑.以此作为给自己的警惕. [版权声明]转载请注明原文来自:http://www.cnblogs.com/GodA/p/6639526.html 本来上个月就开始动笔了,直到现在才发出来,实在太多事情.可能有些小朋友不知道写这一篇随笔的起因,那么你可以看一下我之前写的. 上一篇的最后,我提到了一个问题:代码优化.并留了一个小测试:无符号数与有符号数的性能比

初学spring boot踩过的坑

一.搭建spring boot环境 maven工程 pom文件内容 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-