当前位置: 首页 > news >正文

在RISC-V架构芒果派上部署Node.js与EMQX物联网开发环境

1. 项目概述与核心需求解析

最近在折腾一块芒果派 MangoPi MQ Quad 开发板,这是一款基于全志 D1s 处理器的 RISC-V 架构板子,性能不错,功耗也低,很适合用来做一些物联网边缘端的应用。我的目标是在这块板子上搭建一个能够运行 Node.js 后端服务,并集成 EMQX MQTT 消息中间件的环境,为后续的智能家居数据网关或者设备管理平台打基础。对于嵌入式开发或者物联网项目来说,直接在目标硬件上配置好稳定、可维护的开发环境是第一步,也是最关键的一步,能避免后续很多“水土不服”的问题。

这个需求很明确:我们需要一个灵活的 Node.js 环境来编写和运行业务逻辑,同时需要一个轻量且高性能的 MQTT Broker(EMQX)来处理设备与服务器、设备与设备之间的消息通信。直接在 ARM 或 RISC-V 架构的 Linux 系统上安装这些环境,和我们在 x86 的云服务器上操作,思路类似但细节上会遇到不少差异,尤其是包管理、依赖库和编译工具链方面。接下来,我就把在芒果派 MQ Quad 上从零开始部署 Node.js 和 EMQX 的完整过程、遇到的坑以及解决方案详细记录下来,如果你也在类似的嵌入式 Linux 平台上做部署,这份经验应该能帮你省下不少时间。

2. 环境准备与系统基础配置

在开始安装具体软件之前,我们需要先确保芒果派 MQ Quad 的系统处于一个良好的基础状态。我使用的是官方推荐的 Tina Linux 系统(基于 OpenWrt 改造)或 Debian 镜像,这里以 Debian 为例,因为它有更完善的 apt 包管理工具,后续安装会更方便。

2.1 系统更新与基础依赖安装

首先,通过 SSH 连接到你的芒果派。建议在操作前更新一下软件源列表并升级已有的软件包,这能确保我们安装的依赖是最新的,减少兼容性问题。

sudo apt update sudo apt upgrade -y

更新完成后,安装一些编译和基础运行所需的工具链。在嵌入式设备上从源码编译或安装二进制包时,这些工具常常是必需的。

sudo apt install -y curl wget git build-essential libssl-dev ca-certificates

注意build-essential包含了 gcc、g++、make 等基础编译工具。libssl-dev是 Node.js 编译和运行某些加密模块所必需的开发库。在资源受限的设备上,如果镜像空间紧张,可以酌情不安装build-essential,前提是你确定要安装的软件都有对应架构的预编译二进制包。

2.2 硬件与网络确认

芒果派 MQ Quad 的 CPU 是全志 D1s,这是一颗单核的 RISC-V 64 处理器。我们可以通过以下命令确认架构:

uname -m

输出应该是riscv64。这一点非常重要,因为后续我们寻找或编译软件时,都必须针对riscv64riscv架构。Node.js 官方提供了 ARM 和 x86 的预编译包,但对于 RISC-V,情况就复杂一些。同样,EMQX 的官方 apt 源也主要面向 x86_64 和 ARM64,我们需要确认是否有 RISC-V 的版本,或者寻找替代的安装方式。

3. Node.js 环境部署:使用 NVM 进行灵活管理

在开发板上直接安装特定版本的 Node.js 二进制包可能比较困难,因为官方不一定提供对应架构的版本。因此,我选择使用 NVM (Node Version Manager) 来管理 Node.js。NVM 的优势在于它可以通过源码编译的方式安装 Node.js,这样就能适配任何支持的架构,包括我们的 RISC-V。

3.1 NVM 的工作原理与选型考量

NVM 本质上是一个 shell 脚本,它通过修改用户的环境变量(主要是PATH)来切换当前 shell 会话中使用的 Node.js 版本。它会将不同版本的 Node.js 安装在用户家目录下的独立文件夹中(例如~/.nvm/versions/node/),互不干扰。为什么选择 NVM 而不是直接apt install nodejs

  1. 版本控制自由:Debian 系统源里的 Node.js 版本往往比较旧。而物联网项目可能依赖较新的 Node.js 特性,或者需要与云端服务保持版本一致,NVM 可以安装任意官方发布的版本。
  2. 多版本共存:同一个板子上可能运行多个不同的 Node.js 应用,它们要求的 Node.js 版本可能不同。NVM 可以让你为每个项目(甚至每个终端会话)快速切换版本。
  3. 规避系统污染:将 Node.js 安装在用户目录下,不需要sudo权限,避免了因误操作影响系统稳定性,卸载也更为干净。

3.2 使用国内源安装 NVM

NVM 的官方安装脚本托管在 GitHub,从国内访问可能速度慢或不稳定。幸运的是,有国内开发者维护了镜像和安装脚本。我们采用一个修改后的脚本来加速安装过程。

首先,下载国内社区维护的安装脚本:

curl -fsSL https://gitee.com/RubyKids/nvm-cn/raw/main/install.sh -o install.sh

下载后,不要直接运行。我们需要先检查并修改脚本,确保它从国内的 Gitee 镜像仓库克隆 NVM 源码,而不是 GitHub。用vimnano打开install.sh文件:

nano install.sh

找到脚本中克隆仓库的部分(通常在靠前的位置,例如原脚本的34-40行附近)。我们需要将git clone的源地址从 GitHub 改为 Gitee 的镜像地址。修改后的关键片段应如下所示:

export NVM_DIR="$HOME/.nvm" && ( echo "=> Git clone nvm" git clone https://gitee.com/mirrors/nvm.git "$NVM_DIR" cd "$NVM_DIR" git checkout `git describe --abbrev=0 --tags --match "v[0-9]*" $(git rev-list --tags --max-count=1)` ) && . "$NVM_DIR/nvm.sh"

这里将仓库地址改为了https://gitee.com/mirrors/nvm.git,这是 NVM 的一个国内镜像,下载速度会快很多。

修改保存后,执行安装:

bash install.sh

安装脚本会自动克隆 NVM 仓库到~/.nvm目录,并将初始化命令添加到你的 shell 配置文件(如~/.bashrc~/.zshrc)中。

安装最后,脚本可能会提示你输入密码,以尝试将nvm-update脚本安装到/usr/local/bin/在嵌入式设备上,这一步通常可以跳过。直接按Ctrl + C终止即可,这不会影响 NVM 的核心功能。我们后续更新 NVM 本身完全可以在用户目录下进行。

安装完成后,需要重新加载 shell 配置,或者新开一个终端窗口,以使nvm命令生效:

source ~/.bashrc # 或者如果你用的是 zsh: source ~/.zshrc

现在,可以验证 NVM 是否安装成功:

nvm --version

如果输出版本号(如0.39.7),说明安装成功。

3.3 在 RISC-V 架构上安装 Node.js

这是最关键也最容易出问题的一步。直接运行nvm install --ltsnvm install node,NVM 会尝试下载对应架构的预编译二进制包。但 Node.js 官方不提供riscv64的预编译包,因此下载会失败。

NVM 的 fallback 机制是:如果找不到预编译二进制包,它会尝试从源码编译。编译 Node.js 对设备的内存和 CPU 有一定要求,好在芒果派 MQ Quad 的 512MB 内存勉强够用,但编译过程会非常漫长(可能需要数小时)。

操作步骤与核心命令:

  1. 指定从源码编译:我们可以通过-s参数明确告诉 NVM 从源码安装。

    nvm install -s 18.19.0

    这里我选择了 18.19.0 这个 LTS 版本,相对稳定且生态兼容性好。你可以替换成任何你需要的版本号。

  2. 漫长的编译过程:执行上述命令后,NVM 会开始下载 Node.js 源码包,并运行./configuremakemake install。屏幕上会滚动大量的编译信息。在这个过程中,请保持 SSH 连接稳定,避免中断。如果编译因网络或内存不足失败,可以尝试交换分区(swap)来缓解。

  3. 启用交换文件(可选但强烈建议):编译 Node.js 可能耗尽内存。我们可以临时创建一个交换文件来充当虚拟内存。

    # 创建一个 1GB 的交换文件 sudo fallocate -l 1G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile

    编译完成后,可以关闭并删除交换文件以释放存储空间:

    sudo swapoff /swapfile sudo rm /swapfile
  4. 验证安装:编译安装完成后,使用以下命令查看已安装的版本并设置为默认。

    nvm list nvm alias default 18.19.0 node --version npm --version

    nvm list会列出所有安装的版本,当前使用的版本前会有一个箭头->nvm alias default可以设置默认版本,这样新开的终端也会自动使用这个版本。

实操心得与避坑指南

  • 耐心是关键:在单核 RISC-V 上编译 Node.js 可能长达 3-5 小时。建议在晚上或不需要使用板子的时候进行。
  • 确保依赖完整:如果编译失败,仔细查看错误日志。常见的失败原因是缺少某些开发库。你可能需要额外安装python3pkg-config等。根据错误提示使用apt安装对应的-dev包。
  • 版本选择:不建议安装太新的奇数版本(如 19.x, 21.x),优先选择 LTS(长期支持)版本,如 18.x 或 20.x,它们在嵌入式环境下的稳定性和社区支持更好。
  • NPM 源优化:安装好 Node.js 后,建议立即将 NPM 的注册表源换成国内镜像,加速后续安装包的速度。
npm config set registry https://registry.npmmirror.com/

4. EMQX MQTT Broker 部署与配置

Node.js 环境就绪后,我们需要部署 MQTT 消息服务器。EMQX 是一个开源的高性能 MQTT 5.0 Broker,用 Erlang/OTP 语言编写,非常适合物联网场景,支持海量并发连接。幸运的是,EMQX 官方为多种架构提供了预编译的安装包,其中就包括arm64riscv64

4.1 通过官方 Apt 源安装 EMQX

这是最推荐的方式,便于后续管理和升级。

  1. 导入 EMQX Apt 仓库的 GPG 密钥并添加源

    # 安装必要的工具以处理 apt 仓库 sudo apt install -y gnupg curl # 添加 GPG 密钥 curl -s https://packages.emqx.io/gpg.pub | sudo apt-key add - # 添加 EMQX Apt 源 echo "deb [arch=riscv64] https://packages.emqx.io/emqx-ce/deb/debian/ ./" | sudo tee /etc/apt/sources.list.d/emqx.list

    注意[arch=riscv64]这个部分,它明确指定了这个源用于riscv64架构的包。这是成功的关键。

  2. 更新本地包索引并安装 EMQX

    sudo apt update sudo apt install emqx

    apt update会从新添加的 EMQX 源拉取软件包信息。如果一切顺利,apt install emqx就会下载并安装针对 RISC-V 64 架构编译好的 EMQX 软件包及其所有依赖。

4.2 管理 EMQX 服务

EMQX 安装后,会作为一个系统服务(systemd service)运行。

  1. 启动与启用开机自启

    sudo systemctl start emqx # 立即启动服务 sudo systemctl enable emqx # 设置开机自动启动
  2. 检查服务状态

    sudo systemctl status emqx

    如果状态显示为active (running),则说明 EMQX 已成功启动。

  3. 使用 EMQX CLI 工具验证: EMQX 提供了一个命令行工具来检查 Broker 状态。

    emqx ctl broker

    这个命令会输出 EMQX 的版本、运行时间、集群状态等概要信息。看到类似Node ‘emqx@127.0.0.1’ started的输出,就证明 Broker 核心运行正常。

4.3 访问 Web 管理控制台并进行基础安全配置

EMQX 默认开启了基于 Web 的管理控制台,这对于监控和配置来说非常方便。

  1. 确定访问地址:首先获取芒果派的 IP 地址。

    ip addr show

    找到eth0(有线网卡)或wlan0(无线网卡)对应的inet地址。

  2. 登录控制台:在同一局域网内的电脑浏览器中,输入http://<你的芒果派IP>:18083。例如http://192.168.50.60:18083

    • 默认用户名admin
    • 默认密码public

    重要:首次登录后,务必立即修改默认密码!在控制台的Management->Users页面可以修改 admin 用户的密码。

  3. 基础配置检查

    • 监听端口:在Management->Listeners页面,确认默认的 MQTT TCP 监听器(端口 1883)和 WebSocket 监听器(端口 8083)是否处于运行状态。这是客户端连接所使用的端口。
    • 系统监控:在Monitoring页面,可以查看连接数、消息吞吐量、系统资源(CPU、内存)使用情况。对于内存只有 512MB 的 MQ Quad,需要密切关注内存使用。

注意事项

  • 防火墙:如果无法从外部访问 18083(管理台)或 1883(MQTT),请检查芒果派系统的防火墙设置(如ufw)是否放行了这些端口。
  • 性能考量:EMQX 默认配置是为服务器设计的。在资源受限的嵌入式设备上,可能需要调整 Erlang VM 参数以限制内存使用。配置文件位于/etc/emqx/emqx.conf。一个简单的优化是减少最大连接数和会话数,例如修改node.max_connectionszone.external.max_connections为一个较小的值(如 1000)。
  • 数据持久化:默认配置下,消息和会话数据存储在内存中。板子断电会丢失。如果需要对消息进行持久化,需要配置 EMQX 使用外部数据库(如 PostgreSQL)或内置的 Mnesia 数据库持久化,但这会显著增加存储 I/O 和内存开销,需根据项目需求权衡。

5. 环境整合验证与示例应用

部署好 Node.js 和 EMQX 后,我们需要验证它们是否能协同工作。一个经典的测试是:编写一个简单的 Node.js 脚本,使用 MQTT 客户端库连接到本地的 EMQX Broker,进行消息的发布和订阅。

5.1 创建测试项目并安装 MQTT 客户端库

在家目录下创建一个测试目录,并初始化一个 Node.js 项目。

mkdir ~/mqtt-test && cd ~/mqtt-test npm init -y

安装一个流行的 MQTT 客户端库,例如mqtt

npm install mqtt

5.2 编写测试脚本

创建一个名为test.js的文件,内容如下:

const mqtt = require('mqtt'); // 连接到本地 EMQX Broker,默认端口 1883 const client = mqtt.connect('mqtt://localhost:1883'); client.on('connect', function () { console.log('✅ 已连接到 MQTT Broker'); // 订阅一个测试主题 client.subscribe('mangopi/test', function (err) { if (!err) { console.log('📨 已订阅主题: mangopi/test'); // 订阅成功后,向该主题发布一条消息 client.publish('mangopi/test', 'Hello from MangoPi MQ Quad!'); } }); }); // 接收消息的回调 client.on('message', function (topic, message) { // message 是 Buffer,需要转成字符串 console.log(`📩 收到消息 [${topic}]: ${message.toString()}`); // 收到消息后,断开连接(仅用于测试) client.end(); }); client.on('error', function (error) { console.error('❌ 连接错误:', error); });

这个脚本做了三件事:

  1. 连接到本机 EMQX。
  2. 连接成功后,订阅主题mangopi/test
  3. 订阅成功后,立即向同一个主题发布一条消息。
  4. 当收到自己发布的消息时,打印出来并断开连接。

5.3 运行测试并观察结果

在终端运行脚本:

node test.js

预期输出

✅ 已连接到 MQTT Broker 📨 已订阅主题: mangopi/test 📩 收到消息 [mangopi/test]: Hello from MangoPi MQ Quad!

如果看到以上输出,恭喜你!这证明:

  1. Node.js 环境工作正常,可以执行 JavaScript 代码并加载第三方模块。
  2. EMQX Broker 工作正常,成功接受了 TCP 连接、处理了订阅和发布请求。
  3. 整个消息通路(发布 -> Broker -> 订阅)是畅通的。

你还可以打开 EMQX 的 Web 控制台,在Monitoring->ClientsMonitoring->Topics页面,实时看到这个测试客户端的连接和消息流转情况。

6. 常见问题排查与性能优化实录

在实际部署和运行中,你可能会遇到以下问题。这里记录了我遇到的情况和解决方法。

6.1 NVM 及 Node.js 相关问题

问题1:nvm install -s编译失败,提示g++: internal compiler error: Killed (program cc1plus)

  • 原因:这通常是编译过程中内存耗尽,系统杀掉了编译进程。RISC-V 架构编译 Node.js 非常消耗内存。
  • 解决
    • 增加交换空间:如前文所述,创建并启用一个足够大的交换文件(如 2GB)。
    • 并行编译限制:通过环境变量限制make使用的 job 数量,减少瞬时内存压力。在运行nvm install前执行:
      export MAKE_JOBS=1 nvm install -s 18.19.0
    • 使用更轻量的版本:尝试安装稍旧一点的 LTS 版本(如 Node.js 16.x),其源码可能对内存需求略低。

问题2:使用npm install安装某些原生模块(如sqlite3,bcrypt)失败

  • 原因:这些模块包含需要针对本机架构编译的 C++ 代码。编译它们同样需要开发工具和库,且可能依赖特定版本的 Node.js 头文件。
  • 解决
    • 确保已安装build-essential,python3,make,g++
    • 尝试使用npm config set跳过可选依赖或指定 Python 路径。
    • 最根本的,优先寻找纯 JavaScript 实现的替代包(例如用better-sqlite3替代sqlite3,用bcryptjs替代bcrypt),它们无需编译,在异构架构上兼容性极佳。

6.2 EMQX 相关问题

问题3:无法通过浏览器访问http://<ip>:18083

  • 排查步骤
    1. 确认服务运行sudo systemctl status emqx查看状态。
    2. 确认监听端口sudo netstat -tlnp | grep 18083。如果看不到监听,可能是 EMQX 启动失败,查看日志sudo journalctl -u emqx -f
    3. 检查防火墙:Debian 可能默认安装了ufw。运行sudo ufw status。如果状态是active,需要放行端口:sudo ufw allow 18083/tcpsudo ufw allow 1883/tcp
    4. 检查网络:确保你的电脑和芒果派在同一个局域网子网内。

问题4:EMQX 运行一段时间后,板子内存占用过高,响应变慢

  • 分析与优化
    1. 监控:通过 Web 控制台或emqx ctl broker命令查看当前连接数和会话数。嵌入式场景下,连接数应控制在数百以内。
    2. 调整配置:编辑/etc/emqx/emqx.conf
      • 限制最大连接数:node.max_connections = 1000(根据实际情况调小)
      • 减少会话过期时间:session.max_lifetime = 2h(默认是永不过期)
      • 关闭非必需功能:如将log.levelinfo改为warning减少日志量;评估是否需要开启规则引擎 (rule_engine) 或数据桥接 (bridges),如果不用可以关闭相关配置。
    3. 重启服务:修改配置后,运行sudo systemctl restart emqx生效。

问题5:Node.js 应用作为 MQTT 客户端频繁断线重连

  • 可能原因
    • 网络不稳定。
    • 客户端代码没有正确处理keepalive和重连逻辑。
    • EMQX 侧配置的keepalive时间太短。
  • 解决
    • 在客户端代码中实现稳健的重连机制,监听closeerror事件。
    • 适当增加客户端的keepalive间隔(例如 60 秒)和 EMQX 的zone.external.keepalive配置。
    • 检查是否有其他进程占用了大量 CPU,导致客户端心跳响应不及时。

6.3 系统层面优化建议

对于芒果派 MQ Quad 这类资源有限的设备,一些系统级的优化能提升整体稳定性:

  1. 禁用不必要的系统服务:使用sudo systemctl list-unit-files --type=service查看,禁用如bluetooth,avahi-daemon等可能用不到的服务。
  2. 使用轻量级进程监控:考虑用htop替代top,或者使用glances进行更全面的监控。
  3. 日志管理:定期清理/var/log目录下的旧日志,防止占满存储。可以配置logrotate或使用journalctl的清理命令。

整个部署过程最耗时的部分就是在 RISC-V 上编译 Node.js,这需要极大的耐心。一旦基础环境搭建完成,后续的应用开发和部署就会顺畅很多。这套组合(Node.js + EMQX)为在芒果派这类边缘设备上构建实时、双向通信的物联网应用提供了一个非常坚实且灵活的基础。

http://www.jsqmd.com/news/866719/

相关文章:

  • Material3 组件选择、状态管理与避坑指南
  • 基于OpenHarmony与SC-3568HA的工业网关开发实战:从硬件选型到分布式应用
  • 工业视觉系统精度保障:CCD相机与镜头参数计算实战指南
  • 2026年最新英语作文批改工具推荐:适合学生用的好用清单
  • 构建之法阅读笔记08
  • 基于EsDA平台的串口设备联网与MQTT上云实战指南
  • Prompt工程进阶:从写Prompt到工程化Prompt管理
  • 新能源汽车动力域系统级测试:从HIL到自动化实战指南
  • BetterNCM Installer深度解析:网易云音乐插件管理的完整解决方案
  • 机器学习核心术语手册:从数据到部署的完整概念解析与实战指南
  • 如何将OpenClaw这类Agent工具接入Taotoken多模型服务
  • 当你的线程“互相等待”时:死锁的四个必要条件与 Java 代码中的“致命拥抱”
  • PET_RK3588_P01开发板深度评测:从硬件解析到AI实战应用
  • JTAG操作实战指南:从原理到嵌入式调试与Flash编程
  • 嵌入式AI实战:从模型量化到人形检测部署全流程解析
  • 蛋白质-配体相互作用分析终极指南:PLIP快速入门与实战应用
  • 2026最新北京本地国画艺考画室综合能力测评结果:央美国画培训与中国画校考集训怎么选 - 企业信息深度横评
  • Windows 10 21H1启用包机制解析与部署实战指南
  • SQL学习指南——再谈连接
  • Linux内核调度器心跳机制:scheduler_tick原理与性能调优
  • 新能源动力域系统级测试:从HIL仿真到自动化验证的完整解决方案
  • 基于EsDA平台实现串口设备联网:Modbus RTU转MQTT网关实战
  • Display Driver Uninstaller:彻底解决显卡驱动问题的3步终极指南
  • RISC-V嵌入式AI部署实战:NanoDet模型与ncnn框架移植指南
  • LangGraph实战:构建可控、可调试的复杂AI工作流
  • 抖音下载器:如何永久保存你喜欢的短视频内容?
  • 开源项目功能扩展技术方案:实现多账户管理与配置优化的完整指南
  • 抖音无水印下载终极指南:douyin-downloader让内容保存变得如此简单
  • 深入Linux调度器心跳:scheduler_tick原理、性能影响与调优实践
  • 网盘直链下载助手实战指南:八大平台免登录高速下载完整方案