> ## Documentation Index
> Fetch the complete documentation index at: https://docs.monad.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# 设置执行事件

本指南将引导您配置 Monad 节点以启用执行事件系统，该系统允许您构建通过共享内存以最低延迟接收事件数据的高性能应用。

## 前置条件

* 一个正在运行的 Monad 全节点（[全节点安装指南](/zh/node-ops/full-node-installation)）
* 一种稳定的方式来访问该节点

<Info title="为什么使用执行事件？">
  Monad 每 300 毫秒产生一个区块，并且每个区块可以处理数千笔交易。传统的 JSON-RPC 和 WebSocket API 可能跟不上如此的数据量。执行事件为消费实时区块链数据提供了吞吐量最高、延迟最低的方式。

  更多详情请参见[执行事件文档](/zh/execution-events/)。
</Info>

## 步骤 1：安装所需的软件包

安装用于管理巨页（huge pages）的 `hugeadm` 工具：

```bash theme={null}
sudo apt install libhugetlbfs-bin
```

<Accordion title="幕后原理">
  安装 `libhugetlbfs-bin` 软件包，其中提供了 `hugeadm` 命令行工具。该工具管理"巨页" —— 大内存页面（2MB 而非标准的 4KB），可以降低内存管理开销，并提升需要快速共享大量数据的应用（如执行事件）的性能。
</Accordion>

如果您计划使用执行事件 SDK（C、C++ 或 Rust）编写应用，还需要安装以下开发包：

```bash theme={null}
sudo apt install libhugetlbfs-dev libhugetlbfs0 libzstd-dev
```

<Accordion title="幕后原理">
  * **libhugetlbfs-dev**：用于开发使用巨页应用的头文件
  * **libhugetlbfs0**：支持巨页的运行时库
  * **libzstd-dev**：Zstandard 压缩库，SDK 中用于高效数据编码
</Accordion>

## 步骤 2：设置 `hugetlbfs` 挂载点

执行事件系统使用巨页进行高性能的共享内存通信。您需要创建一个持久化的 `hugetlbfs` 挂载点。

### 为持久化挂载创建 systemd 服务

创建服务文件：

```bash theme={null}
sudo nano /etc/systemd/system/events-hugepages-mounts.service
```

粘贴以下内容（如果您的用户不是 `monad`，请将其替换）：

```ini theme={null}
[Unit]
Description=Create hugepage mounts for monad
After=local-fs.target

[Service]
Type=oneshot
ExecStart=/usr/bin/hugeadm --create-user-mounts monad
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
```

<Accordion title="幕后原理">
  此 systemd 服务在启动时运行 `hugeadm --create-user-mounts monad`，它会：

  * 在 `/var/lib/hugetlbfs/user/monad/` 创建一个 `hugetlbfs` 文件系统挂载
  * 为不同的页面大小（2MB 和 1GB）设置独立的目录
  * 确保 `monad` 用户在这些目录中拥有创建文件的权限

  `Type=oneshot` 表示服务在启动时运行一次，而 `RemainAfterExit=yes` 会保持服务标记为"active"，以便 systemd 知道该挂载仍然需要。
</Accordion>

保存并退出（`Ctrl+O`、`Enter`、`Ctrl+X`）。

启用并启动服务：

```bash theme={null}
sudo systemctl daemon-reload
sudo systemctl enable --now events-hugepages-mounts
```

<Accordion title="幕后原理">
  * **daemon-reload**：告诉 systemd 重新读取所有服务文件，加载您新建的服务
  * **enable --now**：将服务设置为开机启动并立即启动

  此后，巨页挂载将在当前以及每次重启时可用。
</Accordion>

## 步骤 3：创建 event-rings 目录

执行守护进程会将事件数据写入此目录下的文件：

```bash theme={null}
sudo mkdir -p /var/lib/hugetlbfs/user/monad/pagesize-2MB/event-rings
sudo chown monad:monad /var/lib/hugetlbfs/user/monad/pagesize-2MB/event-rings
```

<Accordion title="幕后原理">
  * **mkdir -p**：创建 `event-rings` 目录（以及任何必需的父目录）
  * **chown monad:monad**：将所有权更改为 `monad` 用户，以便执行守护进程可以在此写入事件环文件

  路径 `/var/lib/hugetlbfs/user/monad/pagesize-2MB/` 是 `hugeadm` 创建 2MB 巨页挂载的位置。执行守护进程会在 `event-rings/` 中创建供消费者应用读取的共享内存文件。
</Accordion>

<Note>
  如果您以其他用户身份运行节点，请将 `monad` 替换为您的实际用户。
</Note>

## 步骤 4：配置执行守护进程

创建一个 systemd 覆盖配置以启用执行事件输出。

打开覆盖编辑器：

```bash theme={null}
sudo systemctl edit monad-execution
```

<Accordion title="幕后原理">
  打开一个文本编辑器，为 `monad-execution` 服务创建"覆盖"文件。覆盖允许您在不修改原始 unit 文件的情况下修改服务设置（否则在软件包更新时会被覆盖）。覆盖文件保存在 `/etc/systemd/system/monad-execution.service.d/override.conf`。
</Accordion>

添加以下配置：

```ini theme={null}
[Service]
ExecStart=
ExecStart=/usr/local/bin/monad \
    --chain "$CHAIN" \
    --db /dev/triedb \
    --block_db /home/monad/monad-bft/ledger \
    --statesync /home/monad/monad-bft/statesync.sock \
    --exec-event-ring /var/lib/hugetlbfs/user/monad/pagesize-2MB/event-rings/monad-exec-events \
    --sq_thread_cpu 1 \
    --log_level INFO
```

<Accordion title="幕后原理">
  * **ExecStart=**（空）：清除基础 unit 文件中的原始命令（覆盖所必需）
  * **ExecStart=/usr/local/bin/monad ...**：使用所有标志设置新命令
  * **--exec-event-ring**：启用执行事件输出的关键标志。它指定守护进程创建共享内存事件环文件的路径

  其他标志是从默认配置复制过来的标准执行守护进程选项。
</Accordion>

<Warning>
  两行 `ExecStart=` 都是必需的。第一行清除原始值，第二行使用 `--exec-event-ring` 标志设置新值。
</Warning>

重新加载并重启执行守护进程：

```bash theme={null}
sudo systemctl daemon-reload
sudo systemctl restart monad-execution
```

<Accordion title="幕后原理">
  * **daemon-reload**：告诉 systemd 重新读取所有服务文件，包括您新建的覆盖
  * **restart monad-execution**：使用新配置停止并启动执行守护进程

  重启后，守护进程将开始向共享内存环形缓冲区写入执行事件。
</Accordion>

## 步骤 5：为 WebSocket 支持配置 RPC 守护进程

此步骤启用 RPC 服务器的 WebSocket 支持，使您可以使用 `eth_subscribe` 获取实时数据。

<Warning>
  启用了 WebSocket 的 RPC 严格依赖于执行进程已启用事件。如果您在完成步骤 4 之前使用 `--ws-enabled` 启动 RPC，RPC 将崩溃。
</Warning>

打开 RPC 覆盖编辑器：

```bash theme={null}
sudo systemctl edit monad-rpc
```

<Accordion title="幕后原理">
  在 `/etc/systemd/system/monad-rpc.service.d/override.conf` 创建一个覆盖文件，用于自定义 RPC 服务配置。
</Accordion>

添加以下配置：

```ini theme={null}
[Service]
ExecStart=
ExecStart=/usr/local/bin/monad-rpc \
    --ipc-path /home/monad/monad-bft/mempool.sock \
    --triedb-path /dev/triedb \
    --otel-endpoint "http://0.0.0.0:4317" \
    --allow-unprotected-txs \
    --node-config /home/monad/monad-bft/config/node.toml \
    --exec-event-path /var/lib/hugetlbfs/user/monad/pagesize-2MB/event-rings/monad-exec-events \
    --ws-enabled
```

<Accordion title="幕后原理">
  * **ExecStart=**（空）：清除基础 unit 文件中的原始命令（覆盖所必需）
  * **--exec-event-path**：指向执行守护进程写入的同一个事件环文件
  * **--ws-enabled**：在端口 8081（默认）启用 WebSocket 支持
</Accordion>

重新加载并重启 RPC 守护进程：

```bash theme={null}
sudo systemctl daemon-reload
sudo systemctl restart monad-rpc
```

<Accordion title="幕后原理">
  * **daemon-reload**：告诉 systemd 重新读取所有服务文件，包括您新建的覆盖
  * **restart monad-rpc**：使用启用 WebSocket 的配置停止并启动 RPC 守护进程
</Accordion>

## 步骤 6：验证设置

检查事件环文件是否已创建：

```bash theme={null}
ls -la /var/lib/hugetlbfs/user/monad/pagesize-2MB/event-rings/
```

<Accordion title="幕后原理">
  列出 event-rings 目录中的内容。您应该会看到一个名为 `monad-exec-events` 的文件。这是执行守护进程写入、消费者应用读取的共享内存文件。
</Accordion>

您应该看到一个名为 `monad-exec-events`（或类似名称）的文件。

检查执行守护进程状态：

```bash theme={null}
sudo systemctl status monad-execution
```

<Accordion title="幕后原理">
  显示执行守护进程服务的当前状态。请留意：

  * **Active: active (running)** —— 服务正在运行
  * 最近的日志输出中没有错误消息

  如果您看到与事件环或巨页相关的错误，请查看下文的故障排查部分。
</Accordion>

服务应处于活动状态并且无错误运行。

### 检查 WebSocket 连通性

一种快速检查 WebSocket 连通性的方法是使用 [`websocat`](https://github.com/vi/websocat)，这是一个命令行 WebSocket 客户端。可以通过 `cargo install websocat` 或下载预编译二进制文件进行安装。

使用默认端口 8081 上的 WebSocket 服务在详细模式下运行它：

```bash theme={null}
websocat -v ws://localhost:8081
```

您应该看到类似如下的输出：

```
[INFO  websocat::lints] Auto-inserting the line mode
[INFO  websocat::stdio_threaded_peer] get_stdio_peer (threaded)
[INFO  websocat::ws_client_peer] get_ws_client_peer
[INFO  websocat::net_peer] Connected to TCP 127.0.0.1:8081
[INFO  websocat::ws_client_peer] Connected to ws
[INFO  websocat::ws_peer] Received WebSocket ping
```

要订阅新区块头，请输入下面的 JSON-RPC 调用并按回车：

```json theme={null}
{ "id": 1, "jsonrpc": "2.0", "method": "eth_subscribe", "params": ["newHeads"] }
```

大约每半秒钟，您应该会看到关于新区块的更新。

## 后续步骤

在启用执行事件和 WebSocket 支持后，您现在可以：

* **构建自己的数据消费者**：使用执行事件 SDK 用 C、C++ 或 Rust 编写高性能应用。请参阅[入门指南](/zh/execution-events/getting-started/)以获取示例。

* **深入了解 WebSocket 订阅**：请参阅 [WebSocket 指南](/zh/reference/json-rpc/overview) 了解所有可用的订阅类型。

## 故障排查

### 事件环文件未创建

确保巨页挂载处于活动状态：

```bash theme={null}
mount | grep hugetlbfs
```

<Accordion title="幕后原理">
  列出所有已挂载的文件系统并过滤 `hugetlbfs` 挂载。您应该看到类似如下的输出：

  ```
  hugetlbfs on /var/lib/hugetlbfs/user/monad/pagesize-2MB type hugetlbfs (rw,relatime,...)
  ```

  如果没有输出，则说明巨页挂载未激活。
</Accordion>

您应该看到类似 `/var/lib/hugetlbfs/user/monad/pagesize-2MB` 的挂载点。

如果没有，请重启巨页服务：

```bash theme={null}
sudo systemctl restart events-hugepages-mounts
```

<Accordion title="幕后原理">
  重新运行巨页挂载服务，该服务将重新创建 `hugetlbfs` 挂载点。之后，再次运行 `mount | grep hugetlbfs` 命令以验证。
</Accordion>

### 执行守护进程无法启动

查看日志中的错误：

```bash theme={null}
sudo journalctl -u monad-execution -f
```

<Accordion title="幕后原理">
  * **journalctl -u monad-execution**：显示执行守护进程服务的日志
  * **-f**：实时跟随日志（类似于 `tail -f`）

  按 `Ctrl+C` 停止跟随。请查找涉及事件环路径、权限或巨页的错误消息。
</Accordion>

常见问题：

* `event-rings` 目录不存在或权限错误
* 巨页挂载不可用
* systemd 覆盖中的路径不正确

### 权限被拒绝错误

确保 `event-rings` 目录归属正确的用户：

```bash theme={null}
sudo chown -R monad:monad /var/lib/hugetlbfs/user/monad/
```

<Accordion title="幕后原理">
  递归地将整个巨页目录树的所有权更改为 `monad` 用户。`-R` 标志确保所有子目录和文件都被更新。
</Accordion>

## 更多资源

* [执行事件文档](/zh/execution-events/) - 执行事件系统的全面文档
* [执行事件概述](/zh/execution-events/overview) - 核心概念与事件类型
* [C API 参考](/zh/execution-events/c-api) - C 库文档
* [Rust API 参考](/zh/execution-events/rust-api) - Rust crate 文档
* [执行事件与 WebSocket 设置](/zh/node-ops/events-and-websockets) - 在 RPC 中启用 WebSocket 支持
