# 序列化
序列化 本文闡述了 Storm 0.6.0 以上版本的序列化機制。在低于 0.6.0 版本的 Storm 中使用了另一種序列化系統,詳細信息可以參考 [Serialization (prior to 0.6.0)](Serialization-(prior-to-0.6.0).html) 一文
Storm 中的 tuple 可以包含任何類型的對象。由于 Storm 是一個分布式系統,所以在不同的任務之間傳遞消息時 Storm 必須知道怎樣序列化、反序列化消息對象。
Storm 使用 [Kryo](https://github.com/EsotericSoftware/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's home page](https://github.com/EsotericSoftware/kryo) 來理解它是怎樣處理自定義的序列化的。
可以通過topology的 topology.kryo.register 屬性來添加自定義序列化生成器。該屬性接收一個注冊器列表,每個注冊項都可以使用以下兩種注冊格式中的一種格式: 1.只有一個待注冊的類的名稱。在這種情況下,Storm 會使用 Kryo 的 FieldsSerializer 來序列化該類。這也許并不一定是該類的最優化方式 —— 可以查看 Kryo 的文檔來了解更多細節內容。 2\. 一個包含待注冊的類的名稱和實現了 [com.esotericsoftware.kryo.Serializer](https://github.com/EsotericSoftware/kryo/blob/master/src/com/esotericsoftware/kryo/Serializer.java)接口的類組成的集合。 我們來看個例子.
```
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`來實現序列化。
Storm provides helpers for registering serializers in a topology config. The [Config](javadocs/org/apache/storm/Config.html) class has a method called `registerSerialization` that takes in a registration to add to the config. 在topology的配置中,Storm 提供了用于注冊序列化生成器的幫助類。[Config](javadocs/org/apache/storm/Config.html) 類有一個 registerSerialization 方法可以將序列化生成器注冊到配置中。
Config 中有一個更高級的配置項做 `Config.TOPOLOGY_SKIP_MISSING_KRYO_REGISTRATIONS`。如果你將該項設置為 true,Storm 會忽略掉所有已注冊但是在topology的類路徑上沒有相應的代碼的序列化器。否則,Storm 會在無法查找到序列化器的時候拋出錯誤。如果你在集群中運行有多個topology并且每個topology都有不同的序列化器,但是你又想要在`storm.yaml`中聲明好所有的序列化器,在這種情況下這個配置項會有很大的幫助。
### Java serialization(java 序列化)
如果 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 基礎
- 概念
- Scheduler(調度器)
- Configuration
- Guaranteeing Message Processing
- 守護進程容錯
- 命令行客戶端
- Storm UI REST API
- 理解 Storm Topology 的 Parallelism(并行度)
- FAQ
- Layers on Top of Storm
- Storm Trident
- Trident 教程
- Trident API 綜述
- Trident State
- Trident Spouts
- Trident RAS API
- Storm SQL
- Storm SQL 集成
- Storm SQL 示例
- Storm SQL 語言參考
- Storm SQL 內部實現
- Flux
- Storm 安裝和部署
- 設置Storm集群
- 本地模式
- 疑難解答
- 在生產集群上運行 Topology
- Maven
- 安全地運行 Apache Storm
- CGroup Enforcement
- Pacemaker
- 資源感知調度器 (Resource Aware Scheduler)
- 用于分析 Storm 的各種內部行為的 Metrics
- Windows 用戶指南
- Storm 中級
- 序列化
- 常見 Topology 模式
- Clojure DSL
- 使用沒有jvm的語言編輯storm
- Distributed RPC
- Transactional Topologies
- Hooks
- Storm Metrics
- Storm 狀態管理
- Windowing Support in Core Storm
- Joining Streams in Storm Core
- Storm Distributed Cache API
- Storm 調試
- 動態日志級別設置
- Storm Logs
- 動態員工分析
- 拓撲事件檢查器
- Storm 與外部系統, 以及其它庫的集成
- Storm Kafka Integration
- Storm Kafka 集成(0.10.x+)
- Storm HBase Integration
- Storm HDFS Integration
- Storm Hive 集成
- Storm Solr 集成
- Storm Cassandra 集成
- Storm JDBC 集成
- Storm JMS 集成
- Storm Redis 集成
- Azue Event Hubs 集成
- Storm Elasticsearch 集成
- Storm MQTT(Message Queuing Telemetry Transport, 消息隊列遙測傳輸) 集成
- Storm MongoDB 集成
- Storm OpenTSDB 集成
- Storm Kinesis 集成
- Storm Druid 集成
- Storm and Kestrel
- Container, Resource Management System Integration
- Storm 高級
- 針對 Storm 定義一個不是 JVM 的 DSL
- 多語言協議
- Storm 內部實現
- 翻譯進度