我正在尝试部署 Java SpringBoot 微服务以在 OpenShift 容器上使用领导者选举。我无需配置即可使其在本地工作。我尝试了2个节点(在相同的IP,不同的端口上)。我没有做任何特殊配置来让它工作。
但是当我将代码部署到 OpenShift Container 并将其部署到 2 个节点时,集群不起作用。节点似乎无法找到彼此(它们位于不同的 IP,相同的端口)。所以它是裂脑的。
我查找了如何执行此操作,并找到了这些说明来使用和安装 hazelcast-operators(Hazelcast 平台操作员)以使其正常工作,但在我的特定环境中,我们不允许安装此类软件包。
我有什么办法可以完成这项工作,而不需要安装 hazelcast 运算符、RBAC 规则,或者不需要对 OpenShift 环境设置进行任何操作(我在一个非常受限的 OpenShift 环境中工作)?
是否有任何编程或 YAML 配置(在应用程序级别)可以从我的代码中部署以使其正常工作?
我尝试部署我的微服务。这基本上就是我的代码:
@Component
public class Runner implements CommandLineRunner, MembershipListener {
private static final Logger logger = Logger.getLogger(Runner.class.getName());
...
private String leaderAddress;
private HazelcastInstance hazelcastInstance;
...
@Autowired
private CSPRabbitMQConfig rabbitMQConfiguration;
public Runner(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
}
@Override
public void run(String... args) throws Exception {
hazelcastInstance = Hazelcast.newHazelcastInstance(/* hazelcastConfig */);
hazelcastInstance.getCluster().addMembershipListener(this);
logger.info("Members: "+ hazelcastInstance.getCluster().getMembers().size());
leaderAddress = hazelcastInstance.getCluster().getMembers().iterator().next().getSocketAddress().toString();
logger.info("Current leader address: " + leaderAddress);
...
// Leader should be the only process to start the subscriptions
if (amITheLeader()) {
// TODO: need to verify this works in a multi-host environment.
// This node is the leader, do leader-specific tasks here
...
}
...
}
...
public boolean amITheLeader() {
logger.info("> amITheLeader() - cluster size: " + hazelcastInstance.getCluster().getMembers().size());
return hazelcastInstance.getCluster().getLocalMember().getSocketAddress().toString().equals(leaderAddress);
}
@Override
public void memberAdded(MembershipEvent membershipEvent) {
if (membershipEvent.getMember().getSocketAddress().toString().compareTo(leaderAddress) < 0) {
// A new member has joined that has an older address, it becomes the new leader
leaderAddress = membershipEvent.getMember().getSocketAddress().toString();
if (amITheLeader()) {
// This node is the new leader, do leader-specific tasks here
}
}
}
@Override
public void memberRemoved(MembershipEvent membershipEvent) {
if (membershipEvent.getMember().getSocketAddress().toString().equals(leaderAddress)) {
// The leader has left the cluster, a new leader will be elected
leaderAddress = hazelcastInstance.getCluster().getMembers().iterator().next().getSocketAddress().toString();
if (amITheLeader()) {
// This node is the new leader, do leader-specific tasks here
}
}
}
我包含了这个 Maven 依赖项:
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-spring</artifactId>
</dependency>
也许还有另一种方法可以对此进行编码,或者也许我正在以过时的方式进行此操作?
这对于在同一 IP 地址(不同端口)上运行的应用程序的多个实例在本地运行良好 - 有时,有时,节点无法找到彼此。
我原以为部署到 OpenShift 后它会自动工作,但是一旦我这样做了,我发现节点无法找到彼此,因此集群无法工作,这不允许领导者选举正常工作。
在 DNS 查找模式下使用 Kubernetes 可能正是您所需要的。
基本思想是为 Kubernetes 集群中的微服务创建一个 Headless Service。它基本上是一个指向所有服务实例的 DNS 条目。然后,您在 Hazelcast 加入配置中配置此 DNS 名称,每个实例都会找到所有其他实例。该文档提供了有关此类 Kubernetes 服务的外观以及如何使用 YAML 或 Java 调整 Hazelcast 配置的详细信息。
该文档还提供了此方法的优点和缺点的列表。我的印象是这种 DNS Lookup 模式在生产中使用较少,但似乎仍然受支持。