有一个RMI远程对象,在RMI中注册后,有多用户在同一时段内访问该服务。
要求是RMI服务端需要记录每一个访问用户的一些状态信息,在用户发了一个新的请求时,要求能够把每一个用户的状态信息明确区分出来,并返回一些状态信息给用户,类似于有状态的session bean。
当前采用的实现方法是用一个HashMap对象和一个自定义的数据model来实现,key为用户id,用户相关信息为model实例,可以实现基本要求。但是对于用户状态的管理比较复杂,需要自己实现对长时间无动作的用户状态信息进行清理,还有并发问题可能也是一个瓶颈。
现在的问题是有没有更好的在RMI服务段保持用户状态的解决方法?先说几种没有折中的情况:
1、必须RMI服务端保存用户的一些信息。
2、已经明白问题的实质在于多用户都是请求的同一个RMI服务端对象实例,这个实例中的属性也为大家共用,所以,一个用户的更改动作就会让其他用户也得到更该后的结果,如果有办法可以对不同的用户创建不同的服务对象实例,但是都是同一个服务注册名称,这样就不用自己维护HashMap中的状态了,每一个用户的状态可以维护在自己的对象实例中,直到用户断开连接该实例不再有引用被回收站回收为止。

解决方案 »

  1.   

    估计不行,其实不管什么服务器都有主线程和子线程,你要全部并行估计不行,
    在这种事务服务器中这中情况应该很常见,你是打算怎么实现java服务器吗?jboss?
    不然干脆使用ejb有状态会话bean
      

  2.   

    自己写了一个RMI的服务起动类,带main方法的可以自己运行的,运行rmiregister,然后运行这个类就可以启动RMI服务了。用RMI就是不想再做一个中间件的服务器了,实在没有其他的解决办法,就自己开始开一个线程维护用户状态信息了,只要用户状态的维护不影响主服务就行了。至于RMI服务交给JVM管理去吧。
      

  3.   

    实例化多个RMI服务对象,每个注册一个服务名,
    不同用户访问不同RMI服务名,
    每个服务中的方法同步,
    这样看看
      

  4.   

    基本同意楼主的想法,ejb是垃圾,自己做分布式更放心
      

  5.   

    不过在rmiregister,有更好的解决办法,就是自己启动一个 web服务器,最小型的那种,他们可以负责对象传输
      

  6.   

    回复人: cjhyahoo(野虎) ( ) 信誉:89 
    实例化多个RMI服务对象,每个注册一个服务名,
    不同用户访问不同RMI服务名,
    每个服务中的方法同步,
    这样看看这个设计方案更复杂了,要多起一个RMI服务来创建这些实例,然后把新创建的实例名称返回给客户端,客户端来访问新创建的实例,同时还要做好实例的回收工作,否则越开越多,又要设计一个实例池,不如通过直接访问一个RMI服务实例,然后,每来一个用户都要先调用一个方法来创建属于自己的信息对象,并记录到一个HashMap对象中去,每次用户请求动作时,都要传入自己的ID,通过ID去HashMap中查找属于自己的实例对象,每个用户的数据状态也记录在其中。只需要开个线程去维护这个HashMap就行了,做一个类似session中对象的实效机制,超时就可以把它remove掉。现在写好了一个用户状态管理类,开了一个线程专门维护已经存储在HashMap中的用户状态model对象,性能感觉还可以。先凑合用吧,现在最主要的是想找一个可以运行在jvm中自己管理不同请求的用户的信息状态的方法,就像有状态的会话bean一样,可以由容器管理,每个客户端只需要记住自己的sessionid就可以了。
      

  7.   

    这个东西自己实现了以后,发现老是出现
    10:51:21,406 INFO  [STDOUT] java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is: 
    java.net.SocketTimeoutException: Read timed out
    10:51:21,406 INFO  [STDOUT]  at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:274)
    10:51:21,406 INFO  [STDOUT]  at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:171)
    10:51:21,406 INFO  [STDOUT]  at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:94)
    10:51:21,406 INFO  [STDOUT]  at com.aeroinfo.rmi.control.TransferObject_Stub.openCube(Unknown Source)
    10:51:21,406 INFO  [STDOUT]  at com.aeroinfo.business.session.BusinessLogicSessionBean.OLAP_OpenCube(BusinessLogicSessionBean.java:8169)
    连接超时异常,查资料也没什么结果,谁知道怎么回事?谢谢.
      

  8.   

    还有一个很基本的问题,RMI我启动了一个服务,如果有多人同时请求,RMI是不是也是多线程的模式来响应的?我的服务类没有实现线程.
      

  9.   

    自己顶,没人知道rmi为什么超时么?
      

  10.   

    你是在做EJB服务器吗?你的问题没碰到过,会不会是绑定错误,建议还是自己启动一个WEB服务来负责传输对象,rmiregister经常有问题
      

  11.   

    好像是rmiregister的本身机制有点问题,我单独先开一个客户端,每一秒钟都请求一次RMI服务,这个服务很简单,就是请求一个字符串,让它一直保持连接。然后我开始做的那个通过sessionbean客户端请求就可以反复很顺利的请求到了,具体原因没搞清楚,我估计是当客户端在一段时间内没有请求,服务监听就被销毁了,然后再请求就没反应了。谁知道具体原因?
      

  12.   

    关于你说的Timeout我建议你调试程序的时候把防火墙关掉
      

  13.   

    我是在本级调试,所以不存在java虚拟机的安全权限和防火墙问题,这个可以排除,而且我的机器没有装防火墙;是注册激活对象的,但是事实就是服务器的connectiontimeout属性设置为15秒,如果15秒内没有任何一个连接发送动作请求,则所有的连接都将被销毁,然后再去连接这个服务时,不论哪一个都无法连接上,提示请求超时,其实就是该服务的监听没有了,但不影响在同一个rmiregistry中注册其他服务;如果单独开一个客户端,每隔15秒发送一个简单的请求,然后再用其他的客户端去连接,不管其他客户端间隔多长时间都可以顺利连接上去。查了一下资料,据说是rmiregistry本身实现有问题,不敢确定。