使用Kryo的序列化方式提高Netty性能

爲何選擇Kryo?java

首先,Kryo的序列化方式,在性能方面是比較好的,和Protobuf差很少,比Java原生的序列化方式快多了。因爲本篇文章主要想說明Kryo和Netty的整合,因此關於Kryo序列化的原理請查閱其餘文章。git

其次,Protobuf是個跨語言的解決方案,須要預先定義schema,而後經過預編譯生成代碼。若是是Java單語言調用,Kryo是更好的選擇,不須要預編譯,不須要schema。github

使用鏈接池
apache

Kryo對象非線程安全,可是頻繁new會形成巨大的性能損耗,因此應該使用鏈接池。推薦使用apache的commons-pool2。安全

使用Kryo序列化對象要注意的地方性能

  1. 正常狀況下,須要被序列化的對象有默認的無參構造器。測試

  2. 不須要實現Serializable接口。spa

  3. 若是想使用不帶無參構造器的對象也能正確反序列化,能夠考慮kryo-serializers包,使用其提供的KryoReflectionFactorySupport,會採用jdk的ReflectionFactory反射的生成對象。該方式不須要提供默認的構造器也能夠成功反序列化,可是因爲不調用構造器,若是在構造器中維護了別的類的狀態, 會致使別的類狀態失效。因此最佳實踐是,構造器最好只用於初始化本類的屬性。注意:若是使用KryoReflectionFactorySupport而致使錯誤,有可能不拋異常,而是狀態直接錯誤,很難調試,建議謹慎使用。線程

  4. 若是調用了List的sublist方法生成的SubList對象,或者使用Arrays.asList方法生成的對象,都不能正確的序列化。仍然可使用kryo-serializers包所提供的SubListSerializers,ArraysAsListSerializer等完成正確序列化。調試

  5. 對於自定義的特殊類,能夠自定義實現FieldSerialier的create方法,並註冊到Kryo的實例化對象中去。

使用Kryo做爲Netty序列化對象的協議

  1. 經過實現MessageToByteEncoder接口,實現encode對象

  2. 經過實現LengthFieldBasedFrameDecoder接口,實現decode對象

  3. 作了一下測試,發送1萬次請求,java內置序列化耗時6.776秒,Kryo耗時3.160秒;發送10萬次請求,java內置序列化耗時48.555秒,Kryo耗時15.423秒。固然這個數據因環境而異,可是提高效果很是顯著。

具體代碼可參見:

Kryo序列化部分:https://github.com/terrymanu/miracle-framework/tree/master/miracle-framework-common/miracle-framework-common-serialize

Kryo和Netty整合部分:https://github.com/terrymanu/miracle-framework/tree/master/miracle-framework-remote/miracle-framework-remote-netty

相關文章
相關標籤/搜索