При работе в распределенной среде часто необходимо иметь согласованное локальное состояние для каждого узла сетки, которое повторно используется при выполнении различных заданий. Например, что, если нескольким заданиям для выполнения требуется пул соединений с базой данных — как они получают этот пул соединений, который будет инициализирован один раз, а затем повторно использован всеми заданиями, работающими на одном узле сетки? По сути, вы можете думать об этом как о одноэлементном сервисе для каждого узла сетки, но идея не ограничивается только сервисами, это может быть просто обычный Java-бин, содержащий некоторое состояние, которое будет совместно использоваться всеми заданиями, выполняющимися на одном узле сетки. ,
В
версиях GridGain 2.x и более ранних версиях этот подход обрабатывался с помощью
аннотации @GridUserResource для аннотирования полей в
GridTask или
Классы GridJob для указания одноэлементных бинов . Однако этот подход зависит от
GridDeploymentMode конфигурации , и для
ИЗОЛИРОВАННОЕ или
ЧАСТНОЕ режимов развертывания, ресурс может быть инициализирован несколько раз, один раз в
GridTask . Это заставляло пользователей использовать различные хаки в их логике и, как правило, было не очень удобно использовать.
Начиная с GridGain 3.0,
было представлено локальное хранилище GridNodeLocal для каждого узла сетки. Имя было заимствовано из
класса ThreadLocal в Java, потому что точно так же, как
ThreadLocal обеспечивает уникальное пространство для каждого потока в Java,
GridNodeLocalпредоставляет уникальное пространство для каждой сетки в GridGain.
GridNodeLocal реализует
интерфейс java.util.concurrent.ConcurrentMap и абсолютно не блокируется. Фактически, он просто расширяет
реализацию java.util.concurrent.ConcurrentHashMap и, следовательно, наследует все доступные там методы.
Вот пример того, как GridNodeLocal можно использовать для создания какого- то
отдельного пользовательского однотонного сервиса из простого задания GridGain:
final Grid grid = G.start(..); // Execute runnable job on some remote grid node. grid.run(BALANCE, new Runnable() { public void run() { GridNodeLocal<String, MySingleton> nodeLocal = grid.nodeLocal(); // 1. Check if f someone already created our singleton service. MySingleton service = nodeLocal.get("myservice"); if (service == null) { // 2. Create new singleton service. MySingleton other = nodeLocal.putIfAbsent("myservice", service = new MySingleton(..)); if (other != null) service = other; } // Perform operations with our singleton service. ... } });
С http://gridgain.blogspot.com/2011/08/clever-singletons-on-grid.html