learn.lianglianglee.com/专栏/RocketMQ 实战与进阶(完)/01 搭建学习环境准备篇.md.html
2022-08-14 03:40:33 +08:00

402 lines
22 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
<link rel="icon" href="/static/favicon.png">
<title>01 搭建学习环境准备篇.md.html</title>
<!-- Spectre.css framework -->
<link rel="stylesheet" href="/static/index.css">
<!-- theme css & js -->
<meta name="generator" content="Hexo 4.2.0">
</head>
<body>
<div class="book-container">
<div class="book-sidebar">
<div class="book-brand">
<a href="/">
<img src="/static/favicon.png">
<span>技术文章摘抄</span>
</a>
</div>
<div class="book-menu uncollapsible">
<ul class="uncollapsible">
<li><a href="/" class="current-tab">首页</a></li>
</ul>
<ul class="uncollapsible">
<li><a href="../">上一级</a></li>
</ul>
<ul class="uncollapsible">
<li>
<a class="current-tab" href="/专栏/RocketMQ 实战与进阶(完)/01 搭建学习环境准备篇.md.html">01 搭建学习环境准备篇</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/02 RocketMQ 核心概念扫盲篇.md.html">02 RocketMQ 核心概念扫盲篇</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/03 消息发送 API 详解与版本变迁说明.md.html">03 消息发送 API 详解与版本变迁说明</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/04 结合实际应用场景谈消息发送.md.html">04 结合实际应用场景谈消息发送</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/05 消息发送核心参数与工作原理详解.md.html">05 消息发送核心参数与工作原理详解</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/06 消息发送常见错误与解决方案.md.html">06 消息发送常见错误与解决方案</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/07 事务消息使用及方案选型思考.md.html">07 事务消息使用及方案选型思考</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/08 消息消费 API 与版本变迁说明.md.html">08 消息消费 API 与版本变迁说明</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/09 DefaultMQPushConsumer 核心参数与工作原理.md.html">09 DefaultMQPushConsumer 核心参数与工作原理</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/10 DefaultMQPushConsumer 使用示例与注意事项.md.html">10 DefaultMQPushConsumer 使用示例与注意事项</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/11 DefaultLitePullConsumer 核心参数与实战.md.html">11 DefaultLitePullConsumer 核心参数与实战</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/12 结合实际场景再聊 DefaultLitePullConsumer 的使用.md.html">12 结合实际场景再聊 DefaultLitePullConsumer 的使用</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/13 结合实际场景顺序消费、消息过滤实战.md.html">13 结合实际场景顺序消费、消息过滤实战</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/14 消息消费积压问题排查实战.md.html">14 消息消费积压问题排查实战</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/15 RocketMQ 常用命令实战.md.html">15 RocketMQ 常用命令实战</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/16 RocketMQ 集群性能摸高.md.html">16 RocketMQ 集群性能摸高</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/17 RocketMQ 集群性能调优.md.html">17 RocketMQ 集群性能调优</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/18 RocketMQ 集群平滑运维.md.html">18 RocketMQ 集群平滑运维</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/19 RocketMQ 集群监控(一).md.html">19 RocketMQ 集群监控(一)</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/20 RocketMQ 集群监控(二).md.html">20 RocketMQ 集群监控(二)</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/21 RocketMQ 集群告警.md.html">21 RocketMQ 集群告警</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/22 RocketMQ 集群踩坑记.md.html">22 RocketMQ 集群踩坑记</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/23 消息轨迹、ACL 与多副本搭建.md.html">23 消息轨迹、ACL 与多副本搭建</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/24 RocketMQ-Console 常用页面指标获取逻辑.md.html">24 RocketMQ-Console 常用页面指标获取逻辑</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/25 RocketMQ Nameserver 背后的设计理念.md.html">25 RocketMQ Nameserver 背后的设计理念</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/26 Java 并发编程实战.md.html">26 Java 并发编程实战</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/27 从 RocketMQ 学基于文件的编程模式(一).md.html">27 从 RocketMQ 学基于文件的编程模式(一)</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/28 从 RocketMQ 学基于文件的编程模式(二).md.html">28 从 RocketMQ 学基于文件的编程模式(二)</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/29 从 RocketMQ 学 Netty 网络编程技巧.md.html">29 从 RocketMQ 学 Netty 网络编程技巧</a>
</li>
<li>
<a href="/专栏/RocketMQ 实战与进阶(完)/30 RocketMQ 学习方法之我见.md.html">30 RocketMQ 学习方法之我见</a>
</li>
</ul>
</div>
</div>
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
<div class="sidebar-toggle-inner"></div>
</div>
<script>
function add_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.add('show')
}
function remove_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.remove('show')
}
function sidebar_toggle() {
let sidebar_toggle = document.querySelector('.sidebar-toggle')
let sidebar = document.querySelector('.book-sidebar')
let content = document.querySelector('.off-canvas-content')
if (sidebar_toggle.classList.contains('extend')) { // show
sidebar_toggle.classList.remove('extend')
sidebar.classList.remove('hide')
content.classList.remove('extend')
} else { // hide
sidebar_toggle.classList.add('extend')
sidebar.classList.add('hide')
content.classList.add('extend')
}
}
function open_sidebar() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.add('show')
overlay.classList.add('show')
}
function hide_canvas() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.remove('show')
overlay.classList.remove('show')
}
</script>
<div class="off-canvas-content">
<div class="columns">
<div class="column col-12 col-lg-12">
<div class="book-navbar">
<!-- For Responsive Layout -->
<header class="navbar">
<section class="navbar-section">
<a onclick="open_sidebar()">
<i class="icon icon-menu"></i>
</a>
</section>
</header>
</div>
<div class="book-content" style="max-width: 960px; margin: 0 auto;
overflow-x: auto;
overflow-y: hidden;">
<div class="book-post">
<p id="tip" align="center"></p>
<div><h1>01 搭建学习环境准备篇</h1>
<p>本文主要分如下几个部分展开:</p>
<ul>
<li>Linux 服务器安装 RocketMQ、RocketMQ-Console</li>
<li>IDEA 中搭建可调试环境</li>
</ul>
<h3>Linux 安装 RocketMQ、RocketMQ-Console</h3>
<h4><strong>安装 RocketMQ</strong></h4>
<p><strong>Step1从如下地址下载 RocketMQ 安装包</strong></p>
<pre><code>cd /opt/application
wget https://mirrors.tuna.tsinghua.edu.cn/apache/rocketmq/4.7.1/rocketmq-all-4.7.1-bin-release.zip
</code></pre>
<p><strong>Step2解压安装包</strong></p>
<pre><code>unzip rocketmq-all-4.7.1-bin-release.zip
ls -l
</code></pre>
<p>解压后的文件如下图所示:</p>
<p><img src="assets/20200726210733673.png" alt="1" /></p>
<p>其中 conf 文件夹存放的是 RocketMQ 的配置文件,提供了各种部署结构的示例配置。例如 2m-2s-async 是 2 主 2 从异步复制的配置示例2m-noslave 是 2 主的示例配置。由于本文主要是搭建一个学习环境,故采取的部署架构为 1 主的部署架构,关于生产环境下如何搭建 RocketMQ 集群、如何调优参数将在该专栏的后续文章中专门介绍。</p>
<p><strong>Step3修改 NameServer JVM 参数</strong></p>
<pre><code>cd bin
vi runserver.sh
# 定位到如下代码
JAVA_OPT=&quot;${JAVA_OPT} -server -Xms4g -Xmx4g -Xmn2g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m&quot;
# 修改 &quot;-Xms -Xmx -Xmn&quot; 参数
JAVA_OPT=&quot;${JAVA_OPT} -server -Xms512M -Xmx512M -Xmn256M -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m&quot;
</code></pre>
<blockquote>
<p>温馨提示:这里修改 JVM 参数主要目的是个人学习电脑内存不够,默认 NameServer 会占用 4G。</p>
</blockquote>
<p><strong>Step4启动 NameServer</strong></p>
<pre><code>nohup ./mqnamesrv &amp;
</code></pre>
<p>查看 <code>${user_home}/logs/rocketmqlogs/namesrv.log</code> 日志文件,如果输出结果如下图所示即表示启动成功。</p>
<p><img src="assets/20200726210745940.png" alt="2" /></p>
<p><strong>Step5修改 Broker 的配置文件</strong></p>
<pre><code>vi conf/broker.conf
# 使用如下配置文件
brokerClusterName = DefaultCluster
brokerName = broker-a
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
brokerRole = ASYNC_MASTER
flushDiskType = ASYNC_FLUSH
storePathRootDir=/data/rocketmq/store
storePathCommitLog=/data/rocketmq/store/commitlog
namesrvAddr=127.0.0.1:9876
brokerIP1=192.168.3.10
brokerIP2=192.168.3.10
autoCreateTopicEnable=false
</code></pre>
<p><strong>Step6修改 Broker JVM 参数</strong></p>
<pre><code>cd bin
vi runbroker.sh
#修改如下配置(配置前)
JAVA_OPT=&quot;${JAVA_OPT} -server -Xms8g -Xmx8g -Xmn4g&quot;
#配置后
JAVA_OPT=&quot;${JAVA_OPT} -server -Xms1g -Xmx1g -Xmn512m&quot;
</code></pre>
<p><strong>Step7启动 Broker</strong></p>
<pre><code>cd bin
nohup ./mqbroker -c ../conf/broker.conf &amp;
</code></pre>
<p>查看 <code>${user_home}/logs/rocketmqlogs/broker.log</code>,如果输出结果如下图所示表示启动成功。</p>
<p><img src="assets/2020072621075474.png" alt="2" /></p>
<p>经过上面的步骤,就成功在 Linux 环境上安装了 RocketMQ NameServer 服务器与 Broker 服务器。</p>
<blockquote>
<p>温馨提示:如果上面在安装过程中发生了错误,大家可以查看 <code>${user_home}/logs/rocketmqlogs</code> 中的日志,通过错误日志,能够较为直观的判断错误的原因。其中 <code>${user_home}</code> 为用户主目录。</p>
<p>该目录下会有众多的日志文件,如果一开始对这些文件的含义不了解也没关系,大家可以通过 <code>ls -l</code> 命令,逐一查看文件大小不为0的文件,从而寻找错误日志,便于快速解决问题。</p>
</blockquote>
<p>RocketMQ 提供了众多的运维命令来查看 RocketMQ 集群的运行状态,在这里我先简单使用 clusterList 命令来查看集群的状态,用于验证一下集群的状态。</p>
<pre><code>sh ./mqadmin clusterList -n 127.0.0.1:9876
</code></pre>
<p>其运行结果如下图所示:</p>
<p><img src="assets/20200726210803302.png" alt="2" /></p>
<h4><strong>安装 RocketMQ-Console</strong></h4>
<p>使用运维命令不太直观,学习成本较大,为此 RocketMQ 官方提供了一个运维管理界面 RokcetMQ-Console用于对 RocketMQ 集群提供常用的运维功能,故本节主要讲解如何在 Linux 环境安装 RokcetMQ-Console。</p>
<p>RocketMQ 官方并未提供 RokcetMQ-Console 的安装包,故需要通过源码进行编译。</p>
<p><strong>Step1下载源码</strong></p>
<pre><code>wget https://github.com/apache/rocketmq-externals/archive/rocketmq-console-1.0.0.tar.gz
tar -xf rocketmq-console-1.0.0.tar.gz
# 重命名,为了方便后续操作
mv rocketmq-externals-rocketmq-console-1.0.0/rocketmq-console rocketmq-console
</code></pre>
<p><strong>Step2修改配置文件</strong></p>
<pre><code>cd rocketmq-console
vi src/main/resources/applications.properties
</code></pre>
<p>主要是修改指向的 NameServer 地址,修改结果如下图所示:</p>
<p><img src="assets/20200726210814378.png" alt="2" /></p>
<p><strong>Step3使用 Maven 命令编译源代码</strong></p>
<pre><code>mvn clean package -DskipTests
</code></pre>
<p>编译后在 target 目录下会生成可运行的 jar 包,如下图所示:</p>
<p><img src="assets/20200726210822158.png" alt="2" /></p>
<p><strong>Step4我们可以将该包复制到自己常用的软件安装目录例如笔者喜欢将其放在 /opt/application 下</strong></p>
<pre><code>cp rocketmq-console-ng-1.0.0.jar /opt/application/
</code></pre>
<p><strong>Step5启动 RokcetMQ-Console</strong></p>
<pre><code>nohup java -jar rocketmq-console-ng-1.0.0.jar &amp;
</code></pre>
<p>在浏览器中输入 http://localhost:8080 查看是否安装成功,如果出现如下图则表示安装成功。</p>
<p><img src="assets/20200726210832287.png" alt="2" /></p>
<h4><strong>异常分析与解决思路</strong></h4>
<p>如果在安装过程中出现意想不到的错误,别慌,通过查看相关的日志文件,寻找错误日志,根据错误日志进行思考或百度,相信能够轻易将其解决。</p>
<p>例如使用的 Baseuser 启动的 RocketMQ、RokcetMQ-Console相关的日志路径如下</p>
<ul>
<li>RocketMQ/home/baseuser/logs/rocketmqlogs/</li>
<li>RokcetMQ-Console/home/baseuser/logs/consolelogs</li>
</ul>
<h3>IDEA 中安装 RocketMQ</h3>
<p>绝大数的程序员最信赖的开发调试工具基本都是 Debug那能在 IDEA 中 Debug RocketMQ 的源码吗?答案当然是可以的。本节就来演示如何在 IDEA 中运行 RocketMQ 的 NameServer、Broker 组件,并进行 Debug。</p>
<p><strong>Setp1从 GitHub 上下载 RocketMQ 源码,并将其导入到 IEDA 中</strong></p>
<p>其截图如下:</p>
<p><img src="assets/20200726210840103.png" alt="8" /></p>
<p><strong>Step2namesrv/src/main/java/org/apache/rocketmq/namesrv/NamesrvStartup 设置环境变量 ROCKETMQ_HOME</strong></p>
<p>操作步骤如下图所示:</p>
<p><img src="assets/20200726210852167.png" alt="9" /></p>
<p>设置环境变量名称ROCKETMQ_HOME其值用于指定 RocketMQ 运行的主目录,笔者设置的路径为:/home/dingwpmz/tmp/rocketmq。</p>
<p><strong>Step3将 distribution/conf/logback_namesrv.xml 文件拷贝到 Step2 中设置的主目录下</strong></p>
<p>执行后的效果如下图所示:</p>
<p><img src="assets/20200726210902103.png" alt="10" /></p>
<blockquote>
<p>温馨提示:该文件为 NameServer 的日志路劲,可以手动修改 logback_namesrv.xml 文件中的日志目录,由于这是 Logback 的基础知识,这里就不再详细介绍 Logback 的配置方法。</p>
</blockquote>
<p><strong>Step4以 Debug 方法运行 NamesrvStartup,执行效果如下图所示,表示启动成功</strong></p>
<p><img src="assets/20200726210914125.png" alt="11" /></p>
<p><strong>Step5将 distribution/conf/logback_brokerxml、broker.conf 文件拷贝到 Step2 中设置的主目录下</strong></p>
<p>执行后的效果如下图所示:</p>
<p><img src="assets/20200726210923668.png" alt="12" /></p>
<p><strong>Step6修改 broker.conf 中的配置,主要设置 NameServer 的地址、Broker 的名称等相关属性</strong></p>
<pre><code class="language-properties">vi broker.conf
# 使用如下配置文件
brokerClusterName = DefaultCluster
brokerName = broker-a
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
brokerRole = ASYNC_MASTER
flushDiskType = ASYNC_FLUSH
storePathRootDir=/home/dingwpmz/tmp/rocketmq/store
storePathCommitLog=/home/dingwpmz/tmp/rocketmq/store/commitlog
namesrvAddr=127.0.0.1:9876
brokerIP1=192.168.3.10
brokerIP2=192.168.3.10
autoCreateTopicEnable=true
</code></pre>
<p><strong>Step7broker/src/main/java/org/apache/rocketmq/broker/BrokerStartup 设置环境变量 ROCKETMQ_HOME</strong></p>
<p>操作步骤如下图所示:</p>
<p><img src="assets/20200726210931222.png" alt="13" /></p>
<p><strong>Step8以 Debug 模式运行 BrokerStartup</strong></p>
<p>其运行结果如下图所示:</p>
<p><img src="assets/20200726210937382.png" alt="14" /></p>
<p>看到这样的提示就表示大功告成。</p>
<p>接下来简单来做一个验证。</p>
<p>首先先在 AbstractSendMessageProcessor 类的 parseRequestHeader 方法中打上一个断点。</p>
<p>然后运行 example 中 org/apache/rocketmq/example/quickstart/Producer看是否能进入到断点中运行结果如下图所示已进入到 Debug 模式。</p>
<p><img src="assets/20200726210945807.png" alt="15" /></p>
<h3>小结</h3>
<p>本篇作为 RocketMQ 实战系列的第一篇文章,其目的就是构建一个研究 RocketMQ 的学习环境,故从两个方面进行展开:</p>
<ul>
<li>在 Linux 环境安装 RocketMQ、RocketMQ-Console。</li>
<li>在 IDEA 中运行 RocketMQ构建一个可以调试 RocketMQ 的环境。</li>
</ul>
<p>温馨提示:搭建一个可调试的环境,但绝不是学习 RocketMQ 源码,就从 Debug 一步一步跟踪这样会陷入其中而不可自拔。Debug 只是一种辅助,应该用在无法理解某一端代码时使用 Debug借助运行时的一些数据使之更容易理解。</p>
</div>
</div>
<div>
<div style="float: right">
<a href="/专栏/RocketMQ 实战与进阶(完)/02 RocketMQ 核心概念扫盲篇.md.html">下一页</a>
</div>
</div>
</div>
</div>
</div>
</div>
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
</div>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"709974117cb93d60","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
</body>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-NPSEEVD756');
var path = window.location.pathname
var cookie = getCookie("lastPath");
console.log(path)
if (path.replace("/", "") === "") {
if (cookie.replace("/", "") !== "") {
console.log(cookie)
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
}
} else {
setCookie("lastPath", path)
}
function setCookie(cname, cvalue) {
var d = new Date();
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i].trim();
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
}
return "";
}
</script>
</html>