【原】Storm序列化
5. Storm高级篇
序列化
Dynamic typing
Custom serialization
Java serialization
Component-specific serialization registrations
分布式RPC
序列化
本文阐述了 Storm 0.6.0 以上版本的序列化机制。在低于 0.6.0 版本的 Storm 中使用了另一种序列化系统,详细信息可以参考 Serialization (prior to 0.6.0) 一文。
Storm 中的 tuple 可以包含任何类型的对象。由于 Storm 是一个分布式系统,所以在不同的任务之间传递消息时 Storm 必须知道怎样序列化、反序列化消息对象。
Storm 使用 Kryo库 对对象进行序列化。Kryo 是一个灵活、快速的序列化库。Storm 默认支持基础类型、string、byte arrays、ArrayList、HashMap、HashSet 以及 Clojure 的集合类型的序列化。如果你需要在 tuple 中使用其他的对象类型,你就需要注册一个自定义的序列化器。
Dynamic typing
在 tuple 中没有对各个域(field)的直接类型声明。你需要将对象放入对应的域中,然后 Storm 可以动态地实现对象的序列化。在学习序列化接口之前,我们先来了解一下为什么 Storm 的 tuple 是动态类型化的。
为 tuple fields 增加静态类型会大幅增加 Storm 的 API 的复杂度。比如 Hadoop 就将它的 key 和 value 都静态化了,这就要求用户自己添加大量的注解。使用 Hadoop 的 API 非常繁琐,而相应的“类型安全”不值得。相对的,动态类型就非常易于使用。
进一步说,也不可能有什么合理的方法将 Storm 的 tuple 的类型静态化。假如一个 Bolt 订阅了多个 stream,从这些 stream 传入的 tuple 很可能都带有不同的类型。在 Bolt 的 execute 方法接收到一个 tuple 的时候,这个 tuple 可能来自任何一个 stream,也可能包含各种组合类型。也许你可以使用某种反射机制来为 bolt 订阅的每个 tuple stream 声明一个方法类处理 tuple,但是 Storm 可以提供一种更简单、更直接的动态类型机制来解决这个问题。
最后,Storm 使用动态类型定义的另一个原因就是为了用简洁直观的方式使用 Clojure、JRuby 这样的动态类型语言。
Custom serialization
前面已经提到,Storm 使用 Kryo 来处理序列化。如果要实现自定义的序列化生成器,你需要用Kryo注册一个新的序列化生成器。强烈建议读者先仔细阅读 Kryo主页 来理解它是怎样处理自定义的序列化的。
可以通过topology的 topology.kryo.register 属性来添加自定义序列化生成器。该属性接收一个注册器列表,每个注册项都可以使用以下两种注册格式中的一种格式:
1.只有一个待注册的类的名称。在这种情况下,Storm 会使用 Kryo 的 FieldsSerializer 来序列化该类。这也许并不一定是该类的最优化方式 —— 可以查看 Kryo 的文档来了解更多细节内容。
2.一个包含待注册的类的名称和实现了com.esotericsoftware.kryo.Serializer接口的类组成的集合。
举例:
topology.kryo.register:
- com.mycompany.CustomType1
- com.mycompany.CustomType2: com.mycompany.serializer.CustomType2Serializer
- com.mycompany.CustomType3
com.mycompany.CustomType1 和 com.mycompany.CustomType3 会使用 FieldsSerializer,而com.mycompany.CustomType2 则会使用 com.mycompany.serializer.CustomType2Serializer来实现序列化。
在topology的配置中,Storm 提供了用于注册序列化生成器的帮助类。Config 类有一个 registerSerialization 方法可以将序列化生成器注册到配置中。
Config 中有一个更高级的配置项做 Config.TOPOLOGY_SKIP_MISSING_KRYO_REGISTRATIONS。如果你将该项设置为 true,Storm 会忽略掉所有已注册但是在topology的类路径上没有相应的代码的序列化器。否则,Storm 会在无法查找到序列化器的时候抛出错误。如果你在集群中运行有多个topology并且每个topology都有不同的序列化器,但是你又想要在storm.yaml 中声明好所有的序列化器,在这种情况下这个配置项会有很大的帮助。
Java serialization
如果 Storm 发现了一个没有注册序列化器的类型,它会使用 Java 序列化器来代替,如果这个对象无法被 Java 序列化器序列化,Storm 就会抛出异常。
注意,Java 自身的序列化机制非常耗费资源,而且不管在 CPU 的性能上还是在序列化对象的大小上都没有优势。强烈建议读者在生产环境中运行topology 的时候注册一个自定义的序列化器。保留 Java 的序列化机制主要为了便于设计新topology 的原型。
你可以通过将 Config.TOPOLOGY_FALL_BACK_ON_JAVA_SERIALIZATION 配置为 false 的方式来将序列化器回退到 Java 的序列化机制。
Component-specific serialization registrations
Storm 0.7.0 支持对特定组件的配置(详情请参阅Storm配置一文)。当然,如果某个组件定义了一个序列化器,这个序列化器也需要能够支持其他的 bolt —— 否则,后续的 bolt 将会无法接收来自该组件的消息!
在提交topology 的时候,topology 会选择一组序列化器用于在所有的组件间传递消息。这是通过将特定组件的序列化器注册信息与普通的序列化器信息融合在一起实现的。如果两个组件为同一个类定义了两个序列化器,Storm 会从中任意选择一个。
如果在两个组件的序列化器注册信息冲突的时候需要强制使用一个序列化器,可以在topology 级的配置中定义你想要的序列化器。对于序列化器的注册信息,拓扑中配置的值是优先于具体组件的配置的。
【原】Storm序列化的更多相关文章
- 【原】storm源码之storm代码结构【译】
说明:本文翻译自Storm在GitHub上的官方Wiki中提供的Storm代码结构描述一节Structure of the codebase,希望对正在基于Storm进行源码级学习和研究的朋友有所帮助 ...
- storm源码之storm代码结构【译】【转】
[原]storm源码之storm代码结构[译] 说明:本文翻译自Storm在GitHub上的官方Wiki中提供的Storm代码结构描述一节Structure of the codebase,希望对正 ...
- php 序列化(serialize)格式详解
1.前言 PHP (从 PHP 3.05 开始)为保存对象提供了一组序列化和反序列化的函数:serialize.unserialize.不过在 PHP 手册中对这两个函数的说明仅限于如何使用,而对序列 ...
- storm源码之storm代码结构【译】
storm源码之storm代码结构[译] 说明:本文翻译自Storm在GitHub上的官方Wiki中提供的Storm代码结构描述一节Structure of the codebase,希望对正在基于S ...
- Strom序列化机制
Storm 中的 tuple可以包含任何类型的对象.由于Storm 是一个分布式系统,所以在不同的任务之间传递消息时Storm必须知道怎样序列化.反序列化消息对象. Storm 使用 Kryo库对对象 ...
- 序列化、time、random、hashlib、sys模块
•很多常用和内置模块,我们只需要掌握他们的用法而暂时不用考虑内部是如何实现的,这些模块大大提升了开发效率 ! 1.json模块与pickle模块 •json 如果你有这样的困扰,当希望把一种数据存到硬 ...
- day72_10_17 序列化组件之model的运用
一.拆分的序列化. model序列化的基本用法就是使用元类中的fields,其中model绑定的就是model中的表 如果需要多表查询,要在model中定义property: class BookMo ...
- drf框架 - 序列化组件 | ModelSerializer (查,增,删,改)
ModelSerializer 序列化准备: 配置 settings.py # 注册rest_framework框架 INSTALLED_APPS = [ ... 'rest_framework' ] ...
- drf序列化单改-整改-局部改-群改接口的实现
整体单改 路由层.模型层.序列化层不需要做修改,只需要处理视图层:views.py """ 1) 单整体改,说明前台要提供修改的数据,那么数据就需要校验,校验的数据应该在 ...
随机推荐
- mysql级联更新的两种方式:触发器更新和外键
1.mysql级联更新有两种方式:触发器更新和外键更新. 2.触发器更新和外键更新的目的都是为了保证数据完整性. 我们通常有这样的需求:删除表Table 1中记录,需要同时删除其它表中与Table 1 ...
- Error building Player: Win32Exception: ApplicationName=‘xxxxxxxxxxxxxxxxxx//sdk\tools\zipalign.exe' , CommandLine='4 的解决办法
更新了安卓SDK后,有时候Unity编译失失败,报错类似 Error building Player: Win32Exception: ApplicationName='D:/Program File ...
- iOS 开发中遇到的问题
1. 关于纠结很久的KVO崩溃问题,其真正原因是,在删除roomItem的KVO之前,将这个对象已经赋值为nil,所以实际上并没有删除他的observer,因此而崩溃:长时间纠结的原因是受.cxx_d ...
- 一个不错的log4j.properties例子
# Set root logger level to WARN and append to stdout #在开发环境下日志级别要设置成DEBUG,生产环境设置成info或error log4j.ro ...
- Android之NDK编程(JNI)
转自:http://www.cnblogs.com/xw022/archive/2011/08/18/2144621.html NDK编程入门--C回调JAVA方法 一.主要流程 1. 新建一个 ...
- oj放苹果
题目描述 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法. 输入 每个用例包含二个整数M和N.0<=m< ...
- bzoj1562
很明显是二分图匹配,关键是怎么求字典序最小 想到两种做法,首先是直接匹配,然后从第一位贪心调整 第二种是从最后一个倒着匹配,每次匹配都尽量选小的,这样一定能保证字典序最小 type node=reco ...
- UVa 1025 (动态规划) A Spy in the Metro
题意: 有线性的n个车站,从左到右编号分别为1~n.有M1辆车从第一站开始向右开,有M2辆车从第二站开始向左开.在0时刻主人公从第1站出发,要在T时刻回见车站n 的一个间谍(忽略主人公的换乘时间).输 ...
- POJ 1088 滑雪【记忆化搜索】
题意:给出一个二维矩阵,要求从其中的一点出发,并且当前点的值总是比下一点的值大,求最长路径 记忆化搜索,首先将d数组初始化为0,该点能够到达的路径长度保存在d数组中,同时把因为路径是非负的,所以如果已 ...
- main cannot be resolved or is not a field
今天在做XML解析的时候,总是给我报 XML Parsing Error: XML or text declaration not at start of entity 的错误,后来查了下讲大概意思是 ...