Hadoop2.6.0的事件分类与实现
前言
说实在的,在阅读Hadoop YARN的源码之前,我对于java枚举的使用相形见绌。YARN中实现的事件在可读性、可维护性、可扩展性方面的工作都值得借鉴。
概念
在具体分析源码之前,我们先看看YARN是如何定义一个事件的。比如作业启动的事件,很多人可能会用常量将它定义到一个class文件中,就像下面这样:
class Constants {
public static final String JOB_START_EVENT = "jobStart";
}
或者简单的使用枚举,就像下面这样;
enum Enums {
JOB_START_EVENT("jobStart");
private String name;
private Enums(String name) {
this.name = name;
}
}
之后,当增加了作业停止的事件,代码会变为:
class Constants {
public static final String JOB_START_EVENT = "jobStart";
public static final String JOB_END_EVENT = "jobEnd";
}
或者:
enum Enums {
JOB_START_EVENT("jobStart"),
JOB_END_EVENT("jobEnd");
private String name;
private Enums(String name) {
this.name = name;
}
}
我们的系统往往很复杂,这时候引入了任务的概念,包括任务启动、任务停止的事件。随着业务发展,有更多的概念被加进来,就像下面这样;
class Constants {
public static final String JOB_START_EVENT = "jobStart";
public static final String JOB_END_EVENT = "jobEnd";
public static final String TASK_START_EVENT = "taskStart";
public static final String TASK_END_EVENT = "taskEnd";
// 其它各种概念的常量
}
或者:
enum Enums {
JOB_START_EVENT("jobStart"),
JOB_END_EVENT("jobEnd"),
// 其它各种概念的常量枚举
TASK_START_EVENT("taskStart"),
TASK_END_EVENT("taskEnd");
private String name;
private Enums(String name) {
this.name = name;
}
}
当加入的常量值越来越多时,你会发现以上使用方式越来越不可维护。各种概念混杂在一起,显得杂乱无章。你可能会说,我不会这么傻,我会将作业与任务以及其它概念的常量值分而治之,每个业务概念相关的放入一个文件,就像下面这样:
class JobConstants {
public static final String JOB_START_EVENT = "jobStart";
public static final String JOB_END_EVENT = "jobEnd";
}
class TaskConstants {
public static final String TASK_START_EVENT = "taskStart";
public static final String TASK_END_EVENT = "taskEnd";
}
或者:
enum JobEnums {
JOB_START_EVENT("jobStart"),
JOB_END_EVENT("jobEnd");
private String name;
private JobEnums (String name) {
this.name = name;
}
}
enum TaskEnums {
TASK_START_EVENT("taskStart"),
TASK_END_EVENT("taskEnd");
private String name;
private TaskEnums (String name) {
this.name = name;
}
}
现在业务出现了新的变化,每种枚举值除了name属性之外,还增加了code属性。假如你之前选择了常量值来实现,此时不可避免的需要重构。如果你选择了枚举,说明你初步的选择是明智的,你可以这样来扩展:
enum JobEnums {
JOB_START_EVENT(10, "jobStart"),
JOB_END_EVENT(20, "jobEnd");
private int code;
private String name;
private JobEnums (int code, String name) {
this.code = code;
this.name = name;
}
}
enum TaskEnums {
TASK_START_EVENT(110, "taskStart"),
TASK_END_EVENT(120, "taskEnd");
private int code;
private String name;
private TaskEnums (int code, String name) {
this.code = code;
this.name = name;
}
}
可悲的是,你不得不在每一个枚举中都重复加入类似的代码。也许你认为这只不过是增加些许的工作量,你操作键盘的手法熟练而迷人,几次快速的复制操作就可以完成。噩梦远没有结束,新的需求给两个枚举类型融入了新的不同——JobEnums增加了description属性,而TaskEnums则增加了timestamp字段。此外,两者还必须都增加hashCode方法以用于散列。增加这些功能后,代码将变为:
enum JobEnums {
JOB_START_EVENT(10, "jobStart", "job start description"),
JOB_END_EVENT(20, "jobEnd", "job end description");
private int code;
private String name;
private String description;
private JobEnums (int code, String name, String description) {
this.code = code;
this.name = name;
this.description = description;
}
public int hashCode() {
return this.name.hashCode() + this.description.hashCode();
}
}
enum TaskEnums {
TASK_START_EVENT(110, "taskStart", 1460977775087),
TASK_END_EVENT(120, "taskEnd", 1460977775088);
private int code;
private String name;
private long timestamp;
private TaskEnums (int code, String name, long timestamp) {
this.code = code;
this.name = name;
this.timestamp = timestamp;
}
public int hashCode() {
return this.name.hashCode();
}
}
随着业务的发展,你会发现你需要维护的枚举类型差异越来越多。即便它们之间有所不同,可是却有很多内容是重复的。为了解决枚举与常量在可读性、可维护性、可复用性、可扩展性等方面的问题,Hadoop将事件进行了以下定义:
事件 = 事件名称 + 事件类型
比如作业启动事件 = 作业事件 + 作业事件类型
事件与事件类型
Hadoop2.6.0中的事件多种多样,最为常见的包括:ContainerEvent、ApplicationEvent、JobEvent、RMAppEvent、RMAppAttemptEvent、TaskEvent、TaskAttemptEvent等。为了解决枚举与常量在可读性、可维护性、可复用性、可扩展性等方面的问题,Hadoop对事件进行了以下抽象:
/**
* Interface defining events api.
*
*/
@Public
@Evolving
public interface Event<TYPE extends Enum<TYPE>> { TYPE getType();
long getTimestamp();
String toString();
}
以上接口说明了任何一个具体事件都是一个枚举类型,而且有一个事件类型属性(用泛型标记TYPE表示),一个时间戳及toString()方法。
所有事件都有一个基本实现AbstractEvent,其实现如下:
/**
* Parent class of all the events. All events extend this class.
*/
@Public
@Evolving
public abstract class AbstractEvent<TYPE extends Enum<TYPE>>
implements Event<TYPE> { private final TYPE type;
private final long timestamp; // use this if you DON'T care about the timestamp
public AbstractEvent(TYPE type) {
this.type = type;
// We're not generating a real timestamp here. It's too expensive.
timestamp = -1L;
} // use this if you care about the timestamp
public AbstractEvent(TYPE type, long timestamp) {
this.type = type;
this.timestamp = timestamp;
} @Override
public long getTimestamp() {
return timestamp;
} @Override
public TYPE getType() {
return type;
} @Override
public String toString() {
return "EventType: " + getType();
}
}
以JobEvent表示作业事件,其实现如下:
/**
* This class encapsulates job related events.
*
*/
public class JobEvent extends AbstractEvent<JobEventType> { private JobId jobID; public JobEvent(JobId jobID, JobEventType type) {
super(type);
this.jobID = jobID;
} public JobId getJobId() {
return jobID;
} }
TaskEvent表示任务事件,其实现如下:
/**
* this class encapsulates task related events.
*
*/
public class TaskEvent extends AbstractEvent<TaskEventType> { private TaskId taskID; public TaskEvent(TaskId taskID, TaskEventType type) {
super(type);
this.taskID = taskID;
} public TaskId getTaskID() {
return taskID;
}
}
事件类型属性(用泛型标记TYPE表示)在任务事件中对应的是TaskEventType,其实现如下:
/**
* Event types handled by Task.
*/
public enum TaskEventType { //Producer:Client, Job
T_KILL, //Producer:Job
T_SCHEDULE,
T_RECOVER, //Producer:Speculator
T_ADD_SPEC_ATTEMPT, //Producer:TaskAttempt
T_ATTEMPT_LAUNCHED,
T_ATTEMPT_COMMIT_PENDING,
T_ATTEMPT_FAILED,
T_ATTEMPT_SUCCEEDED,
T_ATTEMPT_KILLED
}
JobEventType类似,不再赘述。
这种实现将枚举与各种事件之间的差异(表现在属性和方法的不同)解耦,极大地扩展了可读性、可维护性,并且保留了相同逻辑的代码复用。
后记:个人总结整理的《深入理解Spark:核心思想与源码分析》一书现在已经正式出版上市,目前京东、当当、天猫等网站均有销售,欢迎感兴趣的同学购买。
京东(现有满150减50活动)):http://item.jd.com/11846120.html
当当:http://product.dangdang.com/23838168.html
Hadoop2.6.0的事件分类与实现的更多相关文章
- 安装hadoop2.6.0伪分布式环境 分类: A1_HADOOP 2015-04-27 18:59 409人阅读 评论(0) 收藏
集群环境搭建请见:http://blog.csdn.net/jediael_lu/article/details/45145767 一.环境准备 1.安装linux.jdk 2.下载hadoop2.6 ...
- 搭建hadoop2.6.0集群环境 分类: A1_HADOOP 2015-04-20 07:21 459人阅读 评论(0) 收藏
一.规划 (一)硬件资源 10.171.29.191 master 10.171.94.155 slave1 10.251.0.197 slave3 (二)基本资料 用户: jediael 目录: ...
- Flume1.5.0的安装、部署、简单应用(含伪分布式、与hadoop2.2.0、hbase0.96的案例)
目录: 一.什么是Flume? 1)flume的特点 2)flume的可靠性 3)flume的可恢复性 4)flume 的 一些核心概念 二.flume的官方网站在哪里? 三.在哪里下载? 四.如何安 ...
- hadoop2.6.0汇总:新增功能最新编译 32位、64位安装、源码包、API下载及部署文档
相关内容: hadoop2.5.2汇总:新增功能最新编译 32位.64位安装.源码包.API.eclipse插件下载Hadoop2.5 Eclipse插件制作.连接集群视频.及hadoop-eclip ...
- Hadoop2.2.0安装过程记录
1 安装环境1.1 客户端1.2 服务端1.3 安装准备 2 操作系统安装2.1.1 BIOS打开虚拟化支持2.1.2 关闭防火墙2.1.3 安装 ...
- CentOS下Hadoop-2.2.0集群安装配置
对于一个刚开始学习Spark的人来说,当然首先需要把环境搭建好,再跑几个例子,目前比较流行的部署是Spark On Yarn,作为新手,我觉得有必要走一遍Hadoop的集群安装配置,而不仅仅停留在本地 ...
- ubuntu14.04 安装 hadoop2.4.0
转载:ubuntu搭建hadoop-Ver2.6.0完全分布式环境笔记 自己在搭建hadoop平台时,碰到一些困难,按照该博文解决了问题,转载一下,作为记录. 2 先决条件 确保在你集群中的每个节点上 ...
- Hadoop-1.2.1 升级到Hadoop-2.6.0 HA
Hadoop-1.2.1到Hadoop-2.6.0升级指南 作者 陈雪冰 修改日期 2015-04-24 版本 1.0 本文以hadoop-1.2.1升级到hadoop-2.6.0 Z ...
- Hadoop2.6.0安装 — 集群
文 / vincentzh 原文连接:http://www.cnblogs.com/vincentzh/p/6034187.html 这里写点 Hadoop2.6.0集群的安装和简单配置,一方面是为自 ...
随机推荐
- hql between and 查询
public IList<PrdtStdEntity> QueryPrdtStd(PrdtStdEntity prdtStdEntity) { try { var hql = " ...
- Python: 元组的基本用法
元组和列表是近亲,列表允许并且提供了方法来改变它的值,但元组是不可改变的,即不允许你改变它的值----这也是它没有方法的部分原因. 元组的主要作用是作为参数传递给函数调用.或是从函数调用那里获得参数时 ...
- windows程序里新窗体不在任务栏显示,无标题拖动,键盘事件,始终显示在主窗体上面,单实例运行等
不显示在任务栏,Alt+Tab也不显示 protected override CreateParams CreateParams { get { const int WS_EX_APPWINDOW = ...
- Redis从基础命令到实战之字符串类型
字符串类型是Redis中最基本的数据类型,能存储任何形式的字符串和和二进制数据.本文以代码形式列举常用的操作命令,并在实践部分演示一个简单的商品管理功能,实现了通常使用关系型数据库开发的增改查功能,注 ...
- iOS10以及xCode8相关资料收集
兼容iOS 10 资料整理笔记 源文:http://www.jianshu.com/p/0cc7aad638d9 1.Notification(通知) 自从Notification被引入之后,苹果就不 ...
- Android菜鸟成长记9 -- selector的用法
在项目开发的时候,由于系统给出的控件不够美观,因此开发时领导常常要我更改下界面,用美工给的图片取代系统图片.开始时,我只是给按钮等设置一下背景图片,这样做虽然美观了,但界面看起来却比较死板,比如用户点 ...
- zabbix3.0安装部署文档
zabbix v3.0安装部署 摘要: 本文的安装过程摘自http://www.ttlsa.com/以及http://b.lifec-inc.com ,和站长凉白开的<ZABBIX从入门到精通v ...
- Win32 OpenGL标准例子
在VS2008的MSDN中有一个标准的OpenGL例子,记录如下: /* * Example of a Win32 OpenGL program. * The OpenGL code is the s ...
- java file类的常用方法和属性
1 常用方法 a.createNewFile方法 public boolean createNewFile() throws IOException 该方法的作用是创建指定的文件.该方法只 ...
- python第十八天-----Django基础
1.路由系统 a.普通路由 url(r'^index$', views.index), b.正则路由 url(r'^index/(\d*)', views.index), url(r'^manage/ ...