Рискну предположить, что среднестатистический читатель этой статьи с продуктом Apache Ignite не знаком. Хотя, возможно, слышал или даже читал статью на Хабре, в которой описывается один из возможных сценариев использования этого продукта. О принудительном использовании Ignite в качесте L2 кэша для Activiti я писал недавно. Возможно, узнав о том, что это написанный на Java open source продукт, позиционирующий себя как «высокопроизводительная, интегрированная и распределённая in-memory платформа для вычисления и обработки больших объёмов данных в реальном времени», обладающая, помимо прочего возможностью автоматического деплоймента вашего проекта на все ноды сложной топологии, вам захочется с ним познакомиться. Испытав такое желание, вы обнаружите, что Ignite документирован не то, чтобы совсем плохо, но и не очень хорошо. Есть туториал, кое-какой javadoc, но полного и целостного впечатления от ознакомления с этими источниками не возникает. В настоящей статье я попытаюсь восполнить этот пробел на основе собственного опыта познания Ignite, полученного преимущественно путём дебага. Возможно, в своих выводах и впечатлениях я буду не всегда прав, но таковы издержки метода. От читателя и тех, кто захочет повторить мой путь, требуется не так много, а именно знание Java 8 core, multithreading и Spring core.
В статье будет рассмотрен и препарирован пример класса «Hello World!» с использованием данной технологии.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
<property name="gridName" value="testGrid-client"/>
<property name="clientMode" value="true"/>
<property name="discoverySpi">
<bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
<property name="ipFinder">
<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder">
<property name="addresses">
<list>
<value>127.0.0.1:47500..47509</value>
</list>
</property>
</bean>
</property>
<property name="localAddress" value="localhost"/>
</bean>
</property>
<property name="communicationSpi">
<bean class="org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi">
<property name="localAddress" value="localhost"/>
</bean>
</property>
</bean>
</beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
<property name="gridName" value="testGrid-server"/>
<property name="clientMode" value="false"/>
<property name="discoverySpi">
<bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
<property name="ipFinder">
<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder">
<property name="addresses">
<list>
<value>127.0.0.1:47500..47509</value>
</list>
</property>
</bean>
</property>
<property name="localAddress" value="localhost"/>
</bean>
</property>
<property name="communicationSpi">
<bean class="org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi">
<property name="localAddress" value="localhost"/>
</bean>
</property>
</bean>
</beans>
@Configuration
public class IgniteProvider {
private Log log = LogFactory.getLog(IgniteCacheAdapter.class);
private final Ignite ignite;
private boolean started = false;
public IgniteProvider() {
try {
Ignition.ignite("testGrid-client");
started = true;
} catch (IgniteIllegalStateException e) {
log.debug("Using the Ignite instance that has been already started.");
}
if (started)
ignite = Ignition.ignite("testGrid-client");
else {
ignite = Ignition.start("ignite/example-hello.xml");
((TcpDiscoverySpi) ignite.configuration().getDiscoverySpi())
.getIpFinder()
.registerAddresses(Collections.singletonList(new InetSocketAddress("localhost", DFLT_PORT)));
}
}
public Ignite getIgnite() {
return ignite;
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {IgniteProvider.class})
public class IgniteHelloWorld {
@Autowired
private IgniteProvider igniteProvider;
@Test
public void sendHelloTest() {
Ignite ignite = igniteProvider.getIgnite();
while(true) {
try {
ignite.compute().broadcast(() -> System.out.println("Hello World!"));
Thread.sleep(1000);
}
catch (Exception ex) {}
}
}
}
Caused by: class org.apache.ignite.binary.BinaryInvalidTypeException: ru.kmorozov.ignite.test.IgniteHelloWorld
at org.apache.ignite.internal.binary.BinaryContext.descriptorForTypeId(BinaryContext.java:671)
at org.apache.ignite.internal.binary.BinaryUtils.doReadClass(BinaryUtils.java:1454)
at org.apache.ignite.internal.binary.BinaryUtils.doReadClass(BinaryUtils.java:1392)
at org.apache.ignite.internal.binary.BinaryReaderExImpl.readClass(BinaryReaderExImpl.java:369)
at org.apache.ignite.internal.binary.BinaryFieldAccessor$DefaultFinalClassAccessor.readFixedType(BinaryFieldAccessor.java:828)
at org.apache.ignite.internal.binary.BinaryFieldAccessor$DefaultFinalClassAccessor.read(BinaryFieldAccessor.java:639)
at org.apache.ignite.internal.binary.BinaryClassDescriptor.read(BinaryClassDescriptor.java:776)
at org.apache.ignite.internal.binary.BinaryReaderExImpl.deserialize(BinaryReaderExImpl.java:1481)
at org.apache.ignite.internal.binary.BinaryUtils.doReadObject(BinaryUtils.java:1608)
at org.apache.ignite.internal.binary.BinaryReaderExImpl.readObject(BinaryReaderExImpl.java:1123)
at org.apache.ignite.internal.processors.closure.GridClosureProcessor$C2V2.readBinary(GridClosureProcessor.java:2023)
at org.apache.ignite.internal.binary.BinaryClassDescriptor.read(BinaryClassDescriptor.java:766)
at org.apache.ignite.internal.binary.BinaryReaderExImpl.deserialize(BinaryReaderExImpl.java:1481)
at org.apache.ignite.internal.binary.GridBinaryMarshaller.deserialize(GridBinaryMarshaller.java:298)
at org.apache.ignite.internal.binary.BinaryMarshaller.unmarshal(BinaryMarshaller.java:109)
at org.apache.ignite.internal.processors.job.GridJobWorker.initialize(GridJobWorker.java:409)
... 9 more
Caused by: java.lang.ClassNotFoundException: ru.kmorozov.ignite.test.IgniteHelloWorld
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at org.apache.ignite.internal.util.IgniteUtils.forName(IgniteUtils.java:8350)
at org.apache.ignite.internal.MarshallerContextAdapter.getClass(MarshallerContextAdapter.java:185)
at org.apache.ignite.internal.binary.BinaryContext.descriptorForTypeId(BinaryContext.java:662)
... 24 more
<property name="peerClassLoadingEnabled" value="true"/>
К сожалению, не доступен сервер mySQL