[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-83248":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":15,"stars7d":16,"stars30d":16,"stars90d":15,"forks30d":15,"starsTrendScore":15,"compositeScore":17,"rankGlobal":10,"rankLanguage":10,"license":10,"archived":18,"fork":18,"defaultBranch":19,"hasWiki":20,"hasPages":18,"topics":21,"createdAt":10,"pushedAt":22,"updatedAt":23,"readmeContent":24,"aiSummary":10,"trendingCount":15,"starSnapshotCount":15,"syncStatus":16,"lastSyncTime":25,"discoverSource":26},83248,"r0rpc","manyuegong33\u002Fr0rpc","manyuegong33","to android,ios rpc","",null,"Go",58,20,51,0,2,41.97,false,"main",true,[],"2026-06-10 00:42:13","2026-06-10 05:39:02","# R0RPC 项目总览\n\nR0RPC 是一个面向设备侧的 RPC 中继平台，整体思路类似 Sekiro RPC，但更偏向“可部署、可管理、可观测”的后台化方案。\n\n它适合把 Android、Xposed、Java 或 Python 侧设备接入到服务端，然后由业务后端按 `group` 或指定 `clientId` 发起调用。设备收到任务后执行动作，并把结果实时回传给调用方。\n\n## 快速导航\n\n- 部署入口：`deploy\u002Flinux\u002Fquickstart.sh`\n- 管理后台：`http:\u002F\u002FYOUR_SERVER_IP:9876\u002F`\n- 健康检查：`http:\u002F\u002FYOUR_SERVER_IP:9876\u002Fhealthz`\n- 配置模板：`deploy\u002Flinux\u002F.env.example`\n- 运行配置：`deploy\u002Flinux\u002F.env.docker`\n- Java SDK：`clients\u002Fjava\u002F`\n- Xposed 示例：`clients\u002Fxposed-demo\u002F`\n- Python 示例：`examples\u002Fpython\u002F`\n\n## 1. 项目是什么\n\nR0RPC 的核心目标是：\n\n1. 让后端服务可以按 `group` 或指定 `clientId` 把请求发到在线设备\n2. 让设备执行动作后，把结果实时回传给后端\n3. 提供管理后台，用来查看账号、分组、设备、调用记录、统计指标和在线状态\n4. 支持 Linux 一键部署，默认可连本机 Docker MySQL\u002FRedis，也支持接入外部 MySQL\u002FRedis\n\n当前版本以 Linux 部署为主，不再围绕 Windows 本地启动维护。\n\n## 2. 核心特性\n\n- WebSocket 长连接：设备在线后通过 WebSocket 收任务、回结果\n- 分组治理：`group` 必须先在后台创建，才能被设备登录和 RPC 调用使用\n- 在线设备队列：按 `group` 查看在线设备，支持轮询分发\n- 指定设备调用：传入 `clientId` 后只发给指定设备\n- 管理后台：查看账号、分组、设备、调用记录、趋势指标\n- Linux 一键部署：自动安装 Docker、启动依赖、初始化数据库、拉起服务\n- 配置集中化：运行参数集中放在 `deploy\u002Flinux\u002F.env.docker`\n- Java\u002FXposed\u002FPython 示例：方便设备侧和脚本侧快速联调\n\n## 3. 项目结构\n\n```text\ncmd\u002F                  Go 程序入口\ncmd\u002Fserver            主服务入口\ncmd\u002Fdbinit            数据库初始化入口\n\ninternal\u002F             Go 服务核心代码\ninternal\u002Fconfig       配置读取\ninternal\u002Fstore        MySQL\u002FRedis 存储逻辑\ninternal\u002Frpc          RPC 调度逻辑\ninternal\u002Fweb          Web API、WebSocket、内置前端\n\ndeploy\u002Flinux\u002F         Linux 一键部署入口\nclients\u002Fjava\u002F         Java Relay Client SDK\nclients\u002Fxposed-demo\u002F  Android\u002FXposed 示例项目\nexamples\u002Fpython\u002F      Python 调用和设备端示例\n```\n\n## 4. 系统工作流程\n\n系统可以理解成三层：\n\n1. 调用方  \n   一般是业务后端、Python 脚本，或者其他服务。它通过 HTTP 调用 R0RPC。\n\n2. R0RPC 服务端  \n   负责认证、校验分组、查找在线设备、路由请求、等待结果、记录日志和指标。\n\n3. 设备客户端  \n   设备端先登录，再通过 WebSocket 长连接保持在线。收到任务后执行动作，并把结果回传给服务端。\n\n一次完整调用大致是：\n\n```text\n设备登录 -> 建立 WebSocket -> 调用方发起 RPC -> 服务端选择在线设备\n       -> WebSocket 下发任务 -> 设备执行 action -> 服务端同步返回结果\n```\n\n调用接口形式：\n\n```text\nPOST \u002Frpc\u002Finvoke\u002F{group}\u002F{action}\n```\n\n如果没有指定 `clientId`，服务端会在同组在线设备里轮询分发。如果指定了 `clientId`，就只发给指定设备。\n\n## 5. Group 使用规则\n\n现在 `group` 不是随便填的字符串，必须先创建后使用。\n\n推荐流程：\n\n1. 先在管理后台创建 `group`\n2. 设备登录时使用这个 `group`\n3. 调用方通过 `\u002Frpc\u002Finvoke\u002F{group}\u002F{action}` 发起请求\n4. 需要查看在线设备时，通过 `\u002Frpc\u002FclientQueue?group=...` 查询\n\n异常行为：\n\n- `group` 不存在：返回 `group_not_found`，HTTP 状态码 `404`\n- `group` 被禁用：返回 `group_disabled`，HTTP 状态码 `403`\n- `group` 不存在的调用不会计入 RPC 调用统计，也不会写入正常调用记录\n- `clientQueue` 查询同样要求 `group` 已存在且启用\n\n这样可以避免任意人随便构造一个 `group` 就能发起请求，也让后台里的分组更可控。\n\n## 6. 传输方式\n\n当前主通道是 WebSocket。\n\n设备侧流程：\n\n1. `POST \u002Fapi\u002Fclient\u002Flogin`\n2. 读取返回里的 `token` 和 `wsUrl`\n3. 连接 `GET \u002Fapi\u002Fclient\u002Fws?token=...`\n4. 周期性发送 heartbeat\n5. 接收任务并回传结果\n\n这种方式的好处是：\n\n- 设备在线时延更低\n- 空闲时 HTTP 开销更小\n- 更适合大量设备常驻连接\n\n## 7. 管理后台\n\n默认访问：\n\n```text\nhttp:\u002F\u002FYOUR_SERVER_IP:9876\u002F\n```\n\n后台可以查看和管理：\n\n- 管理员账号\n- 分组列表\n- 设备列表\n- 调用记录\n- 统计指标\n- 在线状态\n- 手动 RPC 调试\n\n默认管理账号：\n\n```text\n用户名：admin\n密码：123456\n```\n\n注意：默认密码来自 `deploy\u002Flinux\u002F.env.docker` 里的 `BOOTSTRAP_ADMIN_PASSWORD`。这个配置只在管理员账号不存在时用于初始化账号；如果账号已经存在，改配置不会覆盖已有密码。\n\n## 8. 常用接口\n\n### 8.1 管理员登录\n\n接口：\n\n```text\nPOST \u002Fapi\u002Fauth\u002Flogin\n```\n\n请求：\n\n```json\n{\n  \"username\": \"admin\",\n  \"password\": \"123456\"\n}\n```\n\n返回里重点看：\n\n- `token`\n- `user`\n\n### 8.2 查询 group 下的设备\n\n接口：\n\n```text\nGET \u002Frpc\u002FclientQueue?group={groupName}\n```\n\n可选参数：\n\n- `group`：必填，分组名\n- `status`：可选，设备状态过滤\n- `limit`：可选，返回数量上限\n\n示例：\n\n```bash\ncurl \"http:\u002F\u002F127.0.0.1:9876\u002Frpc\u002FclientQueue?group=idlefish\"\n```\n\n返回示意：\n\n```json\n{\n  \"group\": \"idlefish\",\n  \"count\": 2,\n  \"clientIds\": [\"device-a\", \"device-b\"],\n  \"items\": [\n    {\n      \"clientId\": \"device-a\",\n      \"group\": \"idlefish\",\n      \"platform\": \"android\",\n      \"status\": \"online\",\n      \"lastSeenAt\": \"2026-04-01T16:00:00+08:00\",\n      \"lastIp\": \"10.0.0.12\"\n    }\n  ]\n}\n```\n\n如果只想看在线设备，不传 `status` 即可。这个接口默认优先返回在线设备队列。\n\n### 8.3 发起 RPC 调用\n\n接口：\n\n```text\nPOST \u002Frpc\u002Finvoke\u002F{group}\u002F{action}\n```\n\n当前支持两种认证方式：\n\n1. Header 里带 Bearer Token\n2. 请求体里直接带 `username` 和 `password`\n3. token会缓存，只有第一次会查询数据库，后面会缓存12小时，无论是请求体带账号信息或者先登录带token都会缓存\n\n推荐的简单调用体：\n\n```json\n{\n  \"username\": \"admin\",\n  \"password\": \"123456\",\n  \"timeoutSeconds\": 20,\n  \"payload\": {\n    \"encode_str\": \"xxx\"\n  }\n}\n```\n\n如果要指定设备，多传一个 `clientId`：\n\n```json\n{\n  \"username\": \"admin\",\n  \"password\": \"123456\",\n  \"clientId\": \"device-001\",\n  \"timeoutSeconds\": 20,\n  \"payload\": {\n    \"encode_str\": \"xxx\"\n  }\n}\n```\n\n字段说明：\n\n- `username`：管理员账号\n- `password`：管理员密码\n- `clientId`：可选，指定某一台设备；不传就按 group 轮询在线设备\n- `timeoutSeconds`：可选，请求超时时间，单位是秒；不传时走服务端默认值，当前默认是 `25` 秒\n- `payload`：真正发给设备 action 的参数对象，建议直接写扁平结构，不要再多套一层 `payload`\n\n调用示例：\n\n```bash\ncurl -X POST \"http:\u002F\u002F127.0.0.1:9876\u002Frpc\u002Finvoke\u002Fidlefish\u002Fdecrypt\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"username\": \"admin\",\n    \"password\": \"123456\",\n    \"timeoutSeconds\": 20,\n    \"payload\": {\n      \"encode_str\": \"v7eNwdELBmc1hOkagpP6NQ==\"\n    }\n  }'\n```\n\n### 8.4 调用返回结构\n\n服务端返回统一结构，重点看这些字段：\n\n- `is_ok`\n- `status`\n- `httpCode`\n- `requestId`\n- `clientId`\n- `data`\n- `error`\n\n判断成功失败时，建议直接看 `is_ok`：\n\n- `true`：本次调用成功\n- `false`：本次调用失败\n\n成功示例：\n\n```json\n{\n  \"is_ok\": true,\n  \"requestId\": \"xxx\",\n  \"group\": \"idlefish\",\n  \"action\": \"decrypt\",\n  \"clientId\": \"a9178e59d1d77782\",\n  \"requestPayload\": {\n    \"encode_str\": \"v7eNwdELBmc1hOkagpP6NQ==\"\n  },\n  \"status\": \"success\",\n  \"httpCode\": 200,\n  \"data\": {\n    \"data\": \"解密结果\"\n  },\n  \"latencyMs\": 132,\n  \"error\": \"\"\n}\n```\n\n超时示例：\n\n```json\n{\n  \"is_ok\": false,\n  \"status\": \"timeout\",\n  \"httpCode\": 504,\n  \"requestId\": \"xxx\",\n  \"group\": \"idlefish\",\n  \"action\": \"decrypt\",\n  \"clientId\": \"a9178e59d1d77782\",\n  \"requestPayload\": {\n    \"encode_str\": \"v7eNwdELBmc1hOkagpP6NQ==\"\n  },\n  \"error\": \"context deadline exceeded\"\n}\n```\n\n## 9. 设备端接入\n\n### 9.1 Java \u002F Xposed\n\n相关目录：\n\n- `clients\u002Fjava\u002F`\n- `clients\u002Fxposed-demo\u002F`\n\n当前 Java\u002FXposed 的 handler 写法：\n\n1. 用 `registerHandler(\"action\", handler)` 注册动作\n2. handler 内实现 `handleRequest(...)`\n3. 请求参数推荐走扁平 `payload`\n4. 需要时可用 `@AutoBind` 直接把 payload 字段绑定到成员变量\n\n示意：\n\n```java\nrelayClient.registerHandler(\"decrypt\", new DecryptHandler());\n```\n\n```java\npublic class DecryptHandler implements RelayHandler {\n    @AutoBind\n    private String encode_str;\n\n    @Override\n    public void handleRequest(RelayRequest request, RelayResponse response) throws Exception {\n        response.success(encode_str);\n    }\n}\n```\n\n如果 Java SDK 还是本地 jar，可以先用：\n\n```gradle\nimplementation files('libs\u002Fr0rpc-relay-client.jar')\n```\n\n如果后面发布到 Maven 仓库，就可以改成类似 Sekiro 这种形式：\n\n```gradle\nimplementation 'com.yourgroup:r0rpc-relay-client:版本号'\n```\n\n坐标需要以实际发布到 Maven 的 groupId、artifactId、version 为准。\n\n### 9.2 Python\n\n相关目录：\n\n- `examples\u002Fpython\u002F`\n- `examples\u002Fpython\u002Finvoke_demo.py`\n- `examples\u002Fpython\u002Ftest_decrypt_demo.py`\n\nPython 侧可以作为调用方，也可以模拟设备端通过 WebSocket 接入。\n\n## 10. Linux 部署\n\n### 10.1 支持系统\n\n自动安装脚本目前支持：\n\n- Ubuntu\n- Debian\n- CentOS\n- RHEL\n- Rocky Linux\n- AlmaLinux\n- Oracle Linux\n\n### 10.2 一键部署\n\n默认最快方式：\n\n```bash\ncd deploy\u002Flinux\nchmod +x quickstart.sh\n.\u002Fquickstart.sh\n```\n\n如果脚本是从 Windows 复制到 Linux 的，先处理换行：\n\n```bash\ncd deploy\u002Flinux\u002F\nfor f in *.sh; do sed -i 's\u002F\\r$\u002F\u002F' \"$f\"; done\nchmod +x *.sh\nbash -x .\u002Fquickstart.sh\n```\n\n这个流程会做：\n\n1. 检查 `docker` 和 `docker compose`\n2. 如果缺失则自动安装\n3. 如果没有 `.env.docker`，就从 `.env.example` 自动生成\n4. 按当前模式启动 MySQL、Redis、R0RPC\n5. 等待依赖服务就绪\n6. 自动初始化数据库\n7. 启动服务端\n\n### 10.3 默认部署模式\n\n默认配置：\n\n```text\nMYSQL_MODE=builtin\nREDIS_MODE=builtin\n```\n\n含义：\n\n- MySQL 用本机 Docker 启动\n- Redis 用本机 Docker 启动\n- R0RPC 也在 Docker 中启动\n\n也就是默认整套服务都在 Linux 机器本地拉起，最省事。\n\n### 10.4 使用外部 MySQL \u002F Redis\n\n如果你已经有自己的 MySQL \u002F Redis，只需要改 `deploy\u002Flinux\u002F.env.docker`：\n\n```text\nMYSQL_MODE=external\nREDIS_MODE=external\nMYSQL_HOST=10.0.0.12\nMYSQL_PORT=3306\nMYSQL_USER=root\nMYSQL_PASSWORD=your-password\nMYSQL_DB=r0rpc\nREDIS_ADDR=10.0.0.13:6379\nREDIS_PASSWORD=your-password\nREDIS_DB=0\n```\n\n然后执行：\n\n```bash\ncd deploy\u002Flinux\n.\u002Fdeploy.sh\n```\n\n### 10.5 混合模式\n\n也可以一部分内置，一部分外部。例如 MySQL 用内置，Redis 用外部：\n\n```text\nMYSQL_MODE=builtin\nREDIS_MODE=external\nREDIS_ADDR=10.0.0.13:6379\nREDIS_PASSWORD=your-password\nREDIS_DB=0\n```\n\n### 10.6 数据库初始化\n\n不需要手工建库、建表、导入 SQL。\n\n当前 Linux 启动链路已经自动处理：\n\n1. 检查 MySQL 是否可连\n2. 检查 Redis 是否可连\n3. 自动执行 `\u002Fapp\u002Fr0rpc-dbinit`\n4. 自动创建数据库和表\n5. 自动确保管理员账号存在\n6. 然后再启动 `\u002Fapp\u002Fr0rpc-server`\n\n### 10.7 常用命令\n\n安装 Docker 和 Compose：\n\n```bash\ncd deploy\u002Flinux\n.\u002Finstall-docker.sh\n```\n\n部署：\n\n```bash\ncd deploy\u002Flinux\n.\u002Fdeploy.sh\n```\n\n停止：\n\n```bash\ncd deploy\u002Flinux\n.\u002Fstop.sh\n```\n\n## 11. 配置文件说明\n\n### 11.1 `.env.example` 和 `.env.docker`\n\n`deploy\u002Flinux\u002F.env.example` 是部署配置模板。\n\n第一次部署时，脚本会复制一份生成：\n\n```text\ndeploy\u002Flinux\u002F.env.docker\n```\n\n真正运行时读的是 `.env.docker`。Docker 内部会把它挂载成：\n\n```text\n\u002Fapp\u002Fr0rpc.conf\n```\n\n建议：\n\n- `.env.example` 保持完整参考\n- `.env.docker` 放你机器上的真实运行配置\n- MySQL、Redis、心跳、掉线判断、数据保留、队列、管理员初始化都集中在 `.env.docker` 里改\n\n### 11.2 基础信息\n\n- `APP_NAME`：应用名称，健康检查和后台展示用\n- `SERVER_ID`：服务节点 ID，多节点时方便区分是哪台服务\n- `TZ`：Docker 容器时区\n- `TIME_ZONE`：服务内部时间解析和展示时区\n- `HTTP_ADDR`：容器内监听地址，默认 `:8080`\n- `HTTP_EXPOSE_PORT`：宿主机暴露端口，默认 `9876`\n- `JWT_SECRET`：JWT 签名密钥；留空时部署脚本会生成并写回 `.env.docker`\n\n### 11.3 RPC、心跳和在线状态\n\n- `REQUEST_TIMEOUT_SECONDS`：RPC 默认超时时间，单位秒，当前默认 `25`\n- `DEVICE_OFFLINE_SECONDS`：设备多久没有心跳或消息就判定离线，单位秒，当前默认 `20`\n- `DEVICE_OFFLINE_MINUTES`：旧版兼容配置，正常保持 `0`\n- `HEARTBEAT_INTERVAL_SECONDS`：设备心跳间隔，当前默认 `5`\n- `PRESENCE_FLUSH_SECONDS`：在线状态刷新间隔，当前默认 `5`\n\n当前默认含义是：设备大约 `5` 秒发一次心跳，服务端超过 `20` 秒没有收到心跳或消息，就认为设备离线。\n\n### 11.4 数据保留\n\n- `RAW_RETENTION_DAYS`：原始 RPC 请求和响应明细保留天数，当前默认 `3`\n- `AGGREGATE_RETENTION_DAYS`：日统计聚合数据保留天数，当前默认 `30`\n- `RAW_REQUEST_KEEP_LATEST_PER_SCOPE`：group + action + clientId 保留条数，默认1000\n也就是说，详细调用记录默认保留 3 天，日统计指标默认保留 30 天。\n\n### 11.5 队列和并发\n\n- `PERSIST_QUEUE_SIZE`：异步持久化队列大小\n- `PERSIST_WORKERS`：持久化 worker 数量\n- `CLIENT_QUEUE_SIZE`：单客户端任务队列大小\n- `CLIENT_MAX_IN_FLIGHT`：单客户端最大并发处理中任务数\n\n服务端会强制这些最小值，避免误配得太小：\n\n```text\nPERSIST_QUEUE_SIZE >= 131072\nPERSIST_WORKERS >= 32\nCLIENT_QUEUE_SIZE >= 2048\nCLIENT_MAX_IN_FLIGHT >= 256\n```\n\n### 11.6 服务模式\n\n- `MYSQL_MODE=builtin`：启动 Docker 内置 MySQL\n- `MYSQL_MODE=external`：使用你已有的外部 MySQL\n- `REDIS_MODE=builtin`：启动 Docker 内置 Redis\n- `REDIS_MODE=external`：使用你已有的外部 Redis\n\n默认是：\n\n```text\nMYSQL_MODE=builtin\nREDIS_MODE=builtin\n```\n\n### 11.7 MySQL\n\n- `MYSQL_ROOT_PASSWORD`：内置 MySQL 的 root 密码\n- `MYSQL_HOST`：MySQL 地址；内置模式保持 `mysql`\n- `MYSQL_PORT`：MySQL 端口，默认 `3306`\n- `MYSQL_USER`：连接 MySQL 的用户名\n- `MYSQL_PASSWORD`：连接 MySQL 的密码\n- `MYSQL_DB`：数据库名，默认 `r0rpc`\n- `MYSQL_EXPOSE_PORT`：内置 MySQL 暴露到宿主机的端口\n- `MYSQL_PARAMS`：MySQL DSN 参数，包含字符集、时区和超时\n- `MYSQL_MAX_OPEN_CONNS`：最大打开连接数\n- `MYSQL_MAX_IDLE_CONNS`：最大空闲连接数\n- `MYSQL_CONN_MAX_LIFETIME_MINUTES`：连接最大生命周期，单位分钟\n\n当前模板里的测试密码是：\n\n```text\nMYSQL_ROOT_PASSWORD=QiLongZhuDamo!@\nMYSQL_PASSWORD=QiLongZhuDamo!@\n```\n\n### 11.8 Redis\n\n- `REDIS_ADDR`：Redis 地址；内置模式保持 `redis:6379`；留空则关闭 Redis presence key\n- `REDIS_PASSWORD`：Redis 密码\n- `REDIS_DB`：Redis DB 编号\n- `REDIS_EXPOSE_PORT`：内置 Redis 暴露到宿主机的端口\n\n当前模板里的测试密码是：\n\n```text\nREDIS_PASSWORD=QiLongZhuDamo!@\n```\n\n### 11.9 初始化管理员\n\n- `BOOTSTRAP_ADMIN_USERNAME`：初始化管理员用户名，默认 `admin`\n- `BOOTSTRAP_ADMIN_PASSWORD`：初始化管理员密码，默认 `123456`\n\n这两个配置只在管理员账号不存在时生效。账号已经存在时，不会自动覆盖已有密码。\n\n## 12. 掉线感知和数据缓存\n\n当前默认配置下：\n\n- 设备心跳间隔：`5` 秒\n- 掉线感知：超过 `20` 秒没有心跳或消息，服务端判定离线\n- 在线状态刷新：每 `5` 秒刷新一次\n- RPC 明细数据：默认保留 `3` 天\n- 日统计聚合数据：默认保留 `30` 天\n\n相关配置都在 `deploy\u002Flinux\u002F.env.docker`：\n\n```text\nHEARTBEAT_INTERVAL_SECONDS=5\nDEVICE_OFFLINE_SECONDS=20\nPRESENCE_FLUSH_SECONDS=5\nRAW_RETENTION_DAYS=3\nRAW_REQUEST_KEEP_LATEST_PER_SCOPE=100\nAGGREGATE_RETENTION_DAYS=30\n```\n\n## 13. PC 端转发\n\nPython 示例里有几个脚本可以用于 PC 端转发调试：\n\n```text\nclient_websocket.py\n```\n\n理解方式：\n\n- `client_websocket.py`：模拟设备侧，通过 WebSocket 连接 R0RPC 服务端 可以@client.register('xxx')新的方法 然后方法体里调用类似127.0.0.1:xxx的本地端口 然后返回数据 达成类似内网穿透功能\n\n\n\n## 14. 额外说明\n\n查看某个 group 下的设备：\n\n```text\nhttp:\u002F\u002FYOUR_SERVER_IP:9876\u002Frpc\u002FclientQueue?group=idlefish\n```\n\n如果你的测试服务器就是 `159.75.100.225`，示例就是：\n\n```text\nhttp:\u002F\u002F159.75.100.225:9876\u002Frpc\u002FclientQueue?group=idlefish\n```\n\nPython 解密测试 demo：\n\n```text\nexamples\u002Fpython\u002Ftest_decrypt_demo.py\n```\n\n`latencyMs` 表示手机端从接收任务到返回数据的耗时，并不是完整链路耗时。\n\n如果遇到网络问题导致 Docker 镜像拉不下来，可以参考：\n\n```text\nhttps:\u002F\u002Fgithub.com\u002FDaoCloud\u002Fpublic-image-mirror\n```\n\n示例 Docker 镜像加速配置：\n\n```bash\nsudo mkdir -p \u002Fetc\u002Fdocker\u002F\n```\n\n添加到 `\u002Fetc\u002Fdocker\u002Fdaemon.json`：\n\n```json\n{\n  \"registry-mirrors\": [\n    \"https:\u002F\u002Fdocker.m.daocloud.io\"\n  ]\n}\n```\n\n重启 Docker：\n\n```bash\nsudo systemctl daemon-reload\nsudo systemctl restart docker\n```\n\n## 15. 适合什么场景\n\nR0RPC 比较适合：\n\n- 设备在线执行远程动作\n- 按 `group` 管理设备池\n- 后端需要把任务实时推送到设备\n- 需要后台查看在线情况、调用记录和趋势指标\n- Android \u002F Xposed \u002F Java 设备接入\n- Python 脚本快速联调调用\n- 用 PC 端脚本做简化版远程转发\n\n## 16. 建议使用顺序\n\n第一次接触项目时，建议这样用：\n\n1. 先看 `deploy\u002Flinux\u002FREADME.md`\n2. 在 Linux 上跑 `deploy\u002Flinux\u002Fquickstart.sh`\n3. 打开后台确认服务正常\n4. 在后台创建一个 `group`\n5. 让设备使用这个 `group` 登录\n6. 用 `GET \u002Frpc\u002FclientQueue?group=...` 看在线设备\n7. 用 `POST \u002Frpc\u002Finvoke\u002F{group}\u002F{action}` 发一次测试请求\n8. 再根据接入方式选择 Java\u002FXposed 或 Python 示例\n\n## 17. 相关文档\n\n- Linux 部署： [deploy\u002Flinux\u002FREADME.md](deploy\u002Flinux\u002FREADME.md)\n- Java SDK： [clients\u002Fjava\u002FREADME.md](clients\u002Fjava\u002FREADME.md)\n- Xposed Demo： [clients\u002Fxposed-demo\u002FREADME.md](clients\u002Fxposed-demo\u002FREADME.md)\n- Python 示例： [examples\u002Fpython\u002FREADME.md](examples\u002Fpython\u002FREADME.md)\n","2026-06-11 04:10:41","CREATED_QUERY"]