从大四开始,一直保持着阅读源码的习惯,也一直都从事中间件相关领域的产品开发,对于如何阅读源码和如何快速选型也有自己的心得于体会。
下面着重讲讲如何阅读 RocketMQ 的源码。
在 研读 &实操 【rocketmq-example】 这里的代码的时候,可以适当通过 debug 模式去看看整体的流程。
如果的内容都满足了,在开始真正阅读源码前,我们需要去看看 RocketMQ 一个很重要的类:RequestCode。由于 RockeMQ 是基于Netty 作为通讯框架,在上层实现自定义协议的,所以,code 这个属性是必备的。code 这个属性的值就代表了请求哪个方法了。
如果的工作都做好了,那就往下看看。看看如何拜读 RocketMQ 的源码。
在研读源码的时候,有时候遇到自己不懂的东西,不要太过于纠结,先写下 TODO 。后面在来多看几遍。
RocketMQ 源码比较难的地方就是:网络部分、存储模块。这两个是大头,在初步研读源码的是时候,就采用假设的方法,假设消息已经存储OK 了。在拜读源码的时候,【假设一定成功,一定OK】 这个套路是非常不错,但记得写上 TODO,留下自己的足迹、留下自己的疑问。
谈了这么多,对于阿里的中间件产品,他们的运维工具写的非常好,直达产品的核心,吃透运维工具后,就完成了了 40% 啦。
在拜读源码的时候,一定要写上注释,不管多么简单的,都写上注释。这个一个好习惯。
在拜读源码的时候,记得在源码自己创建一个 doc 文件夹,用于存放自己在网络上面收集的资料、文档。
源码不在于多,在于能不能看透了,在简单入门后,自己去反思,如果不这样设计的话,那可以采用什么模型呢?
下面是 RocketMQ 里面的 RequestCode 的代码
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the “License”); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.common.protocol;
/**
* 这里相当于 Http 中的 GET 等等方法
*/
public class RequestCode {
// Broker 发送消息
public static final int SEND_MESSAGE = 10;
// Broker 订阅消息
public static final int PULL_MESSAGE = 11;
// Broker 查询消息
public static final int QUERY_MESSAGE = 12;
// Broker 查询Broker Offset
public static final int QUERY_BROKER_OFFSET = 13;
// Broker 查询Consumer Offset
public static final int QUERY_CONSUMER_OFFSET = 14;
// Broker 更新Consumer Offset
public static final int UPDATE_CONSUMER_OFFSET = 15;
// Broker 更新或者增加一个Topic
public static final int UPDATE_AND_CREATE_TOPIC = 17;
// Broker 获取所有Topic的配置(Slave和Namesrv都会向Master请求此配置)
public static final int GET_ALL_TOPIC_CONFIG = 21;
// Broker 获取所有Topic配置(Slave和Namesrv都会向Master请求此配置)
public static final int GET_TOPIC_CONFIG_LIST = 22;
// Broker 获取所有Topic名称列表
public static final int GET_TOPIC_NAME_LIST = 23;
// Broker 更新Broker上的配置
public static final int UPDATE_BROKER_CONFIG = 25;
// Broker 获取Broker上的配置
public static final int GET_BROKER_CONFIG = 26;
// Broker 触发Broker删除文件
public static final int TRIGGER_DELETE_FILES = 27;
// Broker 获取Broker运行时信息
public static final int GET_BROKER_RUNTIME_INFO = 28;
// Broker 根据时间查询队列的Offset,客户端可以配置根据 时间戳来消费
public static final int SEARCH_OFFSET_BY_TIMESTAMP = 29;
// Broker 查询队列最大Offset
public static final int GET_MAX_OFFSET = 30;
// Broker 查询队列最小Offset
public static final int GET_MIN_OFFSET = 31;
// Broker 查询队列最早消息对应时间
public static final int GET_EARLIEST_MSG_STORETIME = 32;
// Broker 根据消息ID来查询消息
public static final int VIEW_MESSAGE_BY_ID = 33;
// Broker Client向Client发送心跳,并注册自身
public static final int HEART_BEAT = 34;
// Broker Client注销
public static final int UNREGISTER_CLIENT = 35;
// 重新消费消息
public static final int CONSUMER_SEND_MSG_BACK = 36;
// Broker Commit或者Rollback事务
public static final int END_TRANSACTION = 37;
// Broker 获取ConsumerId列表通过GroupName
public static final int GET_CONSUMER_LIST_BY_GROUP = 38;
// Broker 主动向Producer回查事务状态
public static final int CHECK_TRANSACTION_STATE = 39;
// 提示 consumer id 列表发生了变化,todo 采用 one way 方式,可能会有点问题
public static final int NOTIFY_CONSUMER_IDS_CHANGED = 40;
// Broker Consumer向Master锁定队列
public static final int LOCK_BATCH_MQ = 41;
// Broker Consumer向Master解锁队列
public static final int UNLOCK_BATCH_MQ = 42;
// Broker 获取所有Consumer Offset
public static final int GET_ALL_CONSUMER_OFFSET = 43;
// Broker 获取所有延迟进度
public static final int GET_ALL_DELAY_OFFSET = 45;
// 检查 consumer 的订阅关系。比如SQL 的过滤是否符合、正确。
public static final int CHECK_CLIENT_CONFIG = 46;
// Namesrv 向Namesrv追加KV配置
public static final int PUT_KV_CONFIG = 100;
// Namesrv 从Namesrv获取KV配置
public static final int GET_KV_CONFIG = 101;
// Namesrv 从Namesrv获取KV配置
public static final int DELETE_KV_CONFIG = 102;
// Namesrv 注册一个Broker,数据都是持久化的,如果存在则覆盖配置
public static final int REGISTER_BROKER = 103;
// Namesrv 卸载一个Broker,数据都是持久化的
public static final int UNREGISTER_BROKER = 104;
// Namesrv 根据Topic获取Broker Name、队列数(包含读队列与写队列)
public static final int GET_ROUTEINTO_BY_TOPIC = 105;
// Namesrv 获取注册到Name Server的所有Broker集群信息
public static final int GET_BROKER_CLUSTER_INFO = 106;
public static final int UPDATE_AND_CREATE_SUBSCRIPTIONGROUP = 200;
public static final int GET_ALL_SUBSCRIPTIONGROUP_CONFIG = 201;
public static final int GET_TOPIC_STATS_INFO = 202;
public static final int GET_CONSUMER_CONNECTION_LIST = 203;
public static final int GET_PRODUCER_CONNECTION_LIST = 204;
public static final int WIPE_WRITE_PERM_OF_BROKER = 205;
// 从Name Server获取完整Topic列表
public static final int GET_ALL_TOPIC_LIST_FROM_NAMESERVER = 206;
// 从Broker删除订阅组
public static final int DELETE_SUBSCRIPTIONGROUP = 207;
// 从Broker获取消费状态(进度)
public static final int GET_CONSUME_STATS = 208;
// Suspend Consumer消费过程
public static final int SUSPEND_CONSUMER = 209;
// Resume Consumer消费过程
public static final int RESUME_CONSUMER = 210;
// 重置Consumer Offset
public static final int RESET_CONSUMER_OFFSET_IN_CONSUMER = 211;
// 重置Consumer Offset
public static final int RESET_CONSUMER_OFFSET_IN_BROKER = 212;
// 调整Consumer线程池数量
public static final int ADJUST_CONSUMER_THREAD_POOL = 213;
// 查询消息被哪些消费组消费
public static final int WHO_CONSUME_THE_MESSAGE = 214;
// 从Broker删除Topic配置
public static final int DELETE_TOPIC_IN_BROKER = 215;
// 从Namesrv删除Topic配置
public static final int DELETE_TOPIC_IN_NAMESRV = 216;
// 获取 KV 列表
public static final int GET_KVLIST_BY_NAMESPACE = 219;
// 重置客户端的 offset
public static final int RESET_CONSUMER_CLIENT_OFFSET = 220;
// 客户端订阅消息
public static final int GET_CONSUMER_STATUS_FROM_CLIENT = 221;
// 通知 broker 重置 offset
public static final int INVOKE_BROKER_TO_RESET_OFFSET = 222;
// 通知 broker 调用客户端订阅消息处理
public static final int INVOKE_BROKER_TO_GET_CONSUMER_STATUS = 223;
// Broker 查询topic被谁消费
// 2014-03-21 Add By shijia
public static final int QUERY_TOPIC_CONSUME_BY_WHO = 300;
// 获取指定集群下的所有 topic
// 2014-03-26
public static final int GET_TOPICS_BY_CLUSTER = 224;
// 向Broker注册Filter Server
// 2014-04-06 Add By shijia
public static final int REGISTER_FILTER_SERVER = 301;
// 向Filter Server注册Class
// 2014-04-06 Add By shijia
public static final int REGISTER_MESSAGE_FILTER_CLASS = 302;
// 根据 topic 和 group 获取消息的时间跨度
public static final int QUERY_CONSUME_TIME_SPAN = 303;
// 获取所有系统内置 Topic 列表
public static final int GET_SYSTEM_TOPIC_LIST_FROM_NS = 304;
// 清理失效队列
public static final int GET_SYSTEM_TOPIC_LIST_FROM_BROKER = 305;
// 通过Broker查询Consumer内存数据
// 2014-07-19 Add By shijia
public static final int CLEAN_EXPIRED_CONSUMEQUEUE = 306;
public static final int GET_CONSUMER_RUNNING_INFO = 307;
// 查找被修正 offset (转发组件)
public static final int QUERY_CORRECTION_OFFSET = 308;
// 通过Broker直接向某个Consumer发送一条消息,并立刻消费,返回结果给broker,再返回给调用方
// 2014-08-11 Add By shijia
public static final int CONSUME_MESSAGE_DIRECTLY = 309;
// Broker 发送消息,优化网络数据包,哪里出现优化啦?比如:属性的名称缩短了。
public static final int SEND_MESSAGE_V2 = 310;
// 单元化相关 topic
public static final int GET_UNIT_TOPIC_LIST = 311;
// 获取含有单元化订阅组的 Topic 列表
public static final int GET_HAS_UNIT_SUB_TOPIC_LIST = 312;
// 获取含有单元化订阅组的非单元化 Topic 列表
public static final int GET_HAS_UNIT_SUB_UNUNIT_TOPIC_LIST = 313;
// 克隆某一个组的消费进度到新的组
public static final int CLONE_GROUP_OFFSET = 314;
// 查看Broker上的各种统计信息
public static final int VIEW_BROKER_STATS_DATA = 315;
// 清除不再使用的 Topic
public static final int CLEAN_UNUSED_TOPIC = 316;
// 获取消费组的消费信息
public static final int GET_BROKER_CONSUME_STATS = 317;
/**
* update the config of name server
*/
public static final int UPDATE_NAMESRV_CONFIG = 318;
/**
* get config from name server
* 从 name server 获取配置信息
*/
public static final int GET_NAMESRV_CONFIG = 319;
// 发送批量消息,不支持 重试队列、delay 特性。只能作为 日志传输方式。消费端拿到的是一条条消息了。
public static final int SEND_BATCH_MESSAGE = 320;
// 获取 consume queue
public static final int QUERY_CONSUME_QUEUE = 321;
}