HAManager

public HAManager(VertxInternal vertx, DeploymentManager deploymentManager,
ClusterManager clusterManager, int quorumSize, String group, boolean enabled) {
this.vertx = vertx;
this.deploymentManager = deploymentManager;
this.clusterManager = clusterManager;
//仲裁结点数量,默认1
this.quorumSize = enabled ? quorumSize : ;
//定义逻辑组名,默认__DEFAULT__
this.group = enabled ? group : "__DISABLED__";
this.enabled = enabled;
this.haInfo = new JsonObject();
haInfo.put("verticles", new JsonArray());
haInfo.put("group", this.group);
//获取集群管理 __vertx.haInfo,添加结点信息
this.clusterMap = clusterManager.getSyncMap(CLUSTER_MAP_NAME);
this.nodeID = clusterManager.getNodeID();
synchronized (haInfo) {
clusterMap.put(nodeID, haInfo.encode());
}
/**添加一个节点侦听器,侦听节点join or leaves */
clusterManager.nodeListener(new NodeListener() {
@Override
public void nodeAdded(String nodeID) {
HAManager.this.nodeAdded(nodeID);
} @Override
public void nodeLeft(String leftNodeID) {
HAManager.this.nodeLeft(leftNodeID);
}
});
//定义周期器,每隔 1s 检查 HADeployments
quorumTimerID = vertx.setPeriodic(QUORUM_CHECK_PERIOD, tid -> checkHADeployments());
// 调用检查仲裁来计算是否有初始仲裁
synchronized (this) {
checkQuorum();
}
} private void checkQuorum() {
if (quorumSize == ) {//判断仲裁数量
this.attainedQuorum = true;
} else {
 /**获取group node数量*/
List<String> nodes = clusterManager.getNodes();
int count = ;
for (String node : nodes) {
String json = clusterMap.get(node);
if (json != null) {
JsonObject clusterInfo = new JsonObject(json);
String group = clusterInfo.getString("group");
if (group.equals(this.group)) {
count++;
}
}
}
/**计算是否到达仲裁数量*/
boolean attained = count >= quorumSize;
if (!attainedQuorum && attained) {
log.info("A quorum has been obtained. Any deploymentIDs waiting on a quorum will now be deployed");
this.attainedQuorum = true;
} else if (attainedQuorum && !attained) {
log.info("There is no longer a quorum. Any HA deploymentIDs will be undeployed until a quorum is re-attained");
this.attainedQuorum = false;
}
}
}

deploy an HA verticle

public void deployVerticle(final String verticleName, DeploymentOptions deploymentOptions,
final Handler<AsyncResult<String>> doneHandler) {
if (attainedQuorum) {//根据是否达到仲裁数量,否则添加到delay Queue
doDeployVerticle(verticleName, deploymentOptions, doneHandler);
} else {
log.info("Quorum not attained. Deployment of verticle will be delayed until there's a quorum.");
addToHADeployList(verticleName, deploymentOptions, doneHandler);
}
} /**
* 部署verticle
*/
private void doDeployVerticle(final String verticleName, DeploymentOptions deploymentOptions,
final Handler<AsyncResult<String>> doneHandler) {
/**添加deploy verticle 后的回调 handler*/
final Handler<AsyncResult<String>> wrappedHandler = asyncResult -> {
if (asyncResult.succeeded()) {
// 添加当前 node 的 HA 相关信息,以便 other node了解
addToHA(asyncResult.result(), verticleName, deploymentOptions);
}
/**触发已添加添加回调 hander*/
if (doneHandler != null) {
doneHandler.handle(asyncResult);
} else if (asyncResult.failed()) {
log.error("Failed to deploy verticle", asyncResult.cause());
}
};
//部署verticle
deploymentManager.deployVerticle(verticleName, deploymentOptions, wrappedHandler);
} /**
* 添加deploy 任务到delay Queue
*/
private void addToHADeployList(final String verticleName, final DeploymentOptions deploymentOptions,
final Handler<AsyncResult<String>> doneHandler) {
toDeployOnQuorum.add(() -> {
ContextImpl ctx = vertx.getContext();
try {
ContextImpl.setContext(null);
//部署verticle
deployVerticle(verticleName, deploymentOptions, doneHandler);
} finally {
ContextImpl.setContext(ctx);
}
});
}

周期每秒检测

private void checkHADeployments() {
try {
if (attainedQuorum) {//判断仲裁数量是否达到
deployHADeployments();
} else {
undeployHADeployments();
}
} catch (Throwable t) {
log.error("Failed when checking HA deploymentIDs", t);
}
} private void deployHADeployments() {
  //获取delay Queue 任务数
int size = toDeployOnQuorum.size();
if (size != ) {
log.info("There are " + size + " HA deploymentIDs waiting on a quorum. These will now be deployed");
Runnable task;
/**处理所有 delay 部署任务*/
while ((task = toDeployOnQuorum.poll()) != null) {
try {
task.run();
} catch (Throwable t) {
log.error("Failed to run redeployment task", t);
}
}
}
} private void undeployHADeployments() {
  /** 遍历所有deploy verticle */
for (String deploymentID: deploymentManager.deployments()) {
Deployment dep = deploymentManager.getDeployment(deploymentID);
if (dep != null) {
if (dep.deploymentOptions().isHa()) {
ContextImpl ctx = vertx.getContext();
try {
ContextImpl.setContext(null);
//卸载
deploymentManager.undeployVerticle(deploymentID, result -> {
if (result.succeeded()) {
log.info("Successfully undeployed HA deployment " + deploymentID + "-" + dep.verticleIdentifier() + " as there is no quorum");
/**添加HA verticle 到 delay Queue 重新部署*/
addToHADeployList(dep.verticleIdentifier(), dep.deploymentOptions(), result1 -> {
if (result1.succeeded()) {
log.info("Successfully redeployed verticle " + dep.verticleIdentifier() + " after quorum was re-attained");
} else {
log.error("Failed to redeploy verticle " + dep.verticleIdentifier() + " after quorum was re-attained", result1.cause());
}
});
} else {
log.error("Failed to undeploy deployment on lost quorum", result.cause());
}
});
} finally {
ContextImpl.setContext(ctx);
}
}
}
}
}

note:不建议使用HA模块,还是利用Health Check作为verticle服务检查,出错时自动重启服务,
"启用高可用性(HA)的情况下部署Verticle。在该上下文中,当Verticle部署在突然死亡的vert.x实例上时,
Verticle将从集群中的另一个vert.x实例上重新部署".
分析:没有verticle持久化,上传集群中心或序列化分发other node,其它集群结点local根本没有
verticle(compile class)如何重新部署,毕竟不是共享内存

vertx模块HAManager高可用的更多相关文章

  1. FastDFS高可用集群架构配置搭建

      一.基本模块及高可用架构 FastDFS 是余庆老师开发的一个开源的高性能分布式文件系统(DFS). 它的主要功能包括:文件存储,文件同步和文件访问,以及高容量和负载平衡. FastDFS 系统有 ...

  2. 10 masterless、高可用、salt执行模块开发、sydic架构

    1.salt无master 官方文档: http://docs.saltstack.cn/topics/tutorials/quickstart.html 1.使用场景 1.在项目中使用salt,写一 ...

  3. nginx内置高可用配置与第三方高可用模块nginx_ustream_check_mudule配置

    1. nginx 第三方高可用模块 IP 备注 10.0.0.63 proxy 10.0.0.64 web1 10.0.0.65 web2 这里会讲解一些nignx常用高可用方案,以及引入第三方高可用 ...

  4. vertx模块DeploymentManager部署管理器

    DeploymentManager public DeploymentManager(VertxInternal vertx) { this.vertx = vertx; loadVerticleFa ...

  5. MySQL高可用方案

    高可用架构对于互联网服务基本是标配,无论是应用服务还是数据库服务都需要做到高可用.虽然互联网服务号称7*24小时不间断服务,但多多少少有一些时候服务不可用,比如某些时候网页打不开,百度不能搜索或者无法 ...

  6. 配置LVS + Keepalived高可用负载均衡集群之图文教程

    负载均衡系统可以选用LVS方案,而为避免Director Server单点故障引起系统崩溃,我们可以选用LVS+Keepalived组合保证高可用性.  重点:每个节点时间都同步哈! C++代码 [r ...

  7. MySQL高可用架构之MHA

    简介: MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司youshimaton(现就职于Facebook公司)开发,是 ...

  8. 理解 OpenStack 高可用(HA)(2):Neutron L3 Agent HA 之 虚拟路由冗余协议(VRRP)

    本系列会分析OpenStack 的高可用性(HA)概念和解决方案: (1)OpenStack 高可用方案概述 (2)Neutron L3 Agent HA - VRRP (虚拟路由冗余协议) (3)N ...

  9. Redis Sentinel 高可用实现说明

    背景:      前面介绍了Redis 复制.Sentinel的搭建和原理说明,通过这篇文章大致能了解Sentinel的原理和实现方法以及相关的搭建.这篇文章就针对Redis Sentinel的搭建做 ...

随机推荐

  1. 使用cURL尝试ElasticSearch

    测试环境:debian 9官网提供了 deb,rpm,源码下载 官方下载地址:https://www.elastic.co/downloads/elasticsearch 通过源码安装会遇到一些小问题 ...

  2. ubuntu下python跑任务输出到文件中遇到的一些问题(输出重定向)

    之前主要是参考https://www.cnblogs.com/chason95/articles/9760291.html 一般使用 python test.py > ./log.txt 或 p ...

  3. sql语句基础

    数据库库(DataBase):就是一个存储数据的仓库.为了方便数据的存储和管理,它将数据按照特定的规律存储在磁盘上.通过数据库管理系统,可以有效的组织和管理存储在数据库中的数据.SQL(Structu ...

  4. 本部jdk切换的坑!!!

    https://www.cnblogs.com/ll409546297/p/6593173.html 如果你参考其他博主没有解决,可以来参考下这个. 1.我们打开注册表,然后找到这个路径: HKEY_ ...

  5. 关于小米4电信4g刷入第三方ROM无信号解决办法

    from: http://www.yuwantb.com/xiaomi4-lineage-os.html   关于小米4电信4g刷入第三方ROM无信号解决办法 下载这个电信4g补丁包. 链接:http ...

  6. Django中ORM介绍

    Object Relational Mapping(ORM) ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据 ...

  7. Windows系统CredSSP漏洞修复

    Windows系统凭证安全支持提供商协议 (CredSSP) 中存在一个严重漏洞,影响所有 Windows 版本,可导致远程攻击者利用 RDP 和 WinRAW 窃取数据并运行恶意代码. 详见:htt ...

  8. DataReader转Dictionary数据类型之妙用

    datareader转dictionary有很多用处,可以输出表中部分字段转实体字段,以前需要全部字段输出或者再建一个实体模型才行,这样就可以减少数据库的输出量了,特别是某些接口的格式化输出很方便. ...

  9. seq2seq

    seq2seq: seq2seq就是将输入序列经过encoder-decoder变成目标序列. 如图所示,输入序列是 [A, B, C, <EOS>],输出序列是  [W, X, Y, Z ...

  10. Haproxy 安装及配置

    Haproxy介绍 HAProxy是一个特别适用于高可用性环境的TCP/HTTP开源的反向代理和负载均衡软件.实现了一种事件驱动,单一进程模型,支持非常大的并发连接,是因为事件驱动模型有更好的资源和时 ...