Огромные возвращаемые данные с использованием Spring RMI (RmiServiceExporter и RmiProxyFactoryBean) - PullRequest
0 голосов
/ 13 февраля 2019

Похоже, что Spring Exporter возвращает полный путь к классу (URIs файлов), кроме значения метода: снимок экрана wireshark

В этом примере приложения требуется около 2 КБ.Но в действительности он занимает более десяти 8-килобайтных 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:

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 / огромный маршал / огромный маршал-приложение / веб-сервер / цель / сервер / WEB-INF / классы / файл: / 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 / огромный-маршал / огромный-marshal-app / web-сервер / target / server / WEB-INF / lib / spring-web-4.3.10.RELEASE.jar файл: / home / user / masoud / jobs / огромный-маршал / огромный-маршал-приложение/web-server/target/server/WEB-INF/lib/aopalliance-1.0.jar файл: / home / user / masoud / jobs / огромный маршал / huфайл ge-marshal-app / web-сервер / target / server / WEB-INF / lib / common-1.0.jar файл: / home / user / masoud / jobs / огромный маршал / приложение-огромный маршал / веб-сервер /Целевой / сервер / WEB-INF / lib / commons-logging-1.2.jar файл: / home / пользователь / masoud / jobs / огромный маршал / огромный маршал-приложение / веб-сервер / целевой / сервер / WEB-INF /Файл lib / spring-security-taglibs-3.2.5.RELEASE.jar: / home / пользователь / masoud / jobs / огромный маршал / огромный маршал-приложение / веб-сервер / цель / сервер / WEB-INF / lib /Файл spring-jdbc-4.3.10.RELEASE.jar: / home / пользователь / masoud / jobs / огромный маршал / огромный маршал-приложение / веб-сервер / целевой сервер / 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 file: / Главная / пользователь / Масуд / работаs / огромный-маршал / огромное-маршал-приложение / веб-сервер / цель / сервер / WEB-INF / lib / spring-context-4.3.10.RELEASE.jar файл: / home / пользователь / masoud / jobs / large-Маршал / огромный-маршал-приложение / веб-сервер / целевой / сервер / WEB-INF / lib / spring-beans-4.3.10.RELEASE.jar файл: / home / user / masoud / jobs / огромный маршал / огромный-Маршал-приложение / веб-сервер / целевой / сервер / WEB-INF / lib / spring-security-web-3.2.5.RELEASE.jar файл: / home / user / masoud / jobs / огромный-маршал / огромный-маршал-файл app / web-сервера / target / server / WEB-INF / lib / spring-tx-4.3.10.RELEASE.jar: / home / user / masoud / jobs / огромный маршал / огромный маршал-приложение / веб-сайтсервер / цель / сервер / WEB-INF / Библиотека / весенне-AOP-4.3.10.RELEASE.jarxptHellotGholi

1 Ответ

0 голосов
/ 15 апреля 2019

Насколько я понимаю, этот список JAR-файлов отправляется как "аннотация класса" в ответе RMI.
Я обнаружил, что с помощью инструмента SerializationDumper, доступного в https://github.com/NickstaDB/SerializationDumper.
(Совет: у меня былпоменять порядок байтов в дампе из Wireshark, используя dd conv=swab <data.orig >data.swapped, чтобы передать его 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 для упаковки и запуска моего приложения, так что это, вероятно, влияет на этот алгоритм.

Способ, который я нашел, всегда отправляет пусто аннотация класса, переопределяет значение по умолчанию 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.LeanRMIClassLoaderSpi, чтобы код в https://github.com/openjdk/jdk/blob/master/src/java.rmi/share/classes/java/rmi/server/RMIClassLoader.java можно было выбратьэто.

И, вуаля, ваш трафик RMI значительно сократился - и приложение все еще работало просто отлично в моем случае.

...