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

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

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

功能需求

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

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

接口设计

 

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

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

?


1

2

3

4

5

6

7

8

9

10

11

/**

 * 是否可验证,实现了此接口的类,可以进行校验

 */

public interface Verifiable {

    /**

     * 校验,如果校验时不出现异常,就表示是OK的

     *

     * @throws RemoteException

     */

    void verify() throws RemoteException;

}

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

?


1

2

public interface RemoteObject extends Serializable, Remote {

}

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

代码实现

第一版代码实现,偶预想的非常简单,如何获取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都是各自的实现,不再有共同的基类。

经验总结

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

关于RMI:

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

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

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

时间: 2025-01-21 12:13:18

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

Javascript之旅——第八站:说说instanceof踩了一个坑

原文:Javascript之旅--第八站:说说instanceof踩了一个坑 前些天写js遇到了一个instanceof的坑,我们的页面中有一个iframe,我在index页面中计算得到了一个array,然后需要传递到Flight页面 这个嵌套的iframe中的一个函数(SearchFlight)中,作为防御性编程,我需要在SearchFlight函数中进行参数检测,也就是判断过来的参数一 定是Array类型.   一:抛出问题 举个例子,下面有两个页面. Index.html页面 1 <!DO

phpMyAdmin“无法载入mysql扩展,请检查PHP配置”的解决方法

phpMyAdmin"无法载入mysql扩展,请检查PHP配置"的解决方法 在配置了PHP的运行环境,并且安装了MySQl数据库之后,下面就可以学习下PHP如何与MySQL进行交互了. 既然MySQL是数据库,则必不可少的需要建立数据库.表.字段等操作(假象下我们使用ASP+ACCESS的情形),然而对于MySQL数据库而言,在我们默认安装时是没有可视化界面操作MySQl的,所以我们很多时候是借助phpMyAdmin来操作MySQL数据库的. 然而通过"PHP 5.2.3 i

7个产品经理/交互新人初入职场时踩过的坑

  前车之鉴后事之师,聪明的人可以从别人的错误中学到经验.这次特意邀请了七位迈入职场不久的产品经理.交互设计师同学,分享那些他们踩过的坑.话不多说,收获有多少,就看你有多聪明啦. 当从象牙塔走入职场,新人们除了兴奋和憧憬以外更多的还有紧张和迷茫:对庞大业务的不熟悉.对工作模式和规范的不了解.对同事和前辈的生疏,都是新人成长的必经之路.有些坑,需要我们亲自踩过才能有深刻的体会,但是前车之鉴后事之师,聪明的人一样可以从别人的错误中学到经验. 这次特意邀请了七位迈入职场不久的产品经理.交互设计师同学,

详解Bypass UAC过程中踩过的坑(第一部分)

本文讲的是详解Bypass UAC过程中踩过的坑(第一部分),我目前正在尝试对Chrome沙盒进行一些改进.而作为其中的一部分,我现在正在对我的沙盒攻击Surface 分析工具进行更新,因为我想衡量我对Chrome做的事情是否具有实际的安全性.但事实上当我在进行这一切时,我一直躲不开绕过UAC的麻烦,这就导致进程出现了问题.所以为了顺便演示下我以前在UAC绕过的博文中所讲的,我决定将这一切再来一次.当我完成这一切的时候,我将使用最新版本的NtObjectManager  Powershell模块

这篇必看:那些产品、交互新人初入职场踩过的坑

当从象牙塔走入职场,新人们除了兴奋和憧憬以外更多的还有紧张和迷茫:对庞大业务的不熟悉.对工作模式和规范的不了解.对同事和前辈的生疏,都是新人成长的必经之路.有些坑,需要我们亲自踩过才能有深刻的体会,但是前车之鉴后事之师,聪明的人一样可以从别人的错误中学到经验. 这次特意邀请了七位迈入职场不久的产品经理.交互设计师同学,分享那些他们踩过的坑.话不多说,收获有多少,就看你有多聪明啦. 交互设计师 鸿影 from 阿里巴巴 1. 无脑闷头执行 过程描述:接到需求的时候,对方描述了一个具体的解决方案,就

详解Bypass UAC 过程中踩过的坑(第二部分)

本文讲的是详解Bypass UAC 过程中踩过的坑(第二部分),在第1部分完成后,我们知道普通用户在拆分令牌管理登录中处理可以获得对升级进程的Terminate,QueryLimitedInformation 和  Synchronize进程访问权限的访问.这是由于正常的用户和管理员具有默认DACL,该默认DACL授予对同一桌面上所有令牌设置的当前登录会话的执行访问权限.我们接下来的问题是如何才能提升你的权限? 在我们拥有的3个访问权限中, Terminate 和 Synchronize 都不是

游戏服务器数据库踩过的坑

     在页游服务器这块很早之前一直没有认真考虑过,大部分是之前搭建好的,我只需要按照他原来的设计继续码代码就好了.      可是这次服务器重构的过程中,还是遇到了很多始料不及的问题.那么就按照踩过的坑,去一个个讲讲分析分析.      1:起初mysql的方案    起初的设计方案是这样,用一个RolePlayer 去做玩家数据的缓存,所有玩家的数据更新到RolePlayer中,定时十秒中更新到数据库.RolePlayer大概是这样一个设计       class RolePlayer 

说说云计算时代,运维人员会踩到哪些坑?

近期在ChinaUnix论坛有一场讨论,标题是--云计算时代:运维人员会踩到哪些坑? 整个讨论过程非常活跃,大概有50个答复,运维派这就给大家整理了一些讨论的优质内容分享给大家. 背景: 在云计算领域,运维人员就是这样的存在,小到一条短信,大到一次网上交易,只要和IT相关的业务就需要这些运维人员,没有他们在背后的支持,生活是会出大乱子的. 可是到了云计算时代,不少人说IT人要下岗了,是否真会如此呢?云计算的出现是否会使得整体行业对运维的需求萎缩了呢? 面对传统的几十台服务器时,运维人员还能手动处

win764位平台下,注册的shell扩展dll不起作用,如何解决?

问题描述 win764位平台下,注册的shell扩展dll不起作用,如何解决? win764位平台下,注册的shell扩展编译成64位dll经注册后可以成功注入到explorer进程,但是没有实际效果,如何解决? 解决方案 首先,你实现的所有的接口,是不是64bit的sdk提供的那些.另外,你确认你正确安装了你的扩展没有.你怎么确认它注入成功的. 解决方案二: https://code.msdn.microsoft.com/windowsapps/CppShellExtContextMenuHa