📎 配套脚本附件正文未内嵌 · 共 5 个 · 点开可在线查看
📂 查看全部 761 个脚本附件 →
⚠️ 脚本内含明文凭据(与本页正文一致),请勿在公网环境直接运行。
Dify · 专题六

weaviate 中继(IPv4→[::])

socat IPv4 中继 + WEAVIATE_ENDPOINT。步骤未改,代码块已换成完整脚本。

Dify_专题六_weaviate中继_cursor.md

这是基于原文生成的 Cursor 版文档。

原文件未改动;本版只做三件事:统一阅读入口、修正已审出的明显问题、补充更适合快速排障的提示。

Cursor 版修订说明

阅读提示

运行环境:业务脚本均在 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。

表现:


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

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

bash
#!/usr/bin/env bash
set -euo pipefail

cd /dify/dify-main/docker
docker compose up -d weaviate_relay
docker compose ps | grep weaviate_relay

3.4 Dify 侧改端点

把 Dify 用到 weaviate 的端点从直连改为中继地址。在 docker/.env 里:

完整 .env 片段:patches_cursor/Dify_专题六_weaviate中继/专题六_内联_01.env

运行/引用:patches_cursor/Dify_专题六_weaviate中继/专题六_内联_01.env

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 让端点生效:

bash
docker compose up -d

4. 验证

4.1 中继端口通不通

完整脚本:scripts_bash_cursor/Dify_专题六_weaviate中继/专题六_内联_02.sh

运行/引用:bash /opt/workbuddy/scripts_bash_cursor/Dify_专题六_weaviate中继/专题六_内联_02.sh

bash
#!/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

bash
#!/usr/bin/env bash
set -euo pipefail

docker logs docker-weaviate_relay-1 --tail 30
# 能看到连接被 fork 转发的记录

4.3 知识库实测

在 Dify 控制台新建 / 重建一个知识库、跑一次检索,确认索引与检索稳定,不再偶发失败。


5. 排错清单


6. 本次实战(真实遇到的情况)

知识库偶发索引 / 检索失败,定位为 weaviate 的 IPv4→[::] 套接字投递 bug。按统一维度拆解。

现象:Dify 用 http://127.0.0.1:8080 访问 weaviate 时偶发失败;知识库建索引 / 检索随机报错、超时或检索不到刚写入内容;端口 curl 时好时坏(典型 socket 投递错乱特征)。

定位:IPv4 客户端连 127.0.0.1 时,报文被内核投递到只接受 IPv6 的 [::] 套接字,连接被拒/挂起。容器网络栈已知兼容坑,非 Dify 业务代码问题。

改了什么(逐条):

  1. docker-compose.yml 新增 weaviate_relay 服务(network_mode: host、command 仅两个 TCP4-... 参数,见本文 3.1;注意 alpine/socat 的 ENTRYPOINT 已是 socat,command 不能再写 socat);
  2. 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

bash
#!/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

bash
#!/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》(专题八)。