Hazelcast:集群部署的正确方式

3

如何在一个REST服务器和5个工作机器的集群上部署Hazelcast?我应该在每个工作机器上启动5个Hazelcast服务器实例(每个工作机器一个)以及1个HazelcastClient实例在REST服务器上吗?

我有

  • 一个REST服务器,处理所有用户请求;
  • 一个由五个工作机器组成的集群,每台机器都在本地文件系统中保留一些数据。这些数据太大了,无法全部放在内存中,我只需要使用Hazelcast来分发我的搜索查询到整个集群中。

我想要

当用户发出请求时,通过每个工作机器的数据进行搜索,并将结果返回给用户。用户请求将由REST服务器机器接受,然后REST服务器将向集群中的每个工作机器发送搜索MultiTask。类似于:

public MySearchResult handleUserSearchRequest(String query) {
    MultiTask<String> task = new MultiTask<String>(query, Hazelcast.getCluster().getMembers());
    ExecutorService executorService = Hazelcast.getExecutorService();
    executorService.execute(task);
    Collection<String> results = task.get();
    return results.stream().reduce(/*some logic*/);
}

附言

如何从一个地方启动所有6个Hazelcast实例(Spring Boot应用程序)?


你在Worker机器上执行哪些操作?这些是独立的JVM还是一些Web服务器? - A.K.Desai
@A.K.Desai 我正在进行大量的IO操作(通过巨大的磁盘索引进行查找),是的 - 这些都是独立的JVM。 - VB_
好的,那么您可以将Hazelcast节点本身用作工作节点。您想在什么条件下分配负载?如果您已经对数据进行了分区,则可以简单地调用submitToKeyOwner,将任务提交给包含数据的节点。基于此,我可以建议一个快速的设计方法。 - A.K.Desai
@A.K.Desai 一个要点 - 我已经使用Apache Spark的帮助对数据进行了分区。因此,Hazelcast不知道数据是如何分布的。Hazelcast不应该使用集群范围的数据结构。实际上,数据位于每个工作节点的本地文件系统中,而submitToKeyOwner不适用于这种情况。我不能使用Spark代替Hazelcast完成此任务 - 它在同时启动两个会话时存在问题。 - VB_
1个回答

5
您可以编写一个脚本,运行包含节点启动代码的主类,这样就可以多次运行它。
根据您的用例,我提供了一个示例代码,用于从您的REST客户端驱动程序类创建群集并向所有节点提交任务。
运行下面的类5次,以在TCP/IP配置下创建一个由5个节点组成的群集。
public class WorkerNode {

    public static void main(String[] args){

        /*
        Create a new Hazelcast node.
        Get the configurations from Hazelcast.xml in classpath or default one from jar
         */
        HazelcastInstance workerNode = Hazelcast.newHazelcastInstance();

        System.out.println("*********** Started a WorkerNode ***********");
    }

}

这里是包含您IO操作业务逻辑的NodeTask。
public class NodeTask implements Callable<Object>, HazelcastInstanceAware, Serializable {

    private transient HazelcastInstance hazelcastInstance;

    public void setHazelcastInstance(HazelcastInstance hazelcastInstance) {
        this.hazelcastInstance = hazelcastInstance;
    }

    public Object call() throws Exception {

        Object returnableObject = "testData";

        //Do all the IO operations here and set the returnable object

        System.out.println("Running the NodeTask on a Hazelcast Node: " + hazelcastInstance.getName());

        return returnableObject;
    }
}

以下是您REST客户端的驱动程序类:

public class Driver {

    public static void main(String[] args) throws Exception {

        HazelcastInstance client = HazelcastClient.newHazelcastClient();

        IExecutorService executor = client.getExecutorService("executor");
        Map<Member, Future<Object>> result = executor.submitToAllMembers(new NodeTask());

        for (Future<Object> future : result.values()) {
            /*
            Aggregation logic goes here.
             */
            System.out.println("Returned data from node: " + future.get());
        }

        client.shutdown();

        System.exit(0);
    }
}

示例Hazelcast.xml配置:

<hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config http://www.hazelcast.com/schema/config/hazelcast-config-3.8.xsd"
           xmlns="http://www.hazelcast.com/schema/config"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <network>
        <port auto-increment="true" port-count="100">5701</port>
        <join>
            <multicast enabled="false">
                <multicast-group>224.2.2.3</multicast-group>
                <multicast-port>54327</multicast-port>
            </multicast>
            <tcp-ip enabled="true">
                <!--Replace this with the IP addresses of the servers -->
                <interface>127.0.0.1</interface>
            </tcp-ip>
            <aws enabled="false"/>
        </join>
        <interfaces enabled="false">
            <interface>127.0.0.1</interface>
        </interfaces>
    </network>
</hazelcast>

Architecture


非常感谢您提供如此详尽的答案!我理解,我应该将WorkerNode打包到单独的jar文件中,并在集群中的每个节点上运行该jar文件,是这样吗?另外,您的配置是否意味着嵌入式或客户端加成员方法,请参考https://hazelcast.org/deployment-operations-guide/#network-architecture-and-configuration? - VB_
还有一个来自这里http://docs.hazelcast.org/docs/3.5/manual/html/faq.html的注意事项:`在客户端-服务器拓扑中,您创建一个节点集群并独立扩展该集群。您的应用程序托管在客户端上,并且客户端与集群中的节点通信以访问数据。`我不需要在Hazelcast中保留数据,我只需要从集群中获取数据到REST服务器。也许客户端-服务器模式更适合我的需求? - VB_
1
是的,无论您是否想保留数据,请使用客户端-服务器模式。这样,它将具有水平可扩展性。如果您不打算在内存中保存数据,则根据IO操作的内存密集程度以较少的-Xmx启动JVM。 - A.K.Desai
1
只需将所有类和依赖项jar打包到一个单独的jar中,并独立运行该jar,以便它们可以形成集群。只要它们使用相同的hazelcast.xml文件,它们就会自动形成集群。 - A.K.Desai
非常感谢!请允许我问两个问题。99.9%的时间Hazelcast将处于空闲状态。1)如何尽可能地减少我的实例在空闲模式下占用的RAM?我可以有6个HazelcastClient吗? 2)我应该使用CLI启动每个Hazelcast节点,对吗? - VB_
当然。1)Hazelcast节点只是独立的JVM。一旦分配,就无法更改。但是您可以提出自己的自定义逻辑来执行自动缩放,这样可以在需要时带来/关闭更多实例。如果是AWS,则EC2实例自动缩放会处理它。2)无需拥有多个HazelcastClient实例,而是将其设置为单例并在REST服务器中使用。如果您有多个REST服务器,则每个服务器可以有一个客户端。3)是的,您可以使用CLI将它们启动。 - A.K.Desai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接