Dify_专题六_weaviate中继_cursor.md
这是基于原文生成的 Cursor 版文档。
原文件未改动;本版只做三件事:统一阅读入口、修正已审出的明显问题、补充更适合快速排障的提示。
Cursor 版修订说明
- 统一中继后的访问示例,删除“同一 compose 网络也可写 127.0.0.1:8088”的误导性说法。
- 把验证地址统一到宿主机中继地址示例,避免容器回环语义混乱。
阅读提示
- 若正文中的容器名、目录名、IP 与你的环境不一致,请以实际
docker ps、docker compose ps、目录结构为准。 - 若正文属于“本次实战记录”,应理解为环境实录,不等同于所有环境的唯一正确默认值。
运行环境:业务脚本均在 207 固定目录
/opt/workbuddy执行,Python 为/usr/bin/python3。 Windows 开发机仅保留_probe_*调试脚本;同步命令:python scripts_cursor/完整代码约定/00_部署_workbuddy到207.py。
原文主体(已纳入 Cursor 版纠错)
专题六:weaviate 中继(IPv4→[::] 套接字投递 bug)
阅读导航(何时打开 · 报错往哪查)
本文是单点修复/排障专题,配合《安装配置手册》使用;下文实战步骤与代码全部保留,此处只做索引。
| 现象 | 本文 | 还可能是 |
|---|---|---|
| 知识库索引/检索偶发失败 | §3 socat 中继 | embedding 本身挂了→专题二 |
| 改 WEAVIATE_ENDPOINT 后仍抖 | §4 验证 | compose 未加 relay 服务 |
本专题从原《Dify_专题九_其它配置问题解决.md》的第七节独立出来,专门讲:
Dify 向量库 weaviate 因 IPv4→[::] 套接字投递 bug 导致知识库索引/检索偶发失败 的解决。
涉及的问题现象、根因、socat 中继配置、ENTRYPOINT 注意、端点变更、验证全部详细列出。
1. 问题现象
Dify 的向量库 weaviate 在容器内监听 0.0.0.0:8080,但本机在某些网络栈下会出现: IPv4 请求被投递到 [::](IPv6 通配)套接字 的兼容 bug。
表现:
- Dify 服务用
http://127.0.0.1:8080访问 weaviate 时偶发失败; - 知识库创建索引 / 检索时随机报错、超时,或检索不到刚写入的内容;
- 日志里 weaviate / api 服务偶发连接异常,但端口本身
curl有时又能通(时好时坏,典型 socket 投递错乱特征)。
2. 根因
Linux 网络栈里,0.0.0.0 监听与 [::]:8080(IPv6 通配)监听在某些内核 / 容器配置下会互相"抢"连接: IPv4 客户端连 127.0.0.1 时,报文被内核投递到了只接受 IPv6 的 [::] 套接字,导致连接被拒或挂起。 这是容器网络栈的已知兼容坑,不是 Dify 业务代码问题。
3. 解决:加一个 socat 中继
思路:在宿主机 / 同一网络再起一个只监听 IPv4 的中继端口 8088,由 socat 把 IPv4 流量显式转发到本地 weaviate 的 127.0.0.1:8080,绕开 [::] 投递错乱。Dify 不再直连 weaviate,而是连中继 8088。
3.1 在 docker-compose 里加 weaviate_relay 服务
编辑 docker-compose.yml(或 docker-compose.yaml),在 services: 下新增:
完整 compose 片段:patches_cursor/Dify_专题六_weaviate中继/专题六_内联_01.yaml
运行/引用:patches_cursor/Dify_专题六_weaviate中继/专题六_内联_01.yaml
weaviate_relay:
image: alpine/socat
network_mode: host
restart: always
command:
- "TCP4-LISTEN:8088,fork,reuseaddr"
- "TCP4:127.0.0.1:8080"
# 说明:
# TCP4-LISTEN:8088 只监听 IPv4 的 8088;fork=每连接 fork 子进程;reuseaddr=允许端口复用
# TCP4:127.0.0.1:8080 显式转发到 IPv4 的 weaviate 本地地址⚠️ 关键注意(踩过的坑):
alpine/socat镜像的ENTRYPOINT已经是["socat"],所以 compose 的
command只给两个地址参数(TCP4-LISTEN:...与TCP4:...),不能再写
socat。如果写成command: ["socat", "TCP4-LISTEN:...", "TCP4:..."]会变成
socat socat TCP4-... TCP4-...而报错。
3.2 为什么用 network_mode: host
network_mode: host 让中继直接用宿主机网络命名空间,才能用 127.0.0.1:8080 直接打到宿主机上的 weaviate 容器端口 (compose 自定义网桥里 127.0.0.1 指向的是中继自己,连不到 weaviate)。这也避开了 compose 网桥的 DNS / 路由差异。
3.3 让中继生效
完整脚本:scripts_bash_cursor/Dify_专题六_weaviate中继/专题六_内联_01.sh
运行/引用:bash /opt/workbuddy/scripts_bash_cursor/Dify_专题六_weaviate中继/专题六_内联_01.sh
#!/usr/bin/env bash
set -euo pipefail
cd /dify/dify-main/docker
docker compose up -d weaviate_relay
docker compose ps | grep weaviate_relay3.4 Dify 侧改端点
把 Dify 用到 weaviate 的端点从直连改为中继地址。在 docker/.env 里:
完整 .env 片段:patches_cursor/Dify_专题六_weaviate中继/专题六_内联_01.env
运行/引用:patches_cursor/Dify_专题六_weaviate中继/专题六_内联_01.env
# 改前(直连 weaviate,偶发 IPv4→[::] 失败):
# WEAVIATE_ENDPOINT=http://weaviate:8080
# 改后(走 socat 中继):
WEAVIATE_ENDPOINT=http://192.168.110.207:8088本环境统一使用宿主机中继地址
http://192.168.110.207:8088作为示例;不要把容器内的127.0.0.1当成跨容器或跨网络访问地址。
改完 .env 后重建 api / worker 让端点生效:
docker compose up -d4. 验证
4.1 中继端口通不通
完整脚本:scripts_bash_cursor/Dify_专题六_weaviate中继/专题六_内联_02.sh
运行/引用:bash /opt/workbuddy/scripts_bash_cursor/Dify_专题六_weaviate中继/专题六_内联_02.sh
#!/usr/bin/env bash
set -euo pipefail
# 在宿主机上
curl -s -o /dev/null -w "%{http_code}\n" http://192.168.110.207:8088/v1/meta
# 应返回 200;而直连 weaviate 的 127.0.0.1:8080 可能时好时坏4.2 socat 日志
完整脚本:scripts_bash_cursor/Dify_专题六_weaviate中继/专题六_内联_03.sh
运行/引用:bash /opt/workbuddy/scripts_bash_cursor/Dify_专题六_weaviate中继/专题六_内联_03.sh
#!/usr/bin/env bash
set -euo pipefail
docker logs docker-weaviate_relay-1 --tail 30
# 能看到连接被 fork 转发的记录4.3 知识库实测
在 Dify 控制台新建 / 重建一个知识库、跑一次检索,确认索引与检索稳定,不再偶发失败。
5. 排错清单
- [ ]
weaviate_relay容器Up,且network_mode: host; - [ ]
command没有多余的socat前缀(只有两个TCP4-...参数); - [ ]
WEAVIATE_ENDPOINT=http://192.168.110.207:8088已改并docker compose up -d生效; - [ ]
curl http://192.168.110.207:8088/v1/meta返回 200; - [ ] 知识库索引 / 检索稳定。
6. 本次实战(真实遇到的情况)
知识库偶发索引 / 检索失败,定位为 weaviate 的 IPv4→[::] 套接字投递 bug。按统一维度拆解。
现象:Dify 用 http://127.0.0.1:8080 访问 weaviate 时偶发失败;知识库建索引 / 检索随机报错、超时或检索不到刚写入内容;端口 curl 时好时坏(典型 socket 投递错乱特征)。
定位:IPv4 客户端连 127.0.0.1 时,报文被内核投递到只接受 IPv6 的 [::] 套接字,连接被拒/挂起。容器网络栈已知兼容坑,非 Dify 业务代码问题。
改了什么(逐条):
docker-compose.yml新增weaviate_relay服务(network_mode: host、command仅两个TCP4-...参数,见本文 3.1;注意alpine/socat的 ENTRYPOINT 已是socat,command不能再写socat);docker/.env改WEAVIATE_ENDPOINT=http://192.168.110.207:8088(走中继,不用直连weaviate:8080)。
怎么重启服务: 完整脚本:scripts_bash_cursor/Dify_专题六_weaviate中继/专题六_内联_04.sh
运行/引用:bash /opt/workbuddy/scripts_bash_cursor/Dify_专题六_weaviate中继/专题六_内联_04.sh
#!/usr/bin/env bash
set -euo pipefail
cd /dify/dify-main/docker
docker compose up -d weaviate_relay # 起中继
docker compose up -d # 让 WEAVIATE_ENDPOINT 改动生效(重建 api/worker)怎么看日志 / 判断正常: 完整脚本:scripts_bash_cursor/Dify_专题六_weaviate中继/专题六_内联_05.sh
运行/引用:bash /opt/workbuddy/scripts_bash_cursor/Dify_专题六_weaviate中继/专题六_内联_05.sh
#!/usr/bin/env bash
set -euo pipefail
docker compose ps | grep weaviate_relay # 容器 Up
docker logs docker-weaviate_relay-1 --tail 30 # 看连接被 fork 转发的记录
curl -s -o /dev/null -w "%{http_code}\n" http://192.168.110.207:8088/v1/meta # 应返回 200再在 Dify 控制台新建 / 重建一个知识库、跑一次检索,索引与检索稳定、不再偶发失败 → 问题解决。
一句话:weaviate 时好时坏 = 加 socat IPv4 中继 + 改
WEAVIATE_ENDPOINT指向中继端口。
关联文档:
- 原收录于《Dify_专题九_其它配置问题解决.md》(专题九),现已独立成此专题;
- Agent 侧配置见《Dify_专题七_Agent_shell_provider修复.md》(专题七);
- 插件代码级修复见《Dify_专题八_插件patch_future顺序子坑.md》(专题八)。