使用Spring RMI的巨大返回数据(RmiServiceExporter和RmiProxyFactoryBean)

时间:2019-02-13 07:13:23

标签: java spring rmi wireshark

似乎“ Spring Exporter”除了方法的值之外,还返回完整的类路径(文件的URI): wireshark screenshot

在此示例应用程序中,大约需要2KB。但实际上,它需要十个以上的8KB tcp片段,并导致大量的延迟。因此,我正在寻找一种解决方案,以防止传递这些额外的数据。

服务器端配置XML:

<beans xmlns="http://www.springframework.org/schema/beans" ...>
    <bean id="calculationBean" class="com.misc.poc.rmi.CalculationImpl"/>
    <bean class="org.springframework.remoting.rmi.RmiServiceExporter">
        <property name="service" ref="calculationBean"/>
        <property name="serviceInterface" value="com.misc.poc.rmi.Calculation"/>
        <property name="serviceName" value="CalculationService"/>
        <property name="servicePort" value="2000"/>
        <property name="registryPort" value="1999"/>
    </bean>
</beans>

客户端配置XML:

<beans xmlns="http://www.springframework.org/schema/beans" ...>
    <bean id="calculationBean" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
        <property name="serviceUrl" value="rmi://192.168.100.94:1999/CalculationService"/>
        <property name="serviceInterface" value="com.misc.poc.rmi.Calculation"/>
        <property name="lookupStubOnStartup" value="false"/>
        <property name="refreshStubOnConnectFailure" value="true"/>
    </bean>
</beans>

一些相关的类:

public interface Calculation {
    int cube(int number);
    Info greeting(String name);
}

public class Info implements Serializable {
    private String title;
    private String desc;

    public String getTitle() { return title; }
    public void setTitle(String title) { this.title = title; }
    public String getDesc() { return desc; }
    public void setDesc(String desc) { this.desc = desc; }
}

public class CalculationImpl implements Calculation {
    @Override
    public int cube(int number){
        return number*number*number;
    }

    @Override
    public Info greeting(String name) {
        Info res = new Info();
        res.setTitle(name);
        res.setDesc("Hello");
        return res;
    }
}

RMI ReturnData:

E   uüg@@7ÐðiøtC}þz8^j

¾¾〜Q¬íw_`2hå{{R4srcom.misc.poc.rmi.Info ^èù¶é¶××LdesctLjava / lang / String; Ltitleq〜tÉfile:/ home / user / masoud / jobs / huge-marshal / huge-marshal-app / web-server / target / server / WEB-INF / classes /文件:/ home / user / masoud / jobs / huge-marshal / huge-marshal-app / web-server / target / server / WEB -INF / lib / spring-security-config-3.2.5.RELEASE.jar文件:/ home / user / masoud / jobs / huge-marshal / huge-marshal-app / web-server / target / server / WEB-INF /lib/aspectjweaver-1.8.9.jar文件:/home/user/masoud/jobs/huge-marshal/huge-marshal-app/web-server/target/server/WEB-INF/lib/spring-web-4.3 .10.RELEASE.jar文件:/home/user/masoud/jobs/huge-marshal/huge-marshal-app/web-server/target/server/WEB-INF/lib/aopalliance-1.0.jar文件:/ home /user/masoud/jobs/huge-marshal/huge-marshal-app/web-server/target/server/WEB-INF/lib/common-1.0.jar文件:/ home / user / masoud / jobs / huge-marshal /huge-marshal-app/web-server/target/server/WEB-INF/lib/commons-logging-1.2.jar文件:/ home / user / masoud / jobs / huge-marshal / huge-marshal-app / web -服务器/目标/服务r / WEB-INF / lib / spring-security-taglibs-3.2.5.RELEASE.jar文件:/ home / user / masoud / jobs / huge-marshal / huge-marshal-app / web-server / target / server / WEB-INF / lib / spring-jdbc-4.3.10.RELEASE.jar文件:/ home / user / masoud / jobs / huge-marshal / huge-marshal-app / web-server / target / server / WEB-INF / lib / spring-core-4.3.10.RELEASE.jar文件:/ home / user / masoud / jobs / huge-marshal / huge-marshal-app / web-server / target / server / WEB-INF / lib / spring- security-core-3.2.5.RELEASE.jar文件:/ home / user / masoud / jobs / huge-marshal / huge-marshal-app / web-server / target / server / WEB-INF / lib / spring-expression- 4.3.10.RELEASE.jar文件:/home/user/masoud/jobs/huge-marshal/huge-marshal-app/web-server/target/server/WEB-INF/lib/spring-security-acl-3.2。 5.RELEASE.jar文件:/home/user/masoud/jobs/huge-marshal/huge-marshal-app/web-server/target/server/WEB-INF/lib/spring-context-4.3.10.RELEASE。 jar文件:/home/user/masoud/jobs/huge-marshal/huge-marshal-app/web-server/target/server/WEB-INF/lib/spring-beans-4.3.10.RELEASE.jar文件:/主页/用户/ masoud /工作/巨大的火星hal / huge-marshal-app / web-server / target / server / WEB-INF / lib / spring-security-web-3.2.5.RELEASE.jar文件:/ home / user / masoud / jobs / huge-marshal / huge-marshal-app /网络服务器/目标/服务器/WEB-INF/lib/spring-tx-4.3.10.RELEASE.jar文件:/ home / user / masoud / jobs / huge-marshal / huge-marshal- app / web-server / target / server / WEB-INF / lib / spring-aop-4.3.10.RELEASE.jarxptHellotGholi

1 个答案:

答案 0 :(得分:0)

我的理解是,此JAR列表在RMI响应中作为“类注释”发送。
我发现使用https://github.com/NickstaDB/SerializationDumper上的SerializationDumper工具。
(提示:我必须使用dd conv=swab <data.orig >data.swapped从Wireshark的转储中交换字节顺序,以便将其馈送到SerializationDumper -r。)

      ....
      classAnnotations
        TC_STRING - 0x74
          newHandle 0x00 7e 00 01
          Length - 21685 - 0x54 b5
          Value - file:/app/my-rmi-server-app.jar file:/tmp/cache/repository/org/springframework/boot/spring-boot-starter-web/2.1.4.RELEASE/spring-boot-starter-web-2.1.4.RELEASE.jar file:/tmp/maven/repository/org/springframework/boot/spring-boot-starter/2.1.4.RELEASE/spring-boot-starter-2.1.4.RELEASE.jar ...

我不是RMI专家,但是对我来说,这还不是很清楚,RMI服务器上的这些路径对显然无法访问这些路径的RMI客户端有什么用?!?

无论如何,此类注释值是在https://github.com/openjdk/jdk/blob/master/src/java.rmi/share/classes/sun/rmi/server/LoaderHandler.java#L194中生成的。
该算法利用所谓的类/代码库加载器来确定该值必须是什么。
就我而言,我使用Spring Boot Thin Launcher打包和运行我的应用程序,因此可能会对这种算法产生影响。

我发现总是发送 empty 类注释的方法是用我自己的方法覆盖默认的RMIClassLoaderSpi

package my.app;

import java.net.MalformedURLException;
import java.rmi.server.RMIClassLoader;
import java.rmi.server.RMIClassLoaderSpi;

public class LeanRMIClassLoaderSpi extends RMIClassLoaderSpi {
    private final RMIClassLoaderSpi delegate;

    public LeanRMIClassLoaderSpi() {
        this.delegate = RMIClassLoader.getDefaultProviderInstance();
    }

    @Override
    public Class<?> loadClass(String codebase, String name,
                              ClassLoader defaultLoader) throws MalformedURLException,
            ClassNotFoundException {
        return delegate.loadClass(codebase, name, defaultLoader);
    }

    @Override
    public Class<?> loadProxyClass(String codebase, String[] interfaces,
                                   ClassLoader defaultLoader) throws MalformedURLException,
            ClassNotFoundException {
        return delegate.loadProxyClass(codebase, interfaces, defaultLoader);
    }

    @Override
    public ClassLoader getClassLoader(String codebase)
            throws MalformedURLException {
        return delegate.getClassLoader(codebase);
    }

    @Override
    public String getClassAnnotation(Class<?> cl) {
        return null;
    }
}

必须将Java系统属性java.rmi.server.RMIClassLoaderSpi设置为my.app.LeanRMIClassLoaderSpihttps://github.com/openjdk/jdk/blob/master/src/java.rmi/share/classes/java/rmi/server/RMIClassLoader.java中的代码才能将其提取。

而且,您的RMI流量已大大减少-在我看来,该应用程序仍然可以正常工作。