RocketMq源码解析(9)

RocketMq源码解析(九)这一期主要讲整个系统的底层网络以及节点通信,在前几期中我们已经知道其在broker中分为了consumer和producer两种角色,这些角色有着自己的Channel来进行通信,那么底层是如何发送这些信息的呢,这一期我将介绍MQ的底层实现RocketMQSerializable显而易见,这是一个序列化协议,可以把对象序列化为流,这样就可以在网络中传输,具体实...
摘要由CSDN通过智能技术生成

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;

/**
 *  ----------------------------------------------------------
 * |-----code(16)-------|-language(8)-|-----version(16)-----|
 * |-----------------opaque(32)------------------|
 * |-----------------flag(32)--------------------|
 * |--------------remarkLength(32)---------------|
 * |-----------------remark-----------------.....
 * ..............................................|
 * |-------------extFieldsLength(32)-------------|
 * |-----------------extField------------........
 * ..............................................
 * ----------------------------------------------|
 * ------------------------------------------------------------
 * @author xuxiaoxi10
 * @version 1.0
 * @date 2020/4/25 9:19
 */
public class RocketMQSerializable {
   
    private final static Charset CHARSET_UTF8=Charset.forName("UTF-8");


    /**
     * MQ协议编码
     * @param cmd 远程命令
     * @return 字节流
     */
    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();
    }

    /**
     * MQ协议解码
     * @param headData 头部数据
     * @return RemotingCommand
     */
    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;
    }

    /**
     * calculate total length
     * @param remark remark length
     * @param ext extra length
     * @return total length
     */
    private static int calTotalLen(int remark, int ext) {
   
        // int code(~32767)
        int length = 2
                // LanguageCode language
                + 1
                // int version(~32767)
                + 2
                // int opaque
                + 4
                // int flag
                + 4
                // String remark
                + 4 + remark
                // HashMap<String, String> extFields
                + 4 + ext;

        return length;
    }

    /**
     * hashMap序列化
     * |------keySize(16)-------|----key-----..........|
     * |------------valueSize(32)----------------|-----------........|
     * @param map
     * @return
     */
    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()){
   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值