仅沿着已部署的服务在选定节点上分发分区的 IgniteCache

Distribute partitioned IgniteCache on selected nodes only along deployed Service

我是 运行 一个 Apache Ignite 集群,具有提供服务的各种节点。每个节点都分配有一个特定的服务组(自定义节点属性),描述该节点提供的服务,例如授权、支付、...

其中一些服务正在使用 Ignite 缓存,但我希望这些服务特定的缓存仅部署在关联的服务节点上。所以我在我的缓存配置中添加了一个节点过滤器:

// 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"));

缓存部署按预期工作(至少没有显示错误)。但是,当我添加提供相同服务的第二个节点时(出于缩放的原因),会显示一个日志条目:

No server nodes found for cache client: MyServiceCache

一旦我停止第二个节点,就会显示另一条日志消息:

[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.

据我了解,第一个节点应该仍在提供服务和缓存。所以这些消息对我来说没有多大意义。有人可以详细说明吗?

这是一个具体的例子:

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());

    }

}

您不应使用 == 来比较属性值。这个条件很好:

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