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序列化的更多相关文章

  1. 【原】storm源码之storm代码结构【译】

    说明:本文翻译自Storm在GitHub上的官方Wiki中提供的Storm代码结构描述一节Structure of the codebase,希望对正在基于Storm进行源码级学习和研究的朋友有所帮助 ...

  2. storm源码之storm代码结构【译】【转】

    [原]storm源码之storm代码结构[译]  说明:本文翻译自Storm在GitHub上的官方Wiki中提供的Storm代码结构描述一节Structure of the codebase,希望对正 ...

  3. php 序列化(serialize)格式详解

    1.前言 PHP (从 PHP 3.05 开始)为保存对象提供了一组序列化和反序列化的函数:serialize.unserialize.不过在 PHP 手册中对这两个函数的说明仅限于如何使用,而对序列 ...

  4. storm源码之storm代码结构【译】

    storm源码之storm代码结构[译] 说明:本文翻译自Storm在GitHub上的官方Wiki中提供的Storm代码结构描述一节Structure of the codebase,希望对正在基于S ...

  5. Strom序列化机制

    Storm 中的 tuple可以包含任何类型的对象.由于Storm 是一个分布式系统,所以在不同的任务之间传递消息时Storm必须知道怎样序列化.反序列化消息对象. Storm 使用 Kryo库对对象 ...

  6. 序列化、time、random、hashlib、sys模块

    •很多常用和内置模块,我们只需要掌握他们的用法而暂时不用考虑内部是如何实现的,这些模块大大提升了开发效率 ! 1.json模块与pickle模块 •json 如果你有这样的困扰,当希望把一种数据存到硬 ...

  7. day72_10_17 序列化组件之model的运用

    一.拆分的序列化. model序列化的基本用法就是使用元类中的fields,其中model绑定的就是model中的表 如果需要多表查询,要在model中定义property: class BookMo ...

  8. drf框架 - 序列化组件 | ModelSerializer (查,增,删,改)

    ModelSerializer 序列化准备: 配置 settings.py # 注册rest_framework框架 INSTALLED_APPS = [ ... 'rest_framework' ] ...

  9. drf序列化单改-整改-局部改-群改接口的实现

    整体单改 路由层.模型层.序列化层不需要做修改,只需要处理视图层:views.py """ 1) 单整体改,说明前台要提供修改的数据,那么数据就需要校验,校验的数据应该在 ...

随机推荐

  1. lintcode:哈希函数

    题目: 哈希函数 在数据结构中,哈希函数是用来将一个字符串(或任何其他类型)转化为小于哈希表大小且大于等于零的整数.一个好的哈希函数可以尽可能少地产生冲突.一种广泛使用的哈希函数算法是使用数值33,假 ...

  2. leetcode 5 :Longest Palindromic Substring 找出最长回文子串

    题目: Given a string S, find the longest palindromic substring in S. You may assume that the maximum l ...

  3. Sina App Engine(SAE)入门教程(5)- SaeSegment(中文分词服务)使用

    分词能干什么? 提取一篇文章的关键字 检测特定的段落中有没有违禁词 智能机器人 …..尽你所想 开启SAE 分词服务 首先你需要在sae的管理面板开始分词服务后才能使用sae的服务.具体的开启操作: ...

  4. Socket称"套接字"

    Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求. 二.利用Socket建立网络连接的步骤 建立Socket连接至少需要一对 ...

  5. java工具类–自动将数据库表生成javabean

    最近和数据库的表打交道挺多的,因为暂时做的是接口活. 在这过程中发现要把表转换成对应的javabean类型,字段少的表还行,如果不小心碰到几十个字段的他妈的写起来就有点麻烦了,万一碰到几百个的呢,那不 ...

  6. Spring IoC — 基于XML的配置

    1.属性注入 注意点: 1)如果类中显示定义了一个带参的构造函数,则一定还要显示提供一个无参构造函数,否则使用属性注入时将抛出异常. 2)JavaBean关于属性命名的特殊规范.Spring只会检查B ...

  7. latex 三线表

    LaTeX 处理三线表相当简单方便.用到的宏包主要是 booktabs .代码如下: 需要添加包:\usepackage{booktabs}. \documentclass{article} \use ...

  8. 配置hibernate根据实体类自动建表功能

    Hibernate支持自动建表,在开发阶段很方便,可以保证hbm与数据库表结构的自动同步. 如何使用呢?很简单,只要在hibernate.cfg.xml里加上如下代码 Xml代码<propert ...

  9. 严重: Catalina.stop: java.net.ConnectException: Connection refused: connect

    原因: 1.连接被拒绝,关闭的时候报错.是不是已经关闭了,你又关闭,他当然找不到了. 2.连接被拒绝有可能是服务端连接数到达最高了 3.服务器拒绝连接,ip地址是否写对,端口号正确与否,网络是否通畅, ...

  10. bzoj2251

    以前看到这道题想到的是SA,做起来不是很美观 学了SAM之后,这题简直是随便搞 ..,'] of longint; s,sa,mx,w,fa:..] of longint; i,n,last,t:lo ...