Netty的Marshalling编解码器

1、编码与解码
    通常我们习惯将编码(Encode)称为序列化(serialization),它将对象序列化为字节数组,用于网络传输、数据持久化或者其它用途。反之,解码(Decode)称为反序列化(deserialization),它把从网络、磁盘等读取的字节数组还原成原始对象(通常是原始对象的拷贝),以方便后续的业务逻辑操作。

2、java序列化
        Java默认提供的序列化机制,需要序列化的Java对象只需要实现java.io.Serializable接口并生成序列化ID,这个类就能够通过java.io.ObjectInput和java.io.ObjectOutput序列化和反序列化。可以直接把Java对象作为可存储的字节数组写入文件,也可以传输到网络上。

2.1 java序列化的缺点      
        无法跨语言。

序列化后码流太大。

序列化性能太低。

3、其他编解码框架
        Java默认的序列化机制效率很低、序列化后的码流也较大,所以涌现出了非常多的优秀的Java序列化框架,例如:Protobuf(google)、Thrift(facebook)、JBoss Marshalling(JBoss)等等。  
    3.1 Protobuf(google)
        Protobuf是google开源的项目,全称Google Protocol Buffers.特点:

1.结构化数据存储格式(xml,json等)

2.高性能编解码技术

3.语言和平台无关,扩展性好

4.支持java,C++,Python三种语言。

3.2 JBoss Marshalling(JBoss)
        JBoss Marshalling是一个java对象的序列化API包,修正了java自带的序列化包的很多问题,但又保持跟java.io.Serializable接口的兼容,

同时又增加了一些可调的参数和附加特性,并且这些参数和特性可通过工厂类的配置。特点:

1.可拔插的类解析器,提供更加便捷的类加载定制策略,通过一个接口即可实现定制。

2.可拔插的对象替换技术,不需要通过继承的方式。

3.可拔插的预定义类缓存表,可以减少序列化的字节数组长度,提升常用类型的对象序列化性能。

4.无须实现java.io.Serializable接口

5.通过缓存技术提升对象的序列化性能。

6.使用非常简单

代码实现

类库:jboss-marshalling-1.3.0.CR9.jar jboss-marshalling-serial-1.3.0.CR9.jar

下载地址:https://www.jboss.org/jbossmarshalling/downloads

我所用的jar 包为 https://pan.baidu.com/s/1tm2EgYtDpTS5dejVnHhvPw 密码:vc8b

1、客户端实体类

package com.xyq.netty.serial;

import java.io.Serializable;

public class Request implements Serializable{

private static final long serialVersionUID = 1L;

private int id;
private String name;
private String requestMessage;

public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRequestMessage() {
return requestMessage;
}
public void setRequestMessage(String requestMessage) {
this.requestMessage = requestMessage;
}

}

2、服务器端实体类
package com.xyq.netty.serial;

import java.io.Serializable;

public class Response implements Serializable{

private static final long serialVersionUID = 1L;

private int id;
private String name;
private String responseMessage;

public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getResponseMessage() {
return responseMessage;
}
public void setResponseMessage(String responseMessage) {
this.responseMessage = responseMessage;
}

}

3、JBoss marshalling编解码工具类
package com.xyq.netty.serial;

import io.netty.handler.codec.marshalling.DefaultMarshallerProvider;
import io.netty.handler.codec.marshalling.DefaultUnmarshallerProvider;
import io.netty.handler.codec.marshalling.MarshallerProvider;
import io.netty.handler.codec.marshalling.MarshallingDecoder;
import io.netty.handler.codec.marshalling.MarshallingEncoder;
import io.netty.handler.codec.marshalling.UnmarshallerProvider;

import org.jboss.marshalling.MarshallerFactory;
import org.jboss.marshalling.Marshalling;
import org.jboss.marshalling.MarshallingConfiguration;

public class MarshallingCodeCFactory {

public static MarshallingDecoder buliteMarshallingDecoder(){

//1、首先通过编组工具类的精通方法获取编组实例对象参数序列标识创建的是java序列化工厂对象。
final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
//2、创建了MarshallingConfiguration对象,配置了版本号为5
final MarshallingConfiguration configuration = new MarshallingConfiguration();
configuration.setVersion(5);
//3、根据marshallerFactory和配置创建提供商
UnmarshallerProvider provider = new DefaultUnmarshallerProvider(marshallerFactory, configuration);
//4、构建Netty的MarshallingDecoder对象,两个参数分别为提供商和单个消息序列化后的最大长度
MarshallingDecoder decoder = new MarshallingDecoder(provider, 1024*1024*1);
return decoder;
}

public static MarshallingEncoder buliteMarshallingEncoder(){
final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
final MarshallingConfiguration configuration = new MarshallingConfiguration();
configuration.setVersion(5);
MarshallerProvider provider = new DefaultMarshallerProvider(marshallerFactory, configuration);
//5、构建Netty的MarshallingEncoder对象,MarshallingEncoder用于实现序列化接口的POJO对象序列化为二进制数组
MarshallingEncoder encoder = new MarshallingEncoder(provider);
return encoder;
}

}

4、服务器端

package com.xyq.netty.serial;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class Server {

public static void main(String[] args) throws Exception{
//1、定义两个线程组
EventLoopGroup pGroup = new NioEventLoopGroup();//一个是用于处理服务器端接收客户端连接的
EventLoopGroup cGroup = new NioEventLoopGroup();//一个是进行网络通信的(网络读写的)
try {
//2、创建辅助工具类,用于服务器通道的一系列配置
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(pGroup, cGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 1024)
.option(ChannelOption.SO_SNDBUF, 32*1024)
.option(ChannelOption.SO_RCVBUF, 32*1024)
.childHandler(new ChannelInitializer<SocketChannel>() {

@Override
protected void initChannel(SocketChannel ch) throws Exception {

//设置marshalling编码
ch.pipeline().addLast(MarshallingCodeCFactory.buliteMarshallingDecoder());
//设置marshalling解码
ch.pipeline().addLast(MarshallingCodeCFactory.buliteMarshallingEncoder());
//处理业务
ch.pipeline().addLast(new ServerHandler());
}
});

//4、进行绑定
ChannelFuture cf = bootstrap.bind(8765).sync();
System.out.println("server start ...");

//5、等待关闭
cf.channel().closeFuture().sync();
} finally{
pGroup.shutdownGracefully();
cGroup.shutdownGracefully();
}

}

}

5、服务器处理类

package com.xyq.netty.serial;

import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;

public class ServerHandler extends ChannelHandlerAdapter{

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)throws Exception {

//读取客户端发过来的信息
Request request = (Request) msg;
System.out.println("服务器接收到客户端的信息为 " + request.getId() + " " + request.getName());

//给客户端回应信息
Response response = new Response();
response.setId(request.getId());
response.setName(request.getName()+"res");
ctx.writeAndFlush(response);
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)throws Exception {
ctx.close();
}

}

6、客户端

package com.xyq.netty.serial;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

public class Client {

public static void main(String[] args) throws Exception{
//创建线程组
EventLoopGroup group = new NioEventLoopGroup();
try {
//创建工具类
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {

@Override
protected void initChannel(SocketChannel ch) throws Exception {

//设置marshalling解码
ch.pipeline().addLast(MarshallingCodeCFactory.buliteMarshallingDecoder());
//设置marshalling编码
ch.pipeline().addLast(MarshallingCodeCFactory.buliteMarshallingEncoder());

ch.pipeline().addLast(new ClientHandler());
}
});

//4、建立连接
ChannelFuture cf = bootstrap.connect("127.0.0.1", 8765).sync();
System.out.println("Client connet ....");

//5、发送信息
for(int i=0; i<5; i++){
Request request = new Request();
request.setId(i);
request.setName("request" + i);
cf.channel().writeAndFlush(request);
}

//6、等待关闭
cf.channel().closeFuture().sync();
} finally{
group.shutdownGracefully();
}
}

}

7、客户端处理类

package com.xyq.netty.serial;

import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil;

public class ClientHandler extends ChannelHandlerAdapter {

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)throws Exception {

try {
//接收服务端的响应信息
Response response = (Response) msg;
System.out.println("客户端接收到服务端的响应消息为 " + response.getId() +" " + response.getName());
} finally{
ReferenceCountUtil.release(msg);
}
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)throws Exception {
ctx.close();
}
}

原文地址:https://www.cnblogs.com/651434092qq/p/11765581.html

时间: 2024-10-18 13:05:11

Netty的Marshalling编解码器的相关文章

编解码-marshalling

JBoss的Marshalling序列化框架,它是JBoss内部使用的序列化框架,Netty提供了Marshalling编码和解码器,方便用户在Netty中使用Marshalling. JBoss Marshalling是一个Java对象序列化包,对JDK默认的序列化框架进行了优化,但又保持跟java.io.Serializable接口的兼容,同时增加了一些可调的参数和附加的特性,这些参数和特性可通过工厂类进行配置. import lombok.Data; import java.io.Seri

【Netty】(9)---Netty编解码器

Netty编解码器 在了解Netty编解码之前,先了解Java的编解码: 编码(Encode)称为序列化, 它将对象序列化为字节数组,用于网络传输.数据持久化或者其它用途. 解码(Decode)称为反序列化,它把从网络.磁盘等读取的字节数组还原成原始对象(通常是原始对象的拷贝),以方便后续的业务逻辑操作. java序列化对象只需要实现java.io.Serializable接口并生成序列化ID,这个类就能够通过java.io.ObjectInput和java.io.ObjectOutput序列化

Netty权威指南

Netty权威指南(异步非阻塞通信领域的经典之作,国内首本深入剖析Netty的著作,全面系统讲解原理.实战和源码,带你完美进阶Netty工程师.) 李林锋 著   ISBN 978-7-121-23343-2 2014年6月出版 定价:79.00元 524页 16开 编辑推荐 - 资深一线专家诚意之作,总结多年实践经验,带你全面掌握Java高并发异步通信的首选框架——Netty. - Facebook.阿里巴巴.1号店.并发编程网.JBoss等多位资深技术专家联名力荐. <Netty权威指南>

Netty5 序列化方式(Jboss Marshalling)

Netty作为很多高性能的底层通讯工具,被很多开发框架应用再底层,今天来说说常用的序列化工具,用Jboss的Marshalling. 直接上代码,Marshalling的工厂类 package com.netty.serialize.marshalling; import io.netty.handler.codec.marshalling.*; import org.jboss.marshalling.MarshallerFactory; import org.jboss.marshallin

Netty with protobuf(二)

上一篇了解了protobuf,现在结合netty做一个例子. 关键就是配置netty的编解码器,因为netty提供了protobuf的编解码器,所以我们可以很容易的使用netty提供的编解码器使用protobuf数据交换协议进行通信.. 下面是示例代码,对于了解的netty的同学应该不难看懂.. 服务器端程序: ProtobufNettyServer.java package com.example.tutorial; import io.netty.bootstrap.ServerBootst

Netty专题(四)-----Bootstrap、ByteBuf、编码解码

引导Bootstrap 我们把前面的用例称作引导一个服务器,后面的用例称作引导一个客户端.虽然这个术语简单方便,但是它略微掩盖了一个重要的事实,即“服务器”和“客户端”实际上表示了不同的网络行为:换句话说,是监听传入的连接还是建立到一个或者多个进程的连接.因此,有两种类型的引导:一种用于 客户端(简单地称为Bootstrap),而另一种(ServerBootstrap)用于服务器.无论你的应用程序使用哪种协议或者处理哪种类型的数据,唯一决定它使用哪种引导类的是它是作为一个客户端还是作为一个服务器

一个入门rpc框架的学习

一个入门rpc框架的学习 参考 huangyong-rpc 轻量级分布式RPC框架 该程序是一个短连接的rpc实现 简介 RPC,即 Remote Procedure Call(远程过程调用),说得通俗一点就是:调用远程计算机上的服务,就像调用本地服务一样. RPC 可基于 HTTP 或 TCP 协议,Web Service 就是基于 HTTP 协议的 RPC, 它具有良好的跨平台性,但其性能却不如基于 TCP 协议的 RPC.会两方面会直接影响 RPC 的性能,一是传输方式,二是序列化. 众所

Netty-解码器架构与常用解码器

任何数据类型想在网络中进行传输,都得经过编解码转换成字节流 在netty中,服务端和客户端进行通信的其实是下面这样的 程序 ---编码--> 网络 网路 ---解码--> 程序 对应服务端: 入站数据, 经过解码器解码后给后续的handler使用 出站数据, 结果编码器编码成字节流给在网络上传播 在netty中的编码器其实就是一个handler,回想一下,无论是编写服务端的代码,还是客户端的代码,总会通过一个channelIniteializer往pipeline中动态的添加多个处理器,在添加

Netty实战十一之预置的ChannelHandler和编解码器

Netty为许多通用协议提供了编解码器和处理器,几乎可以开箱即用,这减少了你在那些相当繁琐的事务上本来会花费的时间与精力.我们将探讨这些工具以及它们所带来的好处,其中包括Netty对于SSL/TLS和WebSocket的支持,以及如何简单地通过数据压缩来压榨HTTP,以获取更好的性能. 1.通过SSL/TLS保护Netty应用程序 SSL和TLS这样的安全协议,它们层叠在其他协议之上,用以实现数据安全.我们在访问安全网站时遇到过这些协议,但是它们也可用于其他不是基于HTTP的应用程序,如安全SM