近期在项目中遇到一个问题,解决此问题,需要改变架构方案,以下为方案具体内容
目录
9.补充测试executor扩容、缩容/宕机、重启恢复场景:
1.痛点
前置:通过river消费kafka中的日志数据,不同的topic中的数据,有不同字段类型,通过不同的river进行解析。
1.1 当日志量达到一定级别之后,低版本es的消费能力明显跟不上,造成消费堆积;
1.2 当业务方新增一个日志类型或者对某个在日志类型新增字段,需要修改river代码,解析不灵活。
2.如何解决
2.1升级ES
基于1.1的问题,我们需要升级ES到高版本,如ES7.0,但是高版本的ES已经不支持river,所以需要替代river的技术,主要解决包括:负载均衡,故障转移等,如果支持监控、告警、分片则更为适合;
2.2 动态解析日志
基于1.2的问题,我们需要实现动态解析日志,能快速满足用户对日志类型的动态变化需求。
3.替代river技术方案调研
通过调研,目前主要分布式任务调度技术方案有saturn(唯品会)、Elastic-Job(当当)、Xxl-Job、Quartz。
对比如下:
也许大家注意到了,怎么没有saturn,下面隆重介绍下,saturn是Elastic-Job的升级版本,取代传统的Linux Cron/Spring Batch Job的方式,做到统一配置,统一监控,任务高可用以及分片并发处理。主要是去中心化,高可用,可分片,动态扩容,有认证和授权功能。
主要特性:
- 支持多种语言作业,语言无关(Java/Go/C++/PHP/Python/Ruby/shell)
- 支持秒级调度
- 支持作业分片并行执行
- 支持依赖作业串行执行
- 支持作业高可用和智能负载均衡
- 支持异常检测和自动失败转移
- 支持异地容灾
- 支持多个集群部署
- 支持跨机房区域部署
- 支持弹性动态扩容
- 支持优先级和权重设置
- 支持docker容器,容器化友好
- 支持cron时间表达式
- 支持多个时间段暂停执行控制
- 支持超时告警和超时强杀控制
- 支持灰度发布
- 支持异常、超时和无法高可用作业监控告警和简易的故障排除
- 支持失败率最高、最活跃和负荷最重的各域各节点TOP10的作业统计
优点:源码清晰,学习入手容易。应用部署简单,提供运维控制台,集中管理作业,运维控制台功能强大,提供作业统计报表 ,告警,增删改查作业,作业统一配置。
所以,采用saturn替代river实现分布式任务调度。
4.saturn运行原理
4.1环境准备
硬件准备:Linux服务器
软件准备:
JDK : 1.7+
ZooKeeper: 3.4.6+
nodejs:7.8.0+
mysql
saturn-console-{version}-exec.jar
saturn-executor-{version}-zip.zip
4.2系统架构
Saturn包括两大部分,Saturn Console和Saturn Executor。Console是一个WEB UI,用来对作业/Executor的管理,告警,系统配置,权限管理,统计报表展现等。他同时也是整个调度系统的大脑:将作业任务分配到各Executor。Executor是执行任务的worker:按照作业配置的要求去执行部署于Executor所在容器或物理机当中的作业脚本和代码。Saturn高度依赖于zookeeper,每个executor及调度服务都会在zookeeper上进行注册,确保调度程序能够及时得到executor的状态。
Saturn定时任务调度的最小单位是分片,即任务的一个执行单元。Saturn的基本任务就是将任务分成多个分片,并将每个分片通过算法调度到对应的executor上去执行。
4.3基本原理
Saturn的基本原理是将作业在逻辑上划分为若干个分片,通过作业分片调度器将作业分片指派给特定的执行节点。执行节点通过quartz触发执行作业的具体实现,在执行的时候,会将分片序号和参数作为参数传入。作业的实现逻辑需分析分片序号和分片参数,并以此为依据来调用具体的实现(比如一个批量处理数据库的作业,可以划分0号分片处理1-10号数据库,1号分片可以处理11-20号数据库)。
配置作业的界面图,着重几块:优先executor、暂停日期及时间段、作业依赖(上下游作业),可满足多场景的需求,这里不做具体阐述,配置如下:
5.动态解析方案
通过zk来进行解析配置管理,应用程序在启动时会根据日志类型参数,在zk上找到需要的日志解析配置,并同时对zk上这个配置节点进行监听,如果配置有变化,本地解析配置将立即生效。
5.1 Zk配置
可以导入配置文件来增加、修改内容。
5.2日志解析格式设置
在一个固定的节点下,去存放解析配置的列表,每种解析配置的节点名称为日志类型名称,每种节点下面将包含全套的该种日志类型的所有版本的解析方式。
格式如下:
{
"testapp": {
"list": {
"version": {
"splitConfig": {
"2-": {
"fields": [{
"index": 0,
"name": "version",
"type": "String"
}, {
"index": 1,
"name": "ldcId",
"type": "String"
}, {
"index": 2,
"name": "hostGroup",
"type": "String"
}, {
"index": 3,
"name": "appId",
"type": "String"
}, {
"index": 4,
"name": "ip",
"type": "String"
}, {
"index": 5,
"name": "path",
"type": "String"
}, {
"index": 6,
"name": "lid",
"type": "String"
}, {
"index": 7,
"name": "hostName",
"type": "String"
}, {
"index": 8,
"name": "hostIp",
"type": "String"
}, {
"index": 9,
"name": "logTime",
"type": "date",
"parserConfigs": {
"format": "",
"type": "timestamp"
}
}, {
"index": 10,
"name": "message",
"type": "String"
}],
"filedLength": 11
}
}
},
"splitChar": "\t"
}
}
}
5.2.1解析方式
其中解析方式设置包括无key的list解析方式,和key-value的map解析方式。
5.2.2日志版本控制
解析时将匹配出该条日志的版本特征,日志最前面是否有版本号,最后面是否有版本号,并提取出版本的特征。比如,前后都没有版本特征,将用- -表示,前有V1后无V将用1-表示。
5.2.3解析字段配置
必须配置:字段位置(index),字段名称(name),要解析成的类型(type).还有分割符类型。
其中parserConfigs一般字段为可选,但是时间相关的类型必须要设置format和type。其中type包括三种类型:normal(一般类型),utc(utc类型)和timestamp(时间戳)。Format字段用来描述时间字段解析格式。
注意:
字段顺序必须要严格按照顺序来定义,从0开始。
6.saturn结合spring-boot测试实例
7.遇到的问题及解决
Q1:如何结局让job只执行一次?
A1:cron表达式设置如下,
备注:如有其它问题,后续补充。
8.环境部署最低要求
为满足高可用,以下为测试环境参考配置:
Saturn console集群部署:3台linux服务器
Zookeeper集群部署:3台linux服务器
Saturn executor部署:3台linux服务器
Mysql集群:3台DB(一主两从)
部署架构图
9.补充测试executor扩容、缩容/宕机、重启恢复场景:
为了确保每个域的executor高可用,需确保每个域有3个及以上的executor在运行,低于3个executor会出现宕机重启后,节点分布不均的情况。
因为一次执行作业可以看做是定时执行作业的最小单元,以定时作业为例,测试executor扩容、缩容/宕机、重启恢复场景,如下:
分片数 | Executor 运行数 | 测试场景 | 运行结果 | 补充 |
4 | 3 | 执行作业过程中,关闭其中一个executor服务,宕机不可用,即缩容 | 被关闭的executor上的任务终止,且该executor上的所有分片任务转移到其他同域的executor上执行,即自动故障转移 | 宕机的executor上失败的分片会自动故障转移到其他同域的executor上(非断点继续执行,而是重新执行该分片),需注意,失败转移的分片,需要等到被转移的executor上的原有分片任务执行完之后立即执行,且多个失败分片任务按顺序执行 |
作业执行过程中或者执行完,对宕机的executor进行重启恢复 | 宕机executor上的任务不会重新执行 | 宕机executor上的任务不会重新执行,即使设置了超时重跑,仍无效 | ||
作业执行过程中,新增一个executor,即扩容 | 不能即时分担分片任务 | 扩容的executor只会在下批次生效,不能即时生效 |
- Executor扩容,非即时生效,下批次任务生效;
- Executor宕机(缩容),被宕机的executor上分片任务终止,失败的任务转移到其他同域且正在运行的executor执行,非断点继续执行,而是重新执行失败分片,而且需要等被转移到的executor上的原有分片任务执行完之后立即执行,且多个失败分片任务按顺序执行。若当前域下午可用的executor,则本批次失败的分片永久失效;
- Executor重启恢复,被恢复的executor上的失败分片不会被重新执行。对于定时任务,被恢复的executor下批次生效,参与下批次分配分片任务。对于一次执行任务,若正在运行的executor上的分片未执行完,又想把恢复的executor投入使用,则需要通过运维线下手动重启正在运行的executor,来终止正在执行的分片,可能会造成数据的丢失,请注意!最后把作业立即执行或者设定一个未来时间,执行一次即可;
- 作业负荷:Saturn Executor 作业分片调度算法的核心思想是尽量保证全域的executor负荷平均。而Executor的负荷等于所有作业的分片乘以负荷的加权。简单来说,如果你希望作业占用更多的资源(Executor),则将次负荷设置为一个大的数字。
图例说明,如下:
Saturn 给每个任务的每个分片一个负荷值,即权重。比如任务 A 每个分片的权重都是 30,任务 B 每个分片的权重都是 10,在进行资源调度的时候,Saturn 可以根据分配给不同机器的总负荷值,来做一个均衡。比如说机器 1 的负荷值是 60,机器 2 的负荷值也是 60,虽然机器 1 只负责了两个任务分片,机器 2 却负责了四个任务分片,通过任务负荷来达到资源均衡的效果。
5.摘取流量不影响本批次任务执行,在下批次任务分配生效,即不参与分片任务分配。重启executor需等待该节点上的分片任务执行完才可以重启。
如有不到之处,请指出,欢迎交流!