如何阅读阿里系的开源作品的源码

    从大四开始,一直保持着阅读源码的习惯,也一直都从事中间件相关领域的产品开发,对于如何阅读源码和如何快速选型也有自己的心得于体会。
    下面着重讲讲如何阅读 RocketMQ 的源码。

  1. 首先,我们需要知道 RocketMQ 是啥东西?消息中间件,仅仅是这样还不够的呢?阿里很多中间件产品都有自己的概念,我们需要对 RocketMQ 相关的概念熟悉了。推荐大伙去看看:【RocketMQ_原理简介】【RocketMQ用户指南】【RocketMQ 最佳实践】。这几个PDF 流传很广了。如果还有时间,可以去看看阿里云的ONS 产品,底层引擎是 RocketMQ。需要明白 RocketMQ 的 consumer 、producer、broker 、NameServer 扮演的角色是啥。
  2. 部署 RocketMQ。部署模式就很简单了,一个 Name Server & 一个 Broker。不要去纠结怎么性能调优啊,设置什么参数,直接按照:http://rocketmq.apache.org/docs/quick-start/ 这里的提示来部署即可。
  3. 研读&实操 RocketMQ 的 【rocketmq-example】 里面的代码,重点实操一下几个 example:【batch】【quickstart】【simple】【ordermessage】。我在阅读源码&编码的过程中有一个习惯:喜欢写 TODO 。
  4. 在 研读 &实操 【rocketmq-example】 这里的代码的时候,可以适当通过 debug 模式去看看整体的流程。

        如果的内容都满足了,在开始真正阅读源码前,我们需要去看看 RocketMQ 一个很重要的类:RequestCode。由于 RockeMQ 是基于Netty 作为通讯框架,在上层实现自定义协议的,所以,code 这个属性是必备的。code 这个属性的值就代表了请求哪个方法了。

    如果的工作都做好了,那就往下看看。看看如何拜读 RocketMQ 的源码。

  1. 第一步:先从 Producer 入手,通过 debug 手段了解 消息 是如何发送出去,消息是在哪里封装封装为 RocketMQ 自定义的协议。发送消息的 code 是:SEND_MESSAGE_V2。
    全部代码搜索一下这个 SEND_MESSAGE_V2,发现只有 client 和 broker 这两个地方再用。
    暂时先别管【消息是如何存储的】
  2. 第一步:从 RocketMQ 的【rocketmq-tools】,里面有很多命令,一定要把命令的功能、逻辑梳理清楚了,比如如何创建 Topic、如何查看消息等等。
  3. 第三步:再去看看消费端是如何 start 的。通过 debug 模式找到 拉取 消息的代码块在哪里。
  4. 第四步:再去看看消费端是如何通过 broker 端去拉取消息的【暂时不涉及到 broker 端】,如何放在客户端的。
  5. 第五步:消费成功、消费失败是如何处理。
  6. 第六步:客户端是如何提交记录的。
  7. 第七步:客户端是如何维护心跳的。
  8. 第八步:看看 Name Server 是如何启动的,启动的过程中做了哪些操作。
  9. 第九步:看看 broker 是如何启动,启动的过程中做了哪些操作。
  10. 第10步:发送端的消息在 broker 是如何存储的,如何写入 commitlog 里面的、consumequque 是如何维护的。
  11. 第11 步:看看 broker 里面的 netty 是如何设计的。
  12. 第12步:看看rocketmq 里面的 存储模式为什么这么设计,有什么好处。比如 kafka 的存储模型、数据库存储模型。

    在研读源码的时候,有时候遇到自己不懂的东西,不要太过于纠结,先写下 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;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值