motan源码分析七:序列化
motan的序列化支持两种协议,一种是json,另一种是hessian2。主要涉及到的类和接口是是:FastJsonSerialization、Hessian2Serialization、Serialization、Codec、AbstractCodec、NettyDecoder、NettyEncoder、DefaultRpcCodec和CompressRpcCodec等。
1.FastJsonSerialization使用json作为数据交换协议,Hessian2Serialization使用hessian2作为数据交换协议
@SpiMeta(name = "hessian2")
public class Hessian2Serialization implements Serialization { @Override
public byte[] serialize(Object data) throws IOException {//使用hessan2进行序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
Hessian2Output out = new Hessian2Output(bos);
out.writeObject(data);
out.flush();
return bos.toByteArray();
} @SuppressWarnings("unchecked")
@Override
public <T> T deserialize(byte[] data, Class<T> clz) throws IOException {//使用hessan2进行反序列化
Hessian2Input input = new Hessian2Input(new ByteArrayInputStream(data));
return (T) input.readObject(clz);
}
}
2.motan支持压缩和非压缩两种方式
public byte[] encode(Channel channel, Object message) throws IOException {
if (needEncodeV1(message)) {//判断使用哪个版本的encode,decode同样
return v1Codec.encode(channel, message);
} else {
// 使用v2压缩版本
return encodeV2(channel, message);//使用压缩版本的encode
}
}
public byte[] encodeV2(Channel channel, Object message) throws IOException {
try {
if (message instanceof Request) {
return encodeRequest(channel, (Request) message);//序列化并压缩request对象
} else if (message instanceof Response) {
return encodeResponse(channel, (Response) message);//序列化并压缩response对象
}
} catch (Exception e) {
if (ExceptionUtil.isMotanException(e)) {
throw (RuntimeException) e;
} else {
throw new MotanFrameworkException("encode error: isResponse=" + (message instanceof Response), e,
MotanErrorMsgConstant.FRAMEWORK_ENCODE_ERROR);
}
}
throw new MotanFrameworkException("encode error: message type not support, " + message.getClass(),
MotanErrorMsgConstant.FRAMEWORK_ENCODE_ERROR);
}
private byte[] encodeRequest(Channel channel, Request request) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput output = createOutput(outputStream);
addMethodInfo(output, request);
//拿到hessian2或fasjson处理对象
Serialization serialization =
ExtensionLoader.getExtensionLoader(Serialization.class).getExtension(
channel.getUrl().getParameter(URLParamType.serialize.getName(), URLParamType.serialize.getValue()));
if (request.getArguments() != null && request.getArguments().length > 0) {
for (Object obj : request.getArguments()) {
serialize(output, obj, serialization);//序列化
}
}
if (request.getAttachments() == null || request.getAttachments().isEmpty()) {
// empty attachments
output.writeShort(0);
} else {
// 需要copy一份attachment进行签名替换,这样在失败重试时原始的request信息不会变更
Map<String, String> attachments = copyMap(request.getAttachments());
replaceAttachmentParamsBySign(channel, attachments);
addAttachment(output, attachments);
}
output.flush();
byte[] body = outputStream.toByteArray();
byte flag = MotanConstants.FLAG_REQUEST;
output.close();
Boolean usegz = channel.getUrl().getBooleanParameter(URLParamType.usegz.getName(), URLParamType.usegz.getBooleanValue());
int minGzSize = channel.getUrl().getIntParameter(URLParamType.mingzSize.getName(), URLParamType.mingzSize.getIntValue());
return encode(compress(body, usegz, minGzSize), flag, request.getRequestId());//压缩处理
}
3.通过NettyDecoder和NettyEncoder与netty框架进行结合
protected Object encode(ChannelHandlerContext ctx, Channel nettyChannel, Object message) throws Exception {
long requestId = getRequestId(message);//获取requestId
byte[] data = null;
if (message instanceof Response) {
try {
data = codec.encode(client, message);
} catch (Exception e) {
LoggerUtil.error("NettyEncoder encode error, identity=" + client.getUrl().getIdentity(), e);
Response response = buildExceptionResponse(requestId, e);
data = codec.encode(client, response);
}
} else {
data = codec.encode(client, message);//调用DefaultRpcCodec或压缩的codec来编码
}
byte[] transportHeader = new byte[MotanConstants.NETTY_HEADER];
ByteUtil.short2bytes(MotanConstants.NETTY_MAGIC_TYPE, transportHeader, 0);
transportHeader[3] = getType(message);
ByteUtil.long2bytes(getRequestId(message), transportHeader, 4);
ByteUtil.int2bytes(data.length, transportHeader, 12);
return ChannelBuffers.wrappedBuffer(transportHeader, data);
}
motan源码分析七:序列化的更多相关文章
- motan源码分析六:客户端与服务器的通信层分析
本章将分析motan的序列化和底层通信相关部分的代码. 1.在上一章中,有一个getrefers的操作,来获取所有服务器的引用,每个服务器的引用都是由DefaultRpcReferer来创建的 pub ...
- ABP源码分析七:Setting 以及 Mail
本文主要说明Setting的实现以及Mail这个功能模块如何使用Setting. 首先区分一下ABP中的Setting和Configuration. Setting一般用于需要通过外部配置文件(或数据 ...
- vuex 源码分析(七) module和namespaced 详解
当项目非常大时,如果所有的状态都集中放到一个对象中,store 对象就有可能变得相当臃肿. 为了解决这个问题,Vuex允许我们将 store 分割成模块(module).每个模块拥有自己的 state ...
- Vue.js 源码分析(七) 基础篇 侦听器 watch属性详解
先来看看官网的介绍: 官网介绍的很好理解了,也就是监听一个数据的变化,当该数据变化时执行我们的watch方法,watch选项是一个对象,键为需要观察的数据名,值为一个表达式(函数),还可以是一个对象, ...
- motan源码分析八:涉及到底层的客户端调用
之前我们分析了客户端调用服务端的源码,但是没有涉及到通讯层和序列化层,本文将之前讲过的内容做一次串联. 1.上层通过动态代理调用refer的call,每个refer又对应一个nettyclient,下 ...
- motan源码分析十一:部分特性
本章将描述motan部分的特性并对源码进行分析. 1.requestid的维护,使用了当前时间左移20位,再和一个自增变量组合 public class RequestIdGenerator { ); ...
- motan源码分析十:流量切换
motan提供了流量切换的功能,可以实现把一个group的流量切换到另一个group(一个或多个服务都可以).大家可以使用tomcat部署motan的管理工具,并设置几个组,例如可以参考demo代码: ...
- motan源码分析五:cluster相关
上一章我们分析了客户端调用服务端相关的源码,但是到了cluster里面的部分我们就没有分析了,本章将深入分析cluster和它的相关支持类. 1.clustersupport的创建过程,上一章的Ref ...
- motan源码分析二:使用spi机制进行类加载
在motan的源码中使用了很多的spi机制进行对象的创建,下面我们来具体分析一下它的实现方法. 1.在实际的jar包的\META-INF\services目录中引入相关的文件,例如下图中,我解压了co ...
随机推荐
- #BeginLibraryItem 的疑问...
<!-- #BeginLibraryItem "/library/ur_here.lbi" --><div style="padding:3px 15p ...
- 对exp full 和 imp full的认识
前段时间听同事说.Toad 工具可以打开 oracle数据库的 .dmp 文件.今天抽空试了试,果然可以!Oracle 执行 export 操作 会把 表的定义导出.表的数据导出. 其实 .dmp 文 ...
- (转)C#Interface简介
接口:描述可属于任何类或结构的一组相关功能,通过interface关键字来声明:接口只包含方法.委托或事件和属性的签名(接口包含的成员).不能包含字段(因为字段是包含数据的).方法的实现是“继承”接口 ...
- C++ 实现网络爬虫
吐槽 前天心血来潮, 把自己面试经历下了下来. 我觉得自己求职一路来比较心酸, 也付出了比一般人更多的汗水. 本以为写出来, 好歹可以作为一篇励志故事. 得到的评论却是, 语言只是一门工具. ||| ...
- php中抽象类和接口的特点、区别和选择
一.特点: 1.抽象类特点 (1) 用 abstract 来修饰一个类,那么这个类就是抽象类:抽象类绝对不能被实例化,即$abc = new 抽象类名();会报错. (2) 用abstract 来修饰 ...
- python3数据类型--数字
数字 Python数字数据类型用于存储数值.数字数据类型是不允许改变的,所以如果改变数字数据类型的值,将重新分配内存空间. 以下实例在变量赋值时Number对象被创建: #!/usr/bin/env ...
- TCP\UDP链接的异同
简单的说TCP与UDP的区别是有无连接状态.TCP是有连接状态的,而UDP没有,所以TCP是一种比较安全的通讯协议,而UDP则比较方便 TCP 127.0.0.1:1026 0.0.0.0:0 LIS ...
- 第六周 G题
G - 数论,最大公约数 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Desc ...
- A题
A - A Time Limit:1000MS Memory Limit:131072KB 64bit IO Format:%I64d & %I64u Descriptio ...
- SQL语句宝典
1.前述: 将数据灵活运用于手掌心! link:1.经典SQL语句大全(cnblogs) 2.SQL教程(W3C)