使用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

相关文章
相关标签/搜索