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 ...
随机推荐
- Rechability的简单使用
AppDelegate.m #import "AppDelegate.h" #import "Reachability.h" @interface AppDel ...
- Linux网络配置命令ifconfig输出信息解析
eth0 Link encap:Ethernet HWaddr 00:1e:4f:e9:c2:84 inet addr:128.224.163.153 Bcast:128.224.163 ...
- java_annotation_01
一,Annotation简介 J2SE5.0提供了很多新的我,其中一个很重要的我就是对元数据的支持,在J2SE5.0中,这种元数据被称为注释,通过使用注释,程序开发人员可以在不改变原有逻辑的情况下,在 ...
- 使用BOOST BIND库提高C++程序性能
Boost.Bind为函数和函数对象,值语义和指针提供语义了一致的语法.我们首先通过一些简单的例子来看看它的基本用法,之后我们会延伸到嵌套绑定以实现功能组合.理解bind用法的一个关键是理解占位符(p ...
- 高效jQuery
1.缓存变量 DOM遍历是昂贵的,所以尽量将会重用的元素缓存. // 糟糕 h = $('#element').height(); $('#element').css('height',h-20); ...
- javascript获得给定日期的前一天的日期
/** * 获得当前日期的前一天 */ function getYestoday(date){ var yesterday_milliseconds=date.getTime()-1000*60*60 ...
- php防止SQL注入详解及防范
SQL 注入是PHP应用中最常见的漏洞之一.事实上令人惊奇的是,开发者要同时犯两个错误才会引发一个SQL注入漏洞一个是没有对输入的数据进行过滤(过滤输入),还有一个是没有对发送到数据库的数据进行转义( ...
- Python学习笔记四--字典与集合
字典是Python中唯一的映射类型.所谓映射即指该数据类型包含哈希值(key)和与之对应的值(value)的序列.字典是可变类型.字典中的数据是无序排列的. 4.1.1字典的创建及赋值 dict1={ ...
- 使用Gson进行json数据转换(list to json 和json to list)
文章借鉴自:http://blog.csdn.net/binyao02123202/article/details/7540407 下面是一个简单的例子: Java代码 public class Pe ...
- light oj 1248 第六周E题(期望)
E - 期望(经典问题) Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%lld & %llu Descri ...