Hibernate Search + Spring + JPA + 2 веб-приложения — правильная конфигурация

Я долго и упорно ищу, и не могу найти окончательного ответа.

У меня есть 2 веб-приложения, работающих на одном экземпляре tomcat: /server и /ROOT

Я настроил Hibernate Search для одного из моих объектов, т.е. Products.

Эти объекты редактируются/добавляются /server и ищутся внешними пользователями на веб-сайте /ROOT.

во время обычных операций все работает как надо, редактирование сущностей на сервере приведет к тому, что эти изменения отразятся при выполнении поиска на внешнем интерфейсе.

однако по прошествии неопределенного времени или последовательности событий индекс больше не обновляется.

вот конфигурация для /server

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="jpaDataSource" />
    <property name="packagesToScan" value="com.foo" />
    <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                    <property name="generateDdl" value="true" />
                    <property name="showSql" value="true" />
            </bean>
    </property>
    <property name="jpaPropertyMap" ref="jpaPropertyMap" />
</bean>

<util:map id="jpaPropertyMap">
    <entry key="hibernate.search.default.directory_provider" value="filesystem" />
    <entry key="hibernate.search.default.indexBase" value="${lucene.index.folder}" />
</util:map>

а вот конфиг для /ROOT

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com.foo" />
    <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                    <property name="generateDdl" value="true" />
                    <property name="showSql" value="true" />
            </bean>
    </property>
    <property name="jpaPropertyMap" ref="jpaPropertyMap" />
</bean>

<util:map id="jpaPropertyMap">
    <entry key="hibernate.search.default.directory_provider" value="filesystem" />
    <entry key="hibernate.search.default.indexBase" value="${lucene.index.folder}" />
</util:map>

По сути идентичны.

и вот как настроен мой Entity через AspectJ ITD

privileged aspect Product_Search {

declare @type: Product: @Indexed;

declare @method :public Long Product.getId() : @DocumentId;
declare @method :public String Product.getTitle() : @Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO);
declare @method :public String Product.getSubTitle() : @Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO);
declare @method :public String Product.getAlternativeTitle() : @Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO);
declare @method :public String Product.getIdentifier() : @Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO);
declare @method :public String Product.getPrimaryCreators() : @Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO);
declare @method :public String Product.getSecondaryCreators() : @Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO);
declare @method :public String Product.getSubjectArea() : @Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO);
declare @method :public String Product.getPublisher() : @Field(index=Index.YES, analyze=Analyze.NO, store=Store.NO);
declare @method :public String Product.getTags() : @Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO);

При дальнейшем поиске я обнаружил главный/подчиненный DirectoryProvider

/server

    <util:map id="jpaPropertyMap">
    <entry key="hibernate.search.default.directory_provider" value="filesystem-master" />
    <entry key="hibernate.search.default.indexBase" value="${lucene.index.folder}/primary" />
    <entry key="hibernate.search.default.sourceBase" value="${lucene.index.folder}/master" />
    <entry key="hibernate.search.default.refresh" value="120" />
</util:map>

/ROOT

    <util:map id="jpaPropertyMap">
    <entry key="hibernate.search.default.directory_provider" value="filesystem-slave" />
    <entry key="hibernate.search.default.sourceBase" value="${lucene.index.folder}/master" />
    <entry key="hibernate.search.default.indexBase" value="${lucene.index.folder}/slave" />
    <entry key="hibernate.search.default.refresh" value="300" />
</util:map>

Это, казалось, работало до тех пор, пока ранее сегодня, когда по какой-то причине мой индекс не «сбросил» себя и содержал только элементы, которые были частью последнего импорта продукта. Я имею в виду, что в моей БД 10000 элементов, но если я сделал query = new MatchAllDocsQuery();, я получил только 15 (размер последнего импорта)

Это действительно сводит меня с ума.

На данный момент мне приходится сносить сайты, удалять индекс, запускать сервер, переиндексировать с помощью FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager()); fullTextEntityManager.createIndexer().startAndWait();

Дайте мне знать, если вам нужна дополнительная информация

Спасибо


person kabal    schedule 18.03.2013    source источник


Ответы (2)


Если изменения поступают только через приложение server и вы всегда хотите запускать server и ROOT на одном и том же компьютере, нет необходимости в установка ведущий/ведомый. Достаточно простой настройки файловой системы, однако вы должны убедиться, что в приложении ROOT указано _hibernate.search.indexing_strategy = manual_. В этом случае обновления индекса будут происходить только в том случае, если в приложении ROOT используется явный API индексирования.

вы включили ведение журнала? В логах есть что. Я думаю, что первый шаг — попытаться воспроизвести проблему надежным способом. Если вы просто говорите, что сначала это работает, но потом вдруг начинает давать сбои, это затрудняет поиск причины. Пробовали ли вы использовать автоматизированные нагрузочные тесты?

person Hardy    schedule 19.03.2013
comment
Только что случилось снова в производстве. Собираюсь переключить уровень журнала поиска в спящем режиме на DEBUG на следующие пару дней. - person kabal; 19.03.2013
comment
Если в ближайшем будущем с вероятностью 90 % мы будем редактировать и приложение ROOT, то рекомендуется ли установка ведущий/подчиненный? Нужно ли запускать master/slave с JMS? - person kabal; 19.03.2013
comment
Пока два приложения находятся на одном компьютере, вы можете использовать каталог файловой системы. Lucene имеет свой собственный механизм блокировки индекса, поэтому индекс не может быть поврежден (вот о чем этот эксклюзивный флаг в другом ответе). Master/Slave требуется, если у вас несколько машин. Вы также можете использовать JGroups для настройки, но рекомендуется использовать JMS. - person Hardy; 19.03.2013

Одна идея — возможно, вам следует перейти на неэксклюзивный режим (см. exclusive_index_use)

person Michail Nikolaev    schedule 18.03.2013