JGroups(2.6.9-GA)使用RpcDispatcher来调用callRemoteMethods等类似的一系列函数来实现远程调用,并且推荐使用MethodCall作为远程调用的函数信息,MethodCall类包装了包括函数名,函数参数及其类型等信息。MethodCall类部分代码如下:
RPC调用端通过序列化MethodCall来传输MethodCall实例,远程的服务器端通过反序列化得到MethodCall实例,之后利用反射技术在预先设定的ServerObject类上查找匹配的函数并利用反射技术调用该方法得到返回结果。
JGroups查找匹配的函数时提供了多种选择,并且通过MethodCall的属性mode设定。这些模式包括:
说明:1.OLD模式:检查函数名与函数参数个数;
2.METHOD模式:此模式同ID模式,先通过ID模式找到Method,并设置MethodCall的method属性;
3.TYPES模式:检查函数名,函数参数个数,并且通过Class.isAssignableFrom(Class clazz)判断是否是匹配类型。
4.ID模式:通过函数ID来查找匹配的函数。
默认的查找方式是OLD,其实现方式是: ,也就是说只检查函数名以及参数个数。这就会导致匹配出现问题。
函数查找模式的设定是通过不同的构造函数类确定的。如:
如果我们在使用MethodCall时并没有设定函数查找模式而使用默认的模式时,那么我们的远程的ServerObject类就不能有参数个数相同而参数类型不同的重载函数。如果出现这种情况的话,MethodCall会找到最先“匹配”到的函数,而未必是我们想调用的函数。如下面两个函数:
,调用 并不能确定能调用ServerObject的 方法。因为它使用的TYPES的查找模式。这种模式检查函数名,参数个数之后用如下的语句判断函数参数类型是否匹配。那么任何Object的子类都是可以复制给万能的Object类型的。
解决办法:1.设定函数匹配模式。
2.对与OLD模式,ServerObject中避免出现函数参数个数相同而类型不同的函数重载。
3.对于TYPES模式,ServerObject中避免出现函数的参数个数相同,类型不同但是有“父子”关系的函数重载。
4.对于SIGNATURE模式,显示通过signature获取参数类型,进而又用TYPES模式去匹配,此模式下同TYPES模式。
5.对于ID模式,需要同步两边的函数ID?。。。
代价最小的修改应该就是通过不同的构造函数去设定函数模式。经上面的讨论在JGroups-2.6.9-GA中就没有精确匹配的办法,除非自己改造ServerObject的函数,不能出现1,2,3,4中的情况。但是此方法代价太大,涉及到应用逻辑部分代码都需要修改。还有就是降低版本了,使用2.6.1版本的TYPES模式是可行的,其他的待考证。升级不靠谱,至少2.9.0以及2.10.0两个版本的存在同样的问题,其他的待考证。