Всем привет! Решил поделиться интересными знаниями. Что такое GEMFIRE? Одним словом, это кэш. GEMFIRE предназначен для Java, C# и C++ разработчиков. Т.к. я Java программист, то использую для описания свой язык ))). Работаю я с GEMFIRE всего месяц, поэтому заранее извиняюсь за возможные ошибки (мне просто нравится писать).
Если смотреть с java позиции, GEMFIRE – это Framework, если со стороны других языков – не знаю ))). Представьте себе следующий task: у вас есть база данных, в ней много таблиц, но объекты, которые вам нужны в коде не имеют аналога-таблицы в базе (хотелось бы их кэшировать в виде объектов). Не надо размышлять по поводу не очень хорошей архитектуры – это просто пример. Т.к. необходимая сущность размазана по нескольким таблицам базы – вы будете получать join данные и инициализировать ими объекты. Предположим, получился очень длинный join, и данных в базе не мало, например 13 000 000 строк в каждой таблице. Выполнять все время join не очень хорошо. Тут начинает работать GEMFIRE. Вот еще один пример использования: у вас очень много приложений, которые используют одну и ту же базу, а вы хотите сделать для них общий кэш (он будет поддерживать транзакции, OQL – аналог SQL, Continues Query – выполняем select и если в другой транзакции произойдет изменение записи, соответствующей этому select-у, то последний будет извещен об изменении). Еще один пример: вы вообще не хотите поддерживать базу данных, а использовать только кэш, иными словами, ORM теряет свой смысл. Цель статьи – рассказать как можно все настроить и начать использовать. Буду приводить куски кода, xml конфигурации – будет интересно!
GEMFIRE – не opensource, нужно платить деньги (((. Но для программистов имеется dev лицензия. Создателем является компания GEMSTONE (www.gemstone.com). Сперва нам нужно скачать сам GEMFIRE и tool для просмотра его работы и статистик. Заходим на http://download.gemstone.com, берем там GemFire Enterprise 6.0 Download и GFMon 2.0.1 Download. Для С# и С++ разработчиков нужно также скачать GemFire Enterprise Native Client 3.0.0.2 Download. Сразу отмечу, Java поддерживается получше, так этот язык имеет прямой API к GEMFIRE. GemFire Visual Statistics Display Download и DataBrowser 1.1.1 Download также очень полезные tools. Установите себе GEMFIRE, все правила по установке находятся в файле INSTALL.txt. Тоже самое с GFMon. Советую в “Path” вашей OS сразу добавить путь к “GemFire601\bin”. Самая основная команда – cacheserver. Выполнив ее, Вы стартуете сервер кэша.
Об архитектуре.
Из выше сказанного понятно, что GEMFIRE стартует как сервер, существует два типа (replicated и partitioned). К GEMFIRE серверу имеют доступ только GEMFIRE клиенты (ну, еще и сервер может получить доступ к серверу, но так делать не надо). Есть такое понятие Distributed System – это кластер из нескольких GEMFIRE серверов. Т.е. если у нас 3 кластера (2 сервера в первом, 1 во втором, 5 в третьем), то у нас 3 Distributed Systems. Бегло отмечу, что достаточно запустить один сервер на одной машине, и другой сервер с такой же конфигурацией на другой машине, чтобы они смогли опознать друг друга и вступить в кластер (Distributed System). Если вы отключите сеть, то у Вас не получится запустить GEMFIRE (вот такая хитрая штука). Теперь бегло о клиенте, клиенты берут данные с серверов, клиента можно сравнить с http session, как только закончилась сессия – все данные на клиенте пропали, а точнее пропал клиент. Не надо сильно задумываться над выше сказанным, на примерах все будет clear.
О типах серверов.
Создадим пустой директорий на диске D, назовем его “gemfire_test”. Будем складывать туда ниже перечисленные xml файлы. Создадим в нем следующий replicated.xml файл (это replicated сервер):
<cache> <cache-server port="40405”/> <region name="root"> <region-attributes/> <region name="exampleRegion"> <region-attributes data-policy="replicate"/> </region> </region> </cache>Поясню основной тег <cache-server port="40405” />. Очевидно данный сервер стартует на порте 40405. Обратите внимание на теги region, они имеют вложенную структуру. Что такое регионы? Говоря очень просто, это аналоги таблиц в базе данных. В регионы можно записывать объекты под определенными ключами, при попытке записать новый объект под уже имеющимся в регионе ключом, происходит update данной записи. Зачем нужна вложенная структура регионов? Если мы попытаемся запустить разные сервера (с разной конфигурацией регионов (но одинаковыми именами), то при старте последнего сервера появится exception). Иными словами вложенность регионов дает нам возможность создать namespace. Можно общие для всех внутренних регионов данные записывать в общий родительский регион. В нашем примере имеется следующая иерархия: “/root/exampleRegion”. Каждый регион обязан иметь <region-attributes/>, даже пустой, этим тегом мы и характеризуем принадлежность данной конфигурации к серверу или клиенту (иными словами, конфигурация клиента будет очень похожей). Основной момент в конфигурации: data-policy="replicate". Это означает, что мы создали сервер, типа replicated. Поговорим о типах серверов: replicated, partitioned. У каждого свои преимущества. Начнем с replicated. Данный сервер не подразумевает создание кластера, хотя это возможно, но нет в этом необходимости. Это самый обыкновенный сервер, который хранит все объекты на одной VM. Если мы запустим еще такой же сервер на другой машине, то слово replicated говорит само за себя, в этом случае два сервера будут просто дублировать объекты. Т.е. если один клиент пытается положить объект на сервер 1, то такой же объект пойдет и на сервер 2. GEMFIRE документация советует использовать только один такой сервер. Partitioned сервер – более сложен по природе. Он подразумевает кластер, т.е. мы стартуем 10 серверов с одинаковой partitioned конфигурацией, тем самым создаем кластер. Если клиент попытается положить на сервер 1 объект, то не факт, что данные попадут именно на этот сервер, может сервер 3 принять или любой другой. Результат: снижение нагрузки на используемую память. Предположим обратную задачу: клиент попытается забрать с сервера 1 объект под клучем “а”, но физически данный объект лежит на сервере 2. Клиенту даже не нужно знать эту физику, сервер 1 успешно ответит правильным результатом. Выше было сказано про Partitioned сервер, взглянем на конфигурацию partitioned.xml:
<cache> <cache-server port="40405”/> <region name="root"> <region-attributes/> <region name="exampleRegion"> <region-attributes> <partition-attributes redundant-copies="1" /> </region-attributes> </region> </region> </cache>Похожая конфигурация. Отмечу только атрибут redundant-copies="1". Предположим, что один из серверов в кластере упал, тем самым появляется опасность в целом для всей системы от одной ошибки. Этот атрибут создает копию всех объектов на partitioned сервере и в случае срыва сервера, подключает эту копию. Разумеется, для этого требуется дополнительная память. Если мы установим его в “0”, то при специальной остановке сервера 1, количество объектов в кластере будет уменьшаться на количество существовавших некогда объектов на сервере 1. Если попробовать указать атрибут replicated в конфигурацию partitioned сервера, то, разумеется, у нас ничего не получится, при старте сервера получим исключение. Это две исключающие друг друга вещи! Рассмотрим клиента. Посмотрим на конфигурацию клиентов. Клиент, в общем, ничем не отличается от сервера. Создаем еще один файл client.xml.
<cache> <pool name="client"> <server host="localhost" port="40405" /> </pool> <region-attributes id="clientAttributes" pool-name="client" scope="local" /> <region name="root"> <region-attributes scope="local" /> <region name="exampleRegion"> <region-attributes refid="clientAttributes" /> </region> </region> </cache>Сперва, отмечу возможность указывать ссылки на атрибуты регионов. Например: refid="clientAttributes". У клиента атрибут scope имеет значение local. Имеется конфигурация pool-name="client", которая указывает на пул соединений с сервером. Конфигурация самого пула очевидна. Начинаем старт серверов. Заходим в директорий “gemfire_test”. Выполняем команду: "cacheserver start cache-xml-file=replicated.xml –J-Xmx128m –J-Xms128m" для старта replicated сервера или "cacheserver start cache-xml-file=partitioned.xml –J-Xmx128m –J-Xms128m" для старта partitioned сервера (можем выполнить последнюю команду на нескольких машинах в локальной сети для создания кластера). Перед тем как выполнить запуск клиента, нужно убедиться, что сервер запущен правильно и регионы установлены. Этим и займемся. Вспомним, что мы установили GFMon. Этот tool видит все запущенные сервера и клиенты в определенной Distributed System. Перед запуском нужно выпонить команду, agent start, эта команда стартует RMI сервис, который и умеет все обнаруживать в сети. По умолчанию этот сервис использует порт 1099, если у вас он занят, установите при запуске агента другой порт (или, возможно, закройте eclipse ))), я обычно использую spring rmi и порт по умолчанию). После успешного старта агента выполните gfmon.bat. Откроется monitor tool, нажимаете кнопку “Connect” и изучайте свои сервера глубже. У нас есть в сети сервер (один из двух типов). Настало время запустить клиента. Разумеется без java кода не обойтись.
package com.test; import java.util.Properties; import com.gemstone.gemfire.cache.Cache; import com.gemstone.gemfire.cache.CacheFactory; import com.gemstone.gemfire.cache.Region; import com.gemstone.gemfire.distributed.DistributedSystem; public class TestGF { public static void main(String[] args) { Properties props = new Properties(); // Имя клиента, можно видеть в мониторе props.setProperty("name", "TestPut"); // Задание пути к конфигурации клиента props.setProperty("cache-xml-file", "client.xml"); // клиент должен работать standalone, вне distributed system // установите для этого mcast-port props.setProperty("mcast-port", "0"); DistributedSystem ds = DistributedSystem.connect(props); // Создаем локальный кэш Cache gfCache = CacheFactory.create(ds); // Получаем регион Regionregion = gfCache .getRegion("root/exampleRegion"); for (int i = 0; i region = gfCache .getRegion("root/exampleRegion"); for (int i = 0; i После запуска клиента, а можно и во время работы, загляните в монитор. Вы увидите, что данные записались в регион, что их 100. В момент работы клиента, можно заметить в правом верхнем углу количество текущих клиентов. Если бы мы не установили mcast-port в программе, то увидели бы немного подозрительную картину (в мониторе было бы 2 сервера и один клиент), повторюсь, клиенты должны запускаться из вне distributed system (советует GEMFIRE док). Вместо создание properties в коде, можно было бы создать файл gemfire.properties в корне проекта и указать их там. Обязательно отмечу распространенную ошибку, на которой часто попадался. В одной виртуальной машине должен существовать только один объект gfCache. Поэтому реализуйте себе singleton и забудьте о проблеме раз и навсегда. Это было очень короткое знакомство. Если будет интерес с Ваших сторон, то напишу подробнее.
Релоцировались? Теперь вы можете комментировать без верификации аккаунта.