Статьи

Координация распределенного кэша EclipseLink JPA2


В более крупных системах, где обработка пользовательских запросов распределена, вам нужна какая-то координация кэша, в противном случае результаты могут быть неверными и / или пользовательский опыт будет плохим.
В
системе
Qualitas у меня есть внешнее веб-приложение Spring, которое отправляет сообщения AMQP брокеру, которые впоследствии выбираются по маршруту Apache Camel. У меня была проблема с кэшированием, потому что веб-приложение показывало старые данные. Чтобы исправить это, я решил использовать координацию распределенного кэша. Читайте ниже, чтобы узнать, как настроить и запустить координацию распределенного кэша с помощью EclipseLink JPA2. В конце статьи есть ссылка на рабочий пример.

Проблема и решение 

Итак, в моем случае веб-приложения и приложения интеграции используют один и тот же уровень доступа к данным (JPA2 и EclipseLink). Но пока маршрут Apache Camel обновлял статусы с каждым успешно выполненным шагом, веб-приложение все еще показывало старые статусы. Я решил использовать координацию кэша EclipseLink через JMS (RMI и CORBA также поддерживаются). В идеале я бы использовал AMQP вместо JMS, но все же JMS — лучший выбор, чем RMI 🙂

необходимое условие

Вам нужен JMS-брокер. Мы все знаем, что ActiveMQ — лучший вариант, поэтому скачайте его отсюда:
http://activemq.apache.org/download.html . Ниже я использовал настройки по умолчанию, поэтому все, что вам нужно сделать, это просто запустить брокер ActiveMQ.

Обновление persistence.xml

Мне пришлось добавить следующие 3 строки в мой файл persistence.xml:

<property name="eclipselink.cache.coordination.protocol" value="jms" />
<property name="eclipselink.cache.coordination.jms.topic" value="jms/Qualitas.EclipseLinkCacheTopic" />
<property name="eclipselink.cache.coordination.jms.factory" value="jms/Qualitas.EclipseLinkCacheConnectionFactory" />

И это было все. Почти все, как и тогда, мне приходилось настраивать JNDI-контексты как для веб-приложений (легкий), так и для Apache Camel (не такой простой).

Настройка контекста JNDI в Jetty

Я использую Jetty 7.6. Сначала мне нужно было создать файл WEB-INF / jetty-env.xml и определить мои ресурсы:
 

<?xml version="1.0"?>
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
 <New id="eclipseLinkCacheConnectionFactory" class="org.eclipse.jetty.plus.jndi.Resource">
  <Arg>jms/Qualitas.EclipseLinkCacheConnectionFactory</Arg>
  <Arg>
   <New class="org.apache.activemq.ActiveMQConnectionFactory">
    <Arg>nio://localhost:61616</Arg>
   </New>
  </Arg>
 </New>
 <New id="eclipseLinkCacheTopic" class="org.eclipse.jetty.plus.jndi.Resource">
  <Arg>jms/Qualitas.EclipseLinkCacheTopic</Arg>
  <Arg>
   <New class="org.apache.activemq.command.ActiveMQTopic">
    <Arg>Qualitas.EclipseLinkCacheTopic</Arg>
   </New>
  </Arg>
 </New>
</Configure>

  Затем мне пришлось добавить правильные сопоставления в мой файл web.xml:

<resource-ref>
 <res-ref-name>jms/Qualitas.EclipseLinkCacheConnectionFactory</res-ref-name>
 <res-type>javax.jms.QueueConnectionFactory</res-type>
 <res-auth>Container</res-auth>
</resource-ref>
<resource-env-ref>
 <resource-env-ref-name>jms/Qualitas.EclipseLinkCacheTopic</resource-env-ref-name>
 <resource-env-ref-type>javax.jms.Topic</resource-env-ref-type>
</resource-env-ref>

 Как и было обещано, настройка контекста JNDI в веб-приложении была простой. Чтобы убедиться, что это действительно работает, я запустил веб-приложение и открыл веб-консоль ActiveMQ. Я видел Qualitas.EclipseLinkCacheTopic и увидел одного активного потребителя.

Настройка JNDI в Apache Camel

Это заняло у меня некоторое время. Короче говоря, чтобы настроить JNDI и привязать к нему объекты, необходимо выполнить следующие действия:

1. Создать фабрику и тему. В своем конфигурационном файле Spring скопируйте и вставьте:

<amq:topic id="eclipseLinkCacheTopic" physicalName="Qualitas.EclipseLinkCacheTopic" />
<amq:connectionFactory id="eclipseLinkCacheConnectionFactory" brokerURL="nio://localhost:61616" /> 

2. Создайте контекст JNDI

. Сначала я хотел попробовать эталонную реализацию Sun (так как в Google есть много сайтов, ссылающихся на нее), но она больше не является частью JDK. Я также хотел попробовать Apache OpenEJB (так как я большой поклонник Apache Geronimo), но я был напуган всеми зависимостями, которые я видел в своей консоли. После некоторого поиска в Google я нашел легкую реализацию JNDI от … Jetty 🙂 Вот как настроить Spring JndiTemplate с реализацией JNDI в Jetty:

<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
 <property name="environment">
  <props>
   <prop key="java.naming.factory.initial">org.eclipse.jetty.jndi.InitialContextFactory</prop>
   <prop key="java.naming.factory.url.pkgs">org.eclipse.jetty.jndi</prop>
  </props>
 </property>
</bean>

 3. Связать фабрику соединений и тему с контекстом JNDI У

меня был каталог JNDI, затем мне пришлось связать фабрику соединений и тему с контекстом JNDI. Я написал довольно наивную реализацию с использованием автопроводки Spring (она была наивной, потому что она потерпела бы неудачу, когда было больше кандидатов на автопроводку, но для меня все было в порядке):

@Component
public class JndiBinder {
    @Autowired
    private JndiTemplate jndiTemplate;
    @Autowired
    private ConnectionFactory eclipseLinkCacheConnectionFactory;
    @Autowired
    private Topic eclipseLinkCacheTopic;
    @PostConstruct
    protected void bindEclipseLinkCacheResources() throws NamingException {
        jndiTemplate.bind("jms", new InitialContext());
        jndiTemplate.bind("jms/Qualitas.EclipseLinkCacheConnectionFactory", eclipseLinkCacheConnectionFactory);
        jndiTemplate.bind("jms/Qualitas.EclipseLinkCacheTopic", eclipseLinkCacheTopic);
    }
}

 Это все.

Запуск образца 

Когда я запустил Jetty и Apache Camel, в веб-консоли ActiveMQ я увидел двух пользователей, подключенных к Qualitas.EclipseLinkCacheTopic. И когда я загрузил пример процесса WS-BPEL в свое веб-приложение, я увидел состояние UPLOADED, но через несколько долей секунды я увидел состояние PROCESSING и через несколько секунд наконец увидел состояние INSTALLED. Все работало как шарм.

Если вы заинтересованы в полном исходном коде, Qualitas размещается как на googlecode: http://code.google.com/p/qualitas/source/browse/, так и на GitHub: https://github.com/lukasz-budnik/. QUALITAS, На данный момент он находится в основной ветке, но через неделю он станет частью релиза 0.0.5-SNAPSHOT и будет помечен как 0.0.5-SNAPSHOT. Этот тег, конечно, будет стабильным. Мастер ветки не всегда может быть стабильным. Прежде чем клонировать основную ветку, убедитесь, что Дженкинс из CouldBees сказал, что это безопасно: https://qualitas.ci.cloudbees.com/job/Qualitas/modules . Qualitas — это распределенная система, и для ее запуска необходимо настроить несколько вещей. Пожалуйста, обратитесь к http://code.google.com/p/qualitas/wiki/BuildingTheProject и http://code.google.com/p/qualitas/wiki/RunningTheProject вики-страницам.

Резюме

Любые комментарии приветствуются. Было бы неплохо иметь координацию кэша на основе AMQP в EclipseLink. Я думаю о добровольчестве для реализации этой функции 🙂