Распределить секционированный IgniteCache на выбранных узлах только по развернутой службе.

Я запускаю кластер Apache Ignite с различными узлами, которые предоставляют услуги. Каждому узлу назначается определенная группа услуг (настраиваемые атрибуты узла), описывающая услугу, предоставляемую этим узлом, например. Авторизация, Оплата, ...

Некоторые из этих сервисов используют Ignite Cache, но я хочу, чтобы эти специфичные для сервиса кэши были развернуты только на связанных сервисных узлах. Итак, я добавляю фильтр узла в свою конфигурацию кеша:

// configuration with custom attribute is provided at node start up
IgniteConfiguration nodeConfig = new IgniteConfiguration();
Map<String,String> nodeAttributes = Collections.singletonMap("role", "MyService");
nodeConfig.setUserAttributes(nodeAttributes);

CacheConfiguration cfg = new CacheConfiguration<>("MyServiceCache");
cfg.setNodeFilter((node) -> node.attribute("role") == nodeConfig .getUserAttributes().get("role"));

Развертывание кеша работает должным образом (по крайней мере, ошибки не отображаются). Однако, когда я добавляю 2-й узел, который предоставляет ту же услугу (по причинам масштабирования), отображается запись в журнале:

No server nodes found for cache client: MyServiceCache

Как только я останавливаю 2-й узел, появляется другое сообщение журнала:

[17:26:29] Topology snapshot [ver=9, servers=1, clients=0, CPUs=4, heap=1.7GB]
[17:26:29] All server nodes for the following caches have left the cluster: 'MyServiceCache'
[17:26:29] Must have server nodes for caches to operate.

Насколько я понимаю, 1-й узел все еще должен обслуживать службу и кеш. Так что эти сообщения не имеют для меня особого смысла. Может кто-нибудь уточнить, пожалуйста?

Вот конкретный пример:

  • Запустите MyService.java дважды или более
  • Остановить 1-й узел
  • Смотреть вывод журнала 2-го узла

NodeConfig.java

public class NodeConfig {

    public static IgniteConfiguration myServiceNode()
    {
        IgniteConfiguration nodeConfig = new IgniteConfiguration();
        Map<String,String> nodeAttributes = Collections.singletonMap("role", "myService");
        nodeConfig.setUserAttributes(nodeAttributes);
        return nodeConfig;
    }

}

CacheConfig.java

public class CacheConfig {

    public static CacheConfiguration<Long, String> myServiceCache() {

        CacheConfiguration<Long, String> cfg = new CacheConfiguration<>("MyServiceCache");

        cfg.setBackups(2);

        cfg.setNodeFilter((node) -> node.attribute("role") == NodeConfig.myServiceNode().getUserAttributes().get("role"));

        return cfg;
    }

}

MyService.java

public class MyService implements Service {

    @IgniteInstanceResource
    private Ignite ignite;
    private IgniteCache cache;

    @Override
    public void cancel(ServiceContext serviceContext) {
        System.out.println("Service " + serviceContext.name() + " cancelled.");
    }

    @Override
    public void init(ServiceContext serviceContext) throws Exception {
        System.out.println("Service " + serviceContext.name() + " initialized.");
    }

    @Override
    public void execute(ServiceContext serviceContext) throws Exception {

        CacheConfiguration config = CacheConfig.myServiceCache();
        cache = ignite.getOrCreateCache(config).withExpiryPolicy(new CreatedExpiryPolicy(Duration.ONE_MINUTE));

        System.out.println("Service " + serviceContext.name() + " executing.");
    }

    public static void main(String[] args) {

        Ignite ignite = Ignition.start(NodeConfig.myServiceNode());

        IgniteServices svcs = ignite.services(ignite.cluster().forAttribute("role", NodeConfig.myServiceNode().getUserAttributes().get("role")));

        svcs.deployNodeSingleton("MyService", new MyService());

    }

}

person Ben    schedule 17.10.2016    source источник
comment
Было бы здорово, если бы вы предоставили небольшой пример, который воспроизводит проблему. Вариант использования не выглядит тривиальным, а описание немного расплывчатым.   -  person Valentin Kulichenko    schedule 17.10.2016
comment
Конечно, я добавил конкретный пример.   -  person Ben    schedule 18.10.2016
comment
Я чувствую, что это как-то связано с тем, как я развертываю сервис на каждом новом узле.   -  person Ben    schedule 18.10.2016


Ответы (1)


Вы не должны использовать == для сравнения значений атрибутов. Это условие работает нормально:

cfg.setNodeFilter((node) -> Objects.equals(node.attribute("role"), NodeConfig.myServiceNode().getUserAttributes().get("role")));
person Valentin Kulichenko    schedule 18.10.2016
comment
Вау, идеально. Это действительно, кажется, исправить это. Тай! - person Ben; 19.10.2016
comment
По-видимому, когда вы развертываете службу таким образом, вы не можете правильно генерировать/перехватывать исключения, см. level" title="перехват пользовательского исключения в удаленной службе на уровне вызывающего"> stackoverflow.com/questions/40545051/ Есть подсказка? - person Ben; 17.11.2016