RocketMq源码解析(九)
这一期主要讲整个系统的底层网络以及节点通信,在前几期中我们已经知道其在broker中分为了
consumer和producer两种角色,这些角色有着自己的Channel来进行通信,那么底层是如何发送
这些信息的呢,这一期我将介绍MQ的底层实现
一级目录
二级目录
三级目录
RocketMQSerializable
显而易见,这是一个序列化协议,可以把对象序列化为流,这样就可以在网络中传输,具体实现如下
package remoting.protocol;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class RocketMQSerializable {
private final static Charset CHARSET_UTF8=Charset.forName("UTF-8");
public static byte[] rocketMQProtocolEncode(RemotingCommand cmd){
byte[] remarkBytes = null;
int remarkLen=0;
if(cmd.getRemark()!=null&&cmd.getRemark().length()>0){
remarkBytes=cmd.getRemark().getBytes(CHARSET_UTF8);
remarkLen=remarkBytes.length;
}
byte[] extFieldsBytes=null;
int extFieldLength=0;
if(cmd.getExtFields()!=null&&!cmd.getExtFields().isEmpty()){
extFieldsBytes=mapSerialize(cmd.getExtFields());
extFieldLength=extFieldsBytes.length;
}
int totalLen=calTotalLen(remarkLen,extFieldLength);
ByteBuffer byteBuffer=ByteBuffer.allocate(totalLen);
byteBuffer.putShort((short)cmd.getCode());
byteBuffer.put(cmd.getLanguage().getCode());
byteBuffer.putShort((short)cmd.getVersion());
byteBuffer.putInt(cmd.getOpaque());
byteBuffer.putInt(cmd.getFlag());
if(remarkBytes!=null){
byteBuffer.putInt(remarkLen);
byteBuffer.put(remarkBytes);
}else {
byteBuffer.putInt(0);
}
if(extFieldsBytes!=null){
byteBuffer.putInt(extFieldLength);
byteBuffer.put(extFieldsBytes);
}else {
byteBuffer.putInt(0);
}
return byteBuffer.array();
}
public static RemotingCommand rocketMQProtocolDecode(byte[] headData){
RemotingCommand cmd=new RemotingCommand();
ByteBuffer byteBuffer=ByteBuffer.wrap(headData);
cmd.setCode(byteBuffer.getShort());
cmd.setLanguage(LanguageCode.valueOf(byteBuffer.get()));
cmd.setVersion(byteBuffer.getShort());
cmd.setOpaque(byteBuffer.getInt());
cmd.setFlag(byteBuffer.getInt());
int remarkLength=byteBuffer.getInt();
if(remarkLength>0){
byte[] remark=new byte[remarkLength];
byteBuffer.get(remark);
cmd.setRemark(new String(remark,CHARSET_UTF8));
}
int extFieldsLength=byteBuffer.getInt();
if(extFieldsLength>0){
byte[] extField=new byte[extFieldsLength];
byteBuffer.get(extField);
cmd.setExtFields(mapDeserialize(extField));
}
return cmd;
}
private static int calTotalLen(int remark, int ext) {
int length = 2
+ 1
+ 2
+ 4
+ 4
+ 4 + remark
+ 4 + ext;
return length;
}
private static byte[] mapSerialize(HashMap<String,String> map){
if (map == null||map.isEmpty()) {
return null;
}
int totalLength=0;
int kvLength;
Iterator<Map.Entry<String,String>> it=map.entrySet().iterator();
while (it.hasNext()){
Map.Entry<String,String> next=it.next();
kvLength=2+next.getKey().getBytes(CHARSET_UTF8).length
+4+next.getValue().getBytes(CHARSET_UTF8).length;
totalLength+=kvLength;
}
ByteBuffer content=ByteBuffer.allocate(totalLength);
it=map.entrySet().iterator();
byte[] key;
byte[] value;
while (it.hasNext()){