Ignite и Spring с несколькими загрузчиками классов

У меня есть система с Spring Cache, в ней несколько загрузчиков классов. На самом деле я использую ehcache, и он отлично работает:

@Component
public class ObjectRepository extends MongoRepository<Object> {
// -------------------------- OTHER METHODS --------------------------

    @Override
    @Cacheable(value = "object", key = "#p0+#p1.name")
    public Object get(String id, Class<? extends Object> clazz) {
        return super.get(id, clazz);
    }

    @Override
    @CacheEvict(value = "object", key = "#p0+#p1.name")
    public void remove(String id, Class<? extends Object> clazz) {
        super.remove(id, clazz);
    }

    @Override
    @CacheEvict(value = "object", key = "#p0+#p0.class.name")
    public void save(Object object) {
        super.save(object);
    }
}

Я пытаюсь изменить, чтобы зажечь:

@Bean
@SuppressWarnings("unchecked")
public CacheManager cacheManager() {
    SpringCacheManager springCacheManager = new SpringCacheManager();
    IgniteConfiguration igniteConfiguration = new IgniteConfiguration();
    igniteConfiguration.setPeerClassLoadingEnabled(true);
    igniteConfiguration.setIncludeEventTypes(org.apache.ignite.events.EventType.EVTS_TASK_EXECUTION);
    springCacheManager.setConfiguration(igniteConfiguration);
    return springCacheManager;
}   

Из-за нескольких загрузчиков классов я получаю сообщение об ошибке, когда я делаю objectRepository.get("1", com.test.ClassInClassLoader1.class), все работает нормально, но после того, как я делаю objectRepository.get("2", com.test.ClassInClassLoader2.class), я получаю сообщение об ошибке:

Caused by: class org.apache.ignite.IgniteCheckedException: Encountered incompatible class loaders for cache [class1=com.test.ClassInClassLoader2, class2=com.test.ClassInClassLoader1]
        at org.apache.ignite.internal.processors.cache.GridCacheDeploymentManager.registerClass(GridCacheDeploymentManager.java:656)
        at org.apache.ignite.internal.processors.cache.GridCacheDeploymentManager.registerClass(GridCacheDeploymentManager.java:601)
        at org.apache.ignite.internal.processors.cache.GridCacheDeploymentManager.registerClass(GridCacheDeploymentManager.java:590)
        at org.apache.ignite.internal.processors.cache.GridCacheDeploymentManager.registerClasses(GridCacheDeploymentManager.java:573)
        at org.apache.ignite.internal.processors.cache.GridCacheUtils.marshal(GridCacheUtils.java:950)
        at org.apache.ignite.internal.processors.cacheobject.IgniteCacheObjectProcessorImpl.marshal(IgniteCacheObjectProcessorImpl.java:94)
        at org.apache.ignite.internal.processors.cache.portable.CacheObjectPortableProcessorImpl.marshal(CacheObjectPortableProcessorImpl.java:727)
        at org.apache.ignite.internal.processors.cacheobject.IgniteCacheObjectProcessorImpl$UserCacheObjectImpl.prepareForCache(IgniteCacheObjectProcessorImpl.java:343)
        ... 186 more

Я пытался использовать DeploymentMode.ISOLATED и DeploymentMode.PRIVATE, но они не работают с igniteConfiguration.setPeerClassLoadingEnabled(true), поэтому мне приходится вручную регистрировать все классы, и я не нашел, как это сделать с помощью LocalDeploymentSpi, я пытался использовать igniteConfiguration.getDeploymentSpi(), но он нулевой, и когда я его создаю, как Ignite игнорирует классы там.


person Bruno    schedule 02.12.2015    source источник


Ответы (1)


Я бы не рекомендовал использовать загрузку одноранговых классов для классов модели предметной области. Вместо этого вы должны сделать все свои классы доступными в пути к классам всех узлов и отключить загрузку одноранговых классов (igniteConfiguration.setPeerClassLoadingEnabled(false)).

Также обратите внимание, что начиная с Ignite 1.5, который скоро будет выпущен, данные кеша по умолчанию будут храниться в двоичном формате, поэтому вам не придется развертывать классы на узлах сервера, даже если загрузка одноранговых классов отключена.

person Valentin Kulichenko    schedule 02.12.2015
comment
Я пытался использовать этот способ, но я получаю java.lang.ClassNotFoundException, потому что класс не находится в ClassLoader по умолчанию, и я не знаю, как зарегистрировать свои собственные классы, я пытался использовать igniteConfiguration.DeploymentSpi(), но он всегда равен нулю, и когда я создаю LocalDeploymentSpi и регистрирую классы в это я получаю ту же ошибку. Я не могу поместить классы в ClassPath, потому что ClassLoader и классы создаются в памяти во время выполнения. Если бы был способ зарегистрировать эти классы, я думаю, это сработало бы. - person Bruno; 03.12.2015
comment
@ Бруно, ты пытаешься вызвать метод DeploymentSpi.register(..) напрямую? Вы никогда не должны этого делать, потому что SPI — это подключаемые компоненты, которые должны использоваться внутренними компонентами Ignite. Также нет необходимости явно настраивать LocalDeploymentSpi, так как он используется по умолчанию и не имеет дополнительной настройки. Вместо этого вы можете попробовать использовать UriDeploymentSpi и динамически загружать классы из файловой системы или другого источника. - person Valentin Kulichenko; 03.12.2015
comment
@Bruno, кроме того, в Ignite 1.5 будут представлены двоичные объекты, которые будут использоваться в качестве формата по умолчанию для хранения данных в памяти. Этот формат поддерживает поиск полей без десериализации и, следовательно, вообще не требует наличия классов. Вы можете динамически создавать объекты любой структуры на лету и работать с ними. Похоже, эта функция может очень помочь вам в вашем случае использования. - person Valentin Kulichenko; 03.12.2015
comment
Пробовал дозвониться не получается. Как я могу использовать UriDeploymentSpi, если мои классы находятся в памяти? И я должен поместить этот класс в igniteConfiguration.setDeploymentSpi(...)? - person Bruno; 04.12.2015
comment
Я попытался использовать версию 1.5.1-RC1-SNAPSHOT из git и получил те же ошибки, какую конфигурацию мне нужно использовать? - person Bruno; 04.12.2015
comment
@ Бруно, похоже, двоичный формат не полностью поддерживается SpringCacheManager прямо сейчас. Я создал для этого тикет в Ignite JIRA: issues.apache.org/jira/browse/ ЗАЖИГАНИЕ-2095 - person Valentin Kulichenko; 08.12.2015
comment
Я буду следовать этому билету, а пока попробую использовать версию 1.4. Я не знаю, смогу ли я ждать слишком много. - person Bruno; 08.12.2015
comment
@Бруно, звучит хорошо. Я планирую исправить это в версии 1.5, поэтому она должна быть доступна к концу года. - person Valentin Kulichenko; 09.12.2015
comment
Хорошие новости @Valentin, так что я подожду эту версию, и когда ваш билет будет готов и зафиксирован, я протестирую версию на github. - person Bruno; 10.12.2015
comment
@Bruno, я только что понял, что добавление этого к SpringCacheManager не имеет особого смысла, потому что это потребует использования Ignite API и, следовательно, нарушит абстракцию. Я бы рекомендовал вам переключиться на Ignite API и использовать бинарный формат. По сути, он позволяет создавать динамические объекты и работать с ними вообще без классов, ни на сервере, ни на клиенте. Пожалуйста, взгляните на интерфейсы BinaryObject и BinaryObjectBuilder. - person Valentin Kulichenko; 12.12.2015
comment
У меня уже есть система с ehcache через Spring, я не могу напрямую использовать Ignite API. Тогда я попробую зарегистрировать классы в ignite, как я могу зарегистрировать класс в Ignite, если у меня есть ClassLoader и Class в памяти? Как видите, я попробовал LocalDeploymentSpi.register(..), и это не сработало, а другой UriDeploymentSpi использует каталог и файловую систему. - person Bruno; 12.12.2015
comment
@Bruno, если у вас есть загрузчик классов, который знает об этих классах, вы можете предоставить его Ignite через IgniteConfiguration.setClassLoader(). Это должно решить вашу проблему. - person Valentin Kulichenko; 13.12.2015
comment
У меня есть список загрузчиков классов, думаю, мне это не подходит. - person Bruno; 14.12.2015
comment
@Bruno, вы можете создать загрузчик классов-оболочек, который будет перебирать этот список, делегировать каждому из них и останавливаться, как только класс будет найден. Будет ли это работать? - person Valentin Kulichenko; 15.12.2015
comment
У меня была точно такая же идея, это то, что я делаю сейчас, но есть вероятность, что это не работает в моей системе. - person Bruno; 16.12.2015
comment
он работает с ClassLoader Wrapper, но у меня возникают другие проблемы stackoverflow.com/questions/34534251/ - person Bruno; 30.12.2015