跳转至主要内容
版本: v0.1

网络技巧

本指南介绍如何在不修改代码库文件的情况下,在受限或缓慢的网络环境中构建和运行。您将通过使用小型本地覆盖文件和 compose 覆盖配置,从而保持代码库的整洁。

解决的问题

  • Hugging Face 模型下载被拦截或缓慢
  • Docker 构建期间 Go 模块获取被拦截
  • mock-vLLM 测试镜像的 PyPI 访问问题

摘要:选择您的方案

  • 最快且最可靠:使用 ./models 中的本地模型,完全跳过 HF 网络。
  • 否则:通过 compose 覆盖配置挂载 HF 缓存并设置镜像站环境变量。
  • 构建时:使用覆盖 Dockerfile 设置 Go 镜像(提供示例)。
  • 针对 mock-vllm:使用覆盖 Dockerfile 设置 pip 镜像(提供示例)。

您可以根据具体情况混合使用这些方法。

1. Hugging Face 模型

除非您提供本地模型,否则路由器会在首次运行时下载嵌入模型。如果可能,首选方案 A。

方案 A — 使用本地模型(无需外部网络)

  1. 通过任何可行的方法(VPN/离线)将所需的模型下载到代码库的 ./models 文件夹中。示例布局:

    • models/all-MiniLM-L12-v2/
    • models/category_classifier_modernbert-base_model
  2. config/config.yaml 中指向本地路径。示例:

    bert_model:
    # point to a local folder under /app/models (already mounted by compose)
    model_id: /app/models/all-MiniLM-L12-v2
  3. 不需要额外的环境变量。deploy/docker-compose/docker-compose.yml 已经挂载了 ./models:/app/models:ro

方案 B — 使用 HF 缓存 + 镜像站

创建一个 compose 覆盖文件以持久化缓存并使用区域镜像站(以下示例使用中国镜像站)。在代码库根目录保存为 docker-compose.override.yml(当您同时指定两者时,Compose 会自动将其与 deploy/docker-compose/docker-compose.yml 合并):

services:
semantic-router:
volumes:
- ~/.cache/huggingface:/root/.cache/huggingface
environment:
- HUGGINGFACE_HUB_CACHE=/root/.cache/huggingface
- HF_HUB_ENABLE_HF_TRANSFER=1
- HF_ENDPOINT=https://hf-mirror.com # example mirror endpoint (China)

可选:在宿主机上预热缓存(仅当您安装了 huggingface_hub 时):

python -m pip install -U huggingface_hub
python - <<'PY'
from huggingface_hub import snapshot_download
snapshot_download(repo_id="sentence-transformers/all-MiniLM-L6-v2", local_dir="~/.cache/huggingface/hub/models--sentence-transformers--all-MiniLM-L6-v2")
PY

2. 使用 Go 镜像构建(Dockerfile 覆盖)

构建 tools/docker/Dockerfile.extproc 时,Go 阶段可能会卡在 proxy.golang.org。创建一个启用镜像站的覆盖 Dockerfile,而无需改动原始文件。

  1. 创建 tools/docker/Dockerfile.extproc.cn,内容如下:
# syntax=docker/dockerfile:1

FROM rust:1.90 AS rust-builder
RUN apt-get update && apt-get install -y make build-essential pkg-config && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY tools/make/ tools/make/
COPY Makefile ./
COPY candle-binding/Cargo.toml candle-binding/
COPY candle-binding/src/ candle-binding/src/
RUN make rust

FROM golang:1.24 AS go-builder
WORKDIR /app

# Go module mirrors (example: goproxy.cn)
ENV GOPROXY=https://goproxy.cn,direct
ENV GOSUMDB=sum.golang.google.cn

RUN mkdir -p src/semantic-router
COPY src/semantic-router/go.mod src/semantic-router/go.sum src/semantic-router/
COPY candle-binding/go.mod candle-binding/semantic-router.go candle-binding/

# Pre-download modules to fail fast if mirrors are unreachable
RUN cd src/semantic-router && go mod download && \
cd /app/candle-binding && go mod download

COPY src/semantic-router/ src/semantic-router/
COPY --from=rust-builder /app/candle-binding/target/release/libcandle_semantic_router.so /app/candle-binding/target/release/

ENV CGO_ENABLED=1
ENV LD_LIBRARY_PATH=/app/candle-binding/target/release
RUN mkdir -p bin && cd src/semantic-router && go build -o ../../bin/router cmd/main.go

FROM quay.io/centos/centos:stream10
WORKDIR /app
COPY --from=go-builder /app/bin/router /app/extproc-server
COPY --from=go-builder /app/candle-binding/target/release/libcandle_semantic_router.so /app/lib/
COPY config/config.yaml /app/config/
ENV LD_LIBRARY_PATH=/app/lib
EXPOSE 50051
COPY scripts/entrypoint.sh /app/entrypoint.sh
RUN chmod +x /app/entrypoint.sh
ENTRYPOINT ["/app/entrypoint.sh"]
  1. 通过扩展 docker-compose.override.yml 将 compose 指向覆盖 Dockerfile:
services:
semantic-router:
build:
dockerfile: tools/docker/Dockerfile.extproc.cn

3. Mock vLLM (通过 Dockerfile 覆盖设置 PyPI 镜像站)

对于可选的测试配置(profile),创建一个覆盖 Dockerfile 以配置 pip 镜像站。

  1. 创建 tools/mock-vllm/Dockerfile.cn
FROM python:3.11-slim
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/*

# Pip mirror (example: TUNA mirror in China)
RUN python -m pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple && \
python -m pip config set global.trusted-host pypi.tuna.tsinghua.edu.cn

COPY requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

COPY app.py /app/app.py
EXPOSE 8000
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
  1. 扩展 docker-compose.override.yml,以便为 mock-vllm 使用覆盖 Dockerfile:
services:
mock-vllm:
build:
dockerfile: Dockerfile.cn

4. 构建并运行

完成覆盖配置后,正常进行构建和运行(Compose 会自动合并):

# Build all images with overrides (explicitly reference the relocated compose file)
docker compose -f deploy/docker-compose/docker-compose.yml -f docker-compose.override.yml build

# Run router + envoy
docker compose -f deploy/docker-compose/docker-compose.yml -f docker-compose.override.yml up -d

# If you need the testing profile (mock-vllm)
docker compose -f deploy/docker-compose/docker-compose.yml -f docker-compose.override.yml --profile testing up -d

5. 出口受限的 Kubernetes 集群

Kubernetes 节点上的容器运行时不会自动重用宿主机的 Docker 守护进程设置。当注册表访问缓慢或被拦截时,Pod 可能会处于 ImagePullBackOff 状态。请选择或组合使用以下缓解措施:

5.1 配置 containerd 或 CRI 镜像站

  • 对于基于 containerd 的集群(如 Kind、k3s、kubeadm),编辑 /etc/containerd/config.toml 或使用 Kind 的 containerdConfigPatches,为 docker.ioghcr.ioquay.io 等注册表添加区域镜像站端点。
  • 更改后重启 containerd 和 kubelet,使新镜像站生效。
  • 除非每个节点都能访问该代理地址,否则避免将镜像站指向回环代理(loopback proxies)。

5.2 预加载或侧载镜像

  • 在本地构建所需的镜像,然后将其推送到集群运行时。对于 Kind,运行 kind load docker-image --name <cluster> <image:tag>;对于其他集群,在每个节点上使用 crictl pullctr -n k8s.io images import
  • 当您确定镜像已存在于节点上时,修改 Deployment 将 imagePullPolicy 设置为 IfNotPresent

5.3 发布到可访问的注册表

  • 为镜像打标签并推送到可从集群访问的注册表(云提供商注册表、私有托管的 Harbor 等)。
  • 使用新的镜像名称更新您的 kustomization.yaml 或 Helm values,如果注册表需要身份验证,请配置 imagePullSecrets

5.4 运行本地拉取穿透缓存

  • 在同一网络内启动注册表代理(registry:2 或供应商特定的缓存),在 containerd 中将其配置为镜像站,并定期预热您需要的镜像。

5.5 调整后验证

  • 使用 kubectl describe pod <name>kubectl get events 确认拉取错误已消失。
  • 检查诸如 semantic-router-metrics 之类的服务是否已暴露端点,并能通过端口转发进行响应(kubectl port-forward svc/<service> <local-port>:<service-port>)。

6. 故障排除

  • Go 模块仍然超时

    • 检查 go-builder 阶段的日志中是否存在 GOPROXYGOSUMDB
    • 尝试清理构建:docker compose build --no-cache
  • HF 模型下载仍然缓慢

    • 首选方案 A(本地模型)。
    • 确保已挂载缓存卷,并且设置了 HF_ENDPOINT/HF_HUB_ENABLE_HF_TRANSFER
  • mock-vllm 的 PyPI 速度慢

    • 确认该服务正在使用指定的 CN Dockerfile。