Hadoop Common源码分析之SerializationFactory、Serialization
SerializationFactory是Hadoop中的一个序列化器工厂,它除了用来存储序列化器种类、更新序列化器相关配置信息,还提供了根据指定待序列化类获取相匹配的序列化器和反序列化器的功能。
SerializationFactory中的关键成员变量只有一个,如下:
private List<Serialization<?>> serializations = new ArrayList<Serialization<?>>();serializations是一个存储实现Serialization接口对象的列表,而Serialization代表了序列化器或反序列化器的公共行为,它实际上是对序列化器/反序列化器对的压缩,列表中的对象其实是(序列化器/反序列化器对)的结合体,提供了以下三个方法:
/** * <p> * Encapsulates a {@link Serializer}/{@link Deserializer} pair. * </p> * @param <T> */ @InterfaceAudience.LimitedPrivate({"HDFS", "MapReduce"}) @InterfaceStability.Evolving public interface Serialization<T> { /** * Allows clients to test whether this {@link Serialization} * supports the given class. * 允许客户端去检测这个Serialization是否支持给定Class */ boolean accept(Class<?> c); /** * 为给定Class获取一个序列化器Serializer * @return a {@link Serializer} for the given class. */ Serializer<T> getSerializer(Class<T> c); /** * 为给定Class获取一个反序列化器Deserializer * @return a {@link Deserializer} for the given class. */ Deserializer<T> getDeserializer(Class<T> c); }很明显,accept(Class<?> c)方法允许客户端去检测这个Serialization是否支持给定Class,getSerializer(Class<T> c)方法为给定Class获取一个序列化器Serializer,而getDeserializer(Class<T> c)方法为给定Class获取一个反序列化器Deserializer。
我们再看SerializationFactory的构造函数,它通过读取配置信息conf中的io.serializations参数来确定Serializations,这个参数是一个逗号隔开的类名列表,代码如下:
/** * <p> * Serializations are found by reading the <code>io.serializations</code> * property from <code>conf</code>, which is a comma-delimited list of * classnames. * 通过读取配置信息conf中的io.serializations参数来确定Serializations,这个参数是一个逗号隔开的类名列表 * </p> */ public SerializationFactory(Configuration conf) { // 调用父类构造函数 super(conf); // 遍历参数io.serializations配置的序列器名称serializerName, // 参数未配置默认为WritableSerialization、AvroSpecificSerialization、AvroReflectSerialization三个 for (String serializerName : conf.getStrings( CommonConfigurationKeys.IO_SERIALIZATIONS_KEY, new String[]{WritableSerialization.class.getName(), AvroSpecificSerialization.class.getName(), AvroReflectSerialization.class.getName()})) { // 调用add(conf, serializerName)方法添加序列化器 add(conf, serializerName); } }构造函数先调用父类构造函数,然后遍历参数io.serializations配置的序列器名称serializerName,参数未配置默认为WritableSerialization、AvroSpecificSerialization、AvroReflectSerialization三个,然后调用add(conf, serializerName)方法添加每个序列化器名称。继续追踪add()方法,代码如下:
@SuppressWarnings("unchecked") private void add(Configuration conf, String serializationName) { try { // 通过类名serializationName获取Class,即serializionClass Class<? extends Serialization> serializionClass = (Class<? extends Serialization>) conf.getClassByName(serializationName); // 通过反射生成类serializionClass的对象,并将其加入到serializations列表 serializations.add((Serialization) ReflectionUtils.newInstance(serializionClass, getConf())); } catch (ClassNotFoundException e) { LOG.warn("Serialization class not found: ", e); } }add()方法很简单,就做了两件事:
1、通过类名serializationName获取Class,即serializionClass;
2、通过反射生成类serializionClass的对象,这个对象其实是(序列化器/反序列化器对)的结合体,并将其加入到serializations列表。
SerializationFactory还提供了为指定类获取序列化器、反序列化器的getSerializer(Class<T> c)和getDeserializer(Class<T> c)方法,代码如下:
// 为指定类c获取序列化器Serializer public <T> Serializer<T> getSerializer(Class<T> c) { // 根据指定类c,调用getSerialization()方法,获取对应序列化器serializer,实际上是确定(序列化器/反序列化器对)对象serializer Serialization<T> serializer = getSerialization(c); if (serializer != null) { // 通过serializer的getSerializer()方法为指定类c获取序列化器的实例 return serializer.getSerializer(c); } // 找不到则返回null return null; } // 为指定类c获取反序列化器Deserializer public <T> Deserializer<T> getDeserializer(Class<T> c) { // 根据指定类c,调用getSerialization()方法,获取对应序列化器serializer,实际上是确定(序列化器/反序列化器对)对象serializer Serialization<T> serializer = getSerialization(c); if (serializer != null) { // 通过serializer的getSerializer()方法为指定类c获取反序列化器的实例 return serializer.getDeserializer(c); } // 找不到则返回null return null; } // 为指定类c获取(序列化器/反序列化器对)对象 @SuppressWarnings("unchecked") public <T> Serialization<T> getSerialization(Class<T> c) { // 遍历serializations列表,获取其中每个Serialization对象serialization for (Serialization serialization : serializations) { // 调用serialization的accept()方法,如果其与c相匹配,则返回该serialization if (serialization.accept(c)) { return (Serialization<T>) serialization; } } // 找不到则返回null return null; }两个方法的处理逻辑一致,大体如下:
1、根据指定类c,调用getSerialization()方法,获取对应序列化器serializer,实际上是确定(序列化器/反序列化器对)对象serializer;
2、通过serializer的getSerializer()方法或getDeserializer()方法为指定类c获取序列化器或发序列化器的实例,并返回;
3、找不到则返回null。
而两者共用的getSerialization()方法则是为指定类c获取(序列化器/反序列化器对)对象,处理逻辑大致为:遍历serializations列表,获取其中每个Serialization对象serialization,调用serialization的accept()方法,如果其与c相匹配,则返回该serialization,找不到则返回null。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
高可用Hadoop平台-应用JAR部署
1.概述 今天在观察集群时,发现NN节点的负载过高,虽然对NN节点的资源进行了调整,同时对NN节点上的应用程序进行重新打包调整,负载问题暂时得到缓解。但是,我想了想,这样也不是长久之计。通过这个问题,我重新分析了一下以前应用部署架构图,发现了一些问题的所在,之前的部署架构是,将打包的应用直接部署在Hadoop集群上,虽然这没什么不好,但是我们分析得知,若是将应用部署在DN节点,那么时间长了应用程序会不会抢占DN节点的资源,那么如果我们部署在NN节点上,又对NN节点计算任务时造成影响,于是,经过讨论后,我们觉得应用程序不应该对Hadoop集群造成干扰,他们应该是属于一种松耦合的关系,所有的应用应该部署在一个AppServer集群上。下面,我就为大家介绍今天的内容。 2.应用部署剖析 由于之前的应用程序直接部署在Hadoop集群上,这堆集群或多或少造成了一些影响。我们知道在本地开发Hadoop应用的时候,都可以直接运行相关Hadoop代码,这里我们只用到了Hadoop的HDFS的地址,那我们为什么不能直接将应用单独部署呢?其实本地开发就可以看作是AppServer集群的一个节点,借助这个思...
- 下一篇
两种配置大数据环境的方法Ambari以及hadoop源代码安装的步骤
1.Ambari安装 Ambari & HDP(Hortonworks Data Platform) ***************************************************************************************************** Base: 0.操作系统原则与对应的HDP对应的版本。rhel6 or rhel7 1.操作系统原则完全安装(Desktop),所有的包都安装。 2.关闭防火墙,IPV6等服务(海涛Python脚本)。SELinux-->>IPv6-->>Iptables _____________________________________________________________ SELINUX: vim /etc/selinux/config SELINUX=disabled 或者: sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config; _________________...
相关文章
文章评论
共有0条评论来说两句吧...