vertx模块HAManager高可用
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高可用的更多相关文章
- FastDFS高可用集群架构配置搭建
一.基本模块及高可用架构 FastDFS 是余庆老师开发的一个开源的高性能分布式文件系统(DFS). 它的主要功能包括:文件存储,文件同步和文件访问,以及高容量和负载平衡. FastDFS 系统有 ...
- 10 masterless、高可用、salt执行模块开发、sydic架构
1.salt无master 官方文档: http://docs.saltstack.cn/topics/tutorials/quickstart.html 1.使用场景 1.在项目中使用salt,写一 ...
- nginx内置高可用配置与第三方高可用模块nginx_ustream_check_mudule配置
1. nginx 第三方高可用模块 IP 备注 10.0.0.63 proxy 10.0.0.64 web1 10.0.0.65 web2 这里会讲解一些nignx常用高可用方案,以及引入第三方高可用 ...
- vertx模块DeploymentManager部署管理器
DeploymentManager public DeploymentManager(VertxInternal vertx) { this.vertx = vertx; loadVerticleFa ...
- MySQL高可用方案
高可用架构对于互联网服务基本是标配,无论是应用服务还是数据库服务都需要做到高可用.虽然互联网服务号称7*24小时不间断服务,但多多少少有一些时候服务不可用,比如某些时候网页打不开,百度不能搜索或者无法 ...
- 配置LVS + Keepalived高可用负载均衡集群之图文教程
负载均衡系统可以选用LVS方案,而为避免Director Server单点故障引起系统崩溃,我们可以选用LVS+Keepalived组合保证高可用性. 重点:每个节点时间都同步哈! C++代码 [r ...
- MySQL高可用架构之MHA
简介: MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司youshimaton(现就职于Facebook公司)开发,是 ...
- 理解 OpenStack 高可用(HA)(2):Neutron L3 Agent HA 之 虚拟路由冗余协议(VRRP)
本系列会分析OpenStack 的高可用性(HA)概念和解决方案: (1)OpenStack 高可用方案概述 (2)Neutron L3 Agent HA - VRRP (虚拟路由冗余协议) (3)N ...
- Redis Sentinel 高可用实现说明
背景: 前面介绍了Redis 复制.Sentinel的搭建和原理说明,通过这篇文章大致能了解Sentinel的原理和实现方法以及相关的搭建.这篇文章就针对Redis Sentinel的搭建做 ...
随机推荐
- Spring Boot 2.x 编写 RESTful API (二) 校验
用Spring Boot编写RESTful API 学习笔记 约束规则对子类依旧有效 groups 参数 每个约束用注解都有一个 groups 参数 可接收多个 class 类型 (必须是接口) 不声 ...
- k8s-jenkins 自动化1
一个流水线例子: 设置参数化构建: 流水线指令: def label = "docker-${UUID.randomUUID().toString()}" podTemplate( ...
- Cnblogs美化总结
测试 扩展阅读 [转载]详谈如何定制自己的博客园皮肤 - 云+社区 - 腾讯云谢谢!! [PS]3步搞定博客园界面风格 - nowgood - 博客园 [分享]博客美化(6)为你的博文自动添加目录 - ...
- 数据库设计很棒的参考CDM-PDM-LDM-PowerDesigner
此页面显示了涵盖主题领域的 50 个类别中的行业特定数据模型列表,用于创建企业数据模型. 以下是我们所有 1,700 多种数据模型的字母顺序列表 1. 广告 1. 顾客 1. 派对 1. 广告中 ...
- 「洛谷3870」「TJOI2009」开关【线段树】
题目链接 [洛谷] 题解 来做一下水题来掩饰ZJOI2019考炸的心情QwQ. 很明显可以线段树. 维护两个值,\(Lazy\)懒标记表示当前区间是否需要翻转,\(s\)表示区间还有多少灯是亮着的. ...
- 洛谷P4643 [国家集训队]阿狸和桃子的游戏(思维题+贪心)
思维题,好题 把每条边的边权平分到这条边的两个顶点上,之后就是个sb贪心了 正确性证明: 如果一条边的两个顶点被一个人选了,一整条边的贡献就凑齐了 如果分别被两个人选了,一作差就抵消了,相当于谁都没有 ...
- DFA确定有限状态自动机
DFA 在计算理论中,确定有限状态自动机或确定有限自动机(英语:deterministic finite automaton, DFA)是一个能实现状态转移的自动机.对于一个给定的属于该自动机的状态和 ...
- 虚拟机 模拟centos 7 系统安装
Cnetos 服务器安装过程 1.制作U盘启动器 网上有很多制作U盘启动的教程,这里就不详细说了 2.用U盘启动电脑进入安装界面 3.开始安装 等待片刻后,正常的应该会进入语言选择界面了. 选择中文 ...
- 010 socket定义服务器
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Ne ...
- Redis非关系型数据库
1.简介 Redis是一个基于内存的Key-Value非关系型数据库,由C语言进行编写. Redis一般作为分布式缓存框架.分布式下的SESSION分离.分布式锁的实现等等. Redis速度快的原因: ...