====== 10 排错清单与练习 ======
===== 排错总原则 =====
按链路从外到内排查:
客户端
-> 网络 / DNS / HTTPS
-> IIS 或 rhino.compute
-> compute.geometry 子进程
-> Rhino.Inside / Rhino 授权
-> Grasshopper / 插件 / 自定义端点
-> 输入数据和业务逻辑
不要一开始就修改 Grasshopper 定义或服务器参数。先确认错误发生在哪一层。
===== 快速健康检查 =====
在服务器本机或客户端访问:
http://server/version
http://server/healthcheck
http://server/activechildren
http://server/sdk
判断:
* ''/healthcheck'' 不通:服务、端口、IIS、网络问题。
* ''/version'' 通但业务 POST 失败:认证、端点、请求格式、业务输入问题。
* ''/sdk'' 不显示自定义端点:插件未加载或注册失败。
* ''/activechildren'' 异常:子进程启动、授权、内存或崩溃问题。
===== 401 Unauthorized =====
含义:请求未通过 API Key 认证。
检查:
* 服务端是否设置了 ''RHINO_COMPUTE_KEY''?
* 客户端 header 名称是否为 ''RhinoComputeKey''?
* header 值是否与服务端完全一致?
* Hops Preferences 中 API Key 是否更新后重启了 Rhino/Grasshopper?
* 是否经过了代理或网关,header 被过滤或改名?
修复:
RhinoComputeKey: your-secret-api-key
===== 500 Internal Server Error =====
含义:服务器处理请求时异常。
常见原因:
* Rhino 授权失败。
* Grasshopper 定义内部异常。
* 第三方插件缺失或加载失败。
* 输入几何非法或 JSON 格式不匹配。
* 自定义端点抛异常。
* Linux/WIP 环境缺少某些功能。
处理:
* 开启 ''RHINO_COMPUTE_DEBUG=true''。
* 查看 Compute 日志中的异常堆栈。
* 用最小输入重放请求。
* 在普通 Rhino/Grasshopper 中打开同一定义测试。
* 如果是自定义端点,在插件代码中增加结构化日志和参数校验。
===== HRESULT E_FAIL / 授权失败 =====
常见含义:RhinoCompute 启动 Rhino 时找不到有效授权。
本地开发:
* 启动 Rhino,完成登录或授权。
* 确认 Rhino 本身能打开。
服务器:
* 配置 ''RHINO_TOKEN''。
* 确认 token 来自已启用 Core-Hour Billing 的团队。
* 重启 Compute 或 IIS 应用池。
* 不要把普通单机 license 当成 Windows Server 授权方案。
===== 超时 =====
可能有两类:
* 客户端超时:Hops 或业务客户端等待时间太短。
* 服务端超时:''RHINO_COMPUTE_TIMEOUT'' 限制。
检查:
* Hops Preferences 中 timeout。
* 服务端 ''RHINO_COMPUTE_TIMEOUT''。
* 业务网关、反向代理、负载均衡的 timeout。
* Grasshopper 定义第一次冷启动是否特别慢。
处理:
* 先优化定义和输入规模。
* 再适当提高客户端和服务端超时。
* 对长任务改为异步任务队列,不要让用户请求一直阻塞。
===== Request body too large =====
含义:请求体超过 Compute 限制。默认上限常见约 50 MB。
处理:
[System.Environment]::SetEnvironmentVariable('RHINO_COMPUTE_MAX_REQUEST_SIZE', '104857600', 'Machine')
然后重启服务。
但提高限制不是首选方案。更好的方式:
* 压缩输入。
* 上传大文件到对象存储,只传文件引用。
* 减少 DataTree 中重复几何。
* 把任务拆分为多个小请求。
===== Hops 定义不更新输入输出 =====
检查:
* Context Get 组件名称是否正确。
* Context Print/Bake 输出名称是否正确。
* Hops 是否缓存了旧定义。
* 文件路径或 URL 是否指向旧版本。
* Hops 组件是否需要重新指定 Path 或刷新。
===== 插件相关问题 =====
检查顺序:
- 普通 Rhino 是否能加载插件?
- 普通 Rhino 中插件命令是否能运行?
- Compute 启动日志中是否看到插件加载?
- ''/sdk'' 是否列出自定义端点?
- 插件是否依赖 UI、窗口、当前文档、用户选择?
- 插件授权是否在服务器账户下生效?
===== 最小复现模板 =====
排错时记录以下信息:
^ 项目 ^ 内容 ^
| 时间 | 发生错误的精确时间。 |
| Compute URL | 例如 ''http://server:80/''。 |
| 端点 | 例如 ''/grasshopper'' 或自定义路径。 |
| HTTP 状态码 | 401、500、timeout 等。 |
| 请求体大小 | byte 或 MB。 |
| Rhino/Compute 版本 | 从 ''/version'' 或日志获取。 |
| 子进程数量 | ''/activechildren'' 或启动参数。 |
| API Key 状态 | 是否配置,不记录真实 key。 |
| GH 定义版本 | 文件名、版本号、最后修改时间。 |
| 插件清单 | 相关第三方插件版本。 |
| 日志片段 | 异常堆栈或关键错误行。 |
===== 综合练习 =====
练习 1:本地启动 Compute,访问 ''/version''、''/healthcheck''、''/sdk''。
练习 2:配置 ''RHINO_COMPUTE_KEY'',用错误 key 发起 POST,确认返回 401。
练习 3:创建一个 Hops 函数,输入两个数字,输出相加结果。分别在本地和远程 Compute 上求解。
练习 4:把一个 Grasshopper 定义改造成无交互版本,移除所有依赖当前 Rhino 文档选择的步骤。
练习 5:写一个自定义 Compute 端点,输入 Curve 和系数,输出调整后的面积,并确认 ''/sdk'' 中可见。
练习 6:构造一个超时或大请求体场景,观察日志,再调整 ''RHINO_COMPUTE_TIMEOUT'' 或 ''RHINO_COMPUTE_MAX_REQUEST_SIZE''。
===== 结业检查 =====
* 能从日志判断 401、500、授权失败、超时、大请求体的根因。
* 能把 Hops 问题拆成客户端配置、Compute 服务、GH 定义、插件依赖四层排查。
* 能说明生产环境为什么需要 API Key、Core-Hour Billing token、idlespan 和日志。
* 能为一个业务几何任务选择 Hops、自定义端点或客户端库调用。
===== 参考资料 =====
* [[https://developer.rhino3d.com/guides/compute/compute-faq/|Compute FAQ]]
* [[https://developer.rhino3d.com/en/guides/compute/development/|Running and Debugging Compute Locally]]
* [[https://developer.rhino3d.com/guides/compute/hops-component/|The Hops Component]]