目录

Sozu 中文使用教程

Sozu 是一个快速、可靠且可编程的 HTTP 和 TCP 反向代理,由 Rust 编写。它支持高级路由、负载均衡、TLS 终止和动态配置。

项目地址:https://github.com/sozu-proxy/sozu.git

1. Rust 环境设置

在安装 Sozu 之前,请确保您的系统上安装了最新稳定版的 Rust。我们推荐使用 rustup 进行安装:

  1. 安装 rustup: 访问 rustup 官方网站 或在终端运行以下命令:
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  2. 配置环境: 按照安装程序的指示操作,通常需要执行 source $HOME/.cargo/env 来将 cargo (Rust 的包管理器) 添加到您的 PATH 中。
  3. 验证安装: 运行 rustc --versioncargo --version 来验证 Rust 是否成功安装。

2. Sozu 安装

您可以选择通过 cargo install 从 crates.io 安装 Sozu,或者从源代码构建。

2.1 通过 cargo install 安装

Sozu 发布在 crates.io 上。安装非常简单:

cargo install sozu

安装完成后,sozu 可执行文件将在您的 ~/.cargo/bin 目录中可用。

2.2 从源代码构建

如果您想从源代码构建 Sozu (例如,进行开发或使用最新版本),请遵循以下步骤:

  1. 克隆仓库: 如果您尚未克隆 Sozu 仓库,请先克隆它:
    git clone https://github.com/sozu-proxy/sozu.git
    cd sozu
  2. 构建: 导航到 bin 目录并使用 cargo build 命令构建。为了获得生产版本,请务必使用 --release 标志以启用优化:
    cd bin
    cargo build --release --locked
    • --release 参数会告知 Cargo 启用编译优化,生成性能更好的二进制文件。仅在构建生产版本时使用。
    • --locked 标志会强制 Cargo 遵守 Cargo.lock 中指定的依赖版本,从而防止依赖中断。

构建完成后,可执行文件将在 target/release/sozu 路径下。

3. 如何使用 Sozu

Sozu 既可以作为独立进程运行,也可以集成到 Docker 容器或 Systemd 服务中。

3.1 运行 Sozu

  • 通过 cargo install 方式安装: 如果您通过 cargo install 安装了 Sozu,那么 sozu 命令应该已经在您的 $PATH 中。
    sozu start -c <您的/config.toml/路径>
  • 从源代码构建: 如果您从源代码构建,Sozu 可执行文件位于 target/release 目录中。
    ./target/release/sozu start -c <您的/config.toml/路径>

您可以在 config.toml 文件中编辑反向代理的配置,声明新的集群、前端和后端。

提示: 您可以使用 sozu 二进制文件作为 CLI 与反向代理进行交互。更多信息请参阅命令行文档 (在 configure_cli.md 中)。

3.2 使用 Docker 运行

Sozu 仓库提供了一个基于 alpine:edge 的多阶段 Dockerfile 镜像。

  1. 构建 Docker 镜像:
    docker build -t sozu .
    您也可以构建特定 Alpine 版本的镜像:
    docker build --build-arg ALPINE_VERSION=3.14 -t sozu:main-alpine-3.14 .
  2. 运行 Docker 容器:
    docker run \
      --ulimit nofile=262144:262144 \
      --name sozu-proxy \
      -v /run/sozu:/run/sozu \
      -v /path/to/your/config/file:/etc/sozu \
      -v /my/state/:/var/lib/sozu \
      -p 8080:80 \
      -p 8443:443 \
      sozu
    • -v /path/to/your/config/file:/etc/sozu: 将您的自定义 config.toml 文件挂载到容器中。
    • -v /my/state/:/var/lib/sozu: 如果您有初始配置状态 JSON 文件,请将其挂载到容器中。

3.3 Systemd 集成

Sozu 仓库提供了 Systemd 单元文件,可以轻松地将其作为服务运行。

  1. 复制单元文件: 将 sozu/os-build/systemd/sozu.service 复制到 /etc/systemd/system/ 目录:
    sudo cp sozu/os-build/systemd/sozu.service /etc/systemd/system/
  2. 重新加载 Systemd:

sudo systemctl daemon-reload 3. **启动服务**:bash sudo systemctl start sozu.service 4. **开机自启**:bash sudo systemctl enable sozu.service ```

4. Sozu 配置

Sozu 的核心配置通过 config.toml 文件进行。它包含三个主要部分:global 参数、协议定义 (如 https, http, tcp) 和 clusters 部分。

4.1 配置文件 (config.toml) 结构概述

Sozu 配置文件的示例如下:

# 全局参数
command_socket = "./command_folder/sock"
saved_state = "./state.json"
log_level = "info"
log_target = "stdout"
worker_count = 2
handle_process_affinity = false
max_connections = 500
buffer_size = 16384
activate_listeners = true

# 监听器配置
[[listeners]]
protocol = "http"
address = "0.0.0.0:8080"
# public_address = "1.2.3.4:80" # 用于日志和转发头
# expect_proxy = false # 期望 PROXY 协议头

# HTTPS 监听器示例
[[listeners]]
protocol = "https"
address = "0.0.0.0:8443"
certificate = "/path/to/certificate.pem"
key = "/path/to/key.pem"
certificate_chain = "/path/to/certificate_chain.pem"
# tls_versions = ["TLS_V12", "TLS_V13"]
# answer_404 = "/path/to/my-404-answer.http" # 自定义错误页面

# 集群配置
[clusters]
[clusters.MyWebsiteCluster]
protocol = "http" # https 代理也使用 http 协议
# load_balancing_policy="roundrobin" # 负载均衡策略: "roundrobin" (默认) 或 "random"
# https_redirect = true # 强制将 http 流量重定向到 https

frontends = [
  { address = "0.0.0.0:8080", hostname = "your_domain.com" },
  # 对于 HTTPS 前端,还需要指定证书和密钥
  { address = "0.0.0.0:8443", hostname = "your_domain.com", certificate = "/path/to/certificate.pem", key = "/path/to/key.pem", certificate_chain = "/path/to/certificate_chain.pem" }
]
backends  = [
  { address = "127.0.0.1:8000" }, # 后端服务器地址
  { address = "127.0.0.1:8001" }
]

# 指标配置
[metrics]
address = "127.0.0.1:8125"
# tagged_metrics = false
# prefix = "sozu"

4.2 全局参数

全局参数在 [global] 部分设置,影响主进程和工作进程:

参数描述可选值
saved_stateSozu 启动时尝试加载状态的路径
log_level日志级别debug, trace, error, warn, info
log_target日志输出目标stdout, tcpudp 地址
access_logs_target访问日志输出目标 (如果激活)stdout, tcpudp 地址
command_socketUnix 命令套接字路径
worker_count工作进程数量
handle_process_affinity将工作进程绑定到 CPU 核心true, false
max_connections最大并发连接数
buffer_size工作进程使用的请求缓冲区大小 (字节)
activate_listeners自动启动监听器true, false
front_timeout前端 socket 最大非活动时间
connect_timeout连接请求的最大非活动时间
request_timeout请求的最大非活动时间
zombie_check_interval检查僵尸会话的间隔
pid_file_path存储 PID 的文件路径

4.3 监听器 (Listeners)

[[listeners]] 部分定义了一组接受客户端连接的监听套接字。您可以定义任意数量的监听器。

  • 通用参数:

    [[listeners]]
    protocol = "http" # 或 "https", "tcp"
    address = "0.0.0.0:8080"
    # public_address = "1.2.3.4:80" # 可选,用于日志和转发头
    # expect_proxy = true # 可选,配置客户端套接字接收 PROXY 协议头
  • HTTP 和 HTTPS 监听器特定选项 (自定义错误页面): 您可以为 HTTP 和 HTTPS 监听器定义自定义响应,如 404 Not Found, 503 Service Unavailable 等。这些响应可以是纯文本文件,其中包含 HTML 和一些模板变量 (如 %REQUEST_ID%)。

    # 当 Sozu 不知晓所请求的域名或路径时发送 404 响应
    answer_404 = "/path/to/my-404-answer.http"
    # 当没有可用的后端服务器时发送 503 响应
    answer_503 = "/path/to/my-503-answer.http"
  • HTTPS 监听器特定选项:

    # 支持的 TLS 版本。可选值:"SSL_V2", "SSL_V3", "TLS_V12", "TLS_V13"。默认为 "TLS_V12" 和 "TLS_V13"。
    tls_versions = ["TLS_V12", "TLS_V13"]
    # 定义 sticky session cookie 的名称,如果集群激活了 sticky_session。默认为 "SOZUBALANCEID"。
    sticky_name = "SOZUBALANCEID"

    基于 Rustls 的 HTTPS 监听器特定选项:

    cipher_list = [
        # TLS 1.3 密码套件
        "TLS13_AES_256_GCM_SHA384",
        # ... 其他密码套件
    ]

4.4 集群 (Clusters)

[clusters] 部分声明您的集群列表:

[clusters]
[clusters.NameOfYourCluster]
protocol = "http" # 或 "tcp"。HTTPS 代理也使用 http 协议
# load_balancing_policy="roundrobin" # 负载均衡策略: "roundrobin" (默认) 或 "random"
# https_redirect = true # 强制将 http 流量重定向到 https
# sticky_session = true # 可选,启用 sticky session

frontends = [
  { address = "0.0.0.0:8080", hostname = "your_domain.com" },
  # 对于 HTTPS 前端,还需要指定证书和密钥
  { address = "0.0.0.0:8443", hostname = "your_domain.com", certificate = "/path/to/certificate.pem", key = "/path/to/key.pem", certificate_chain = "/path/to/certificate_chain.pem" }
]
backs  = [
  { address = "127.0.0.1:8000" }, # 后端服务器地址
  { address = "127.0.0.1:8001" }
]

4.5 指标 (Metrics)

Sozu 通过 UDP 套接字向其他网络组件报告其状态,并实现了 statsd 协议。

配置方式:

[metrics]
address = "127.0.0.1:8125" # statsd 服务的地址和端口
# tagged_metrics = false # 使用 InfluxDB 的 statsd 协议以添加标签
# prefix = "sozu" # 指标键前缀

4.6 PROXY 协议

PROXY 协议用于在代理链中传递客户端的真实 IP 地址和端口信息。Sozu 支持 PROXY 协议版本 2。

  • 配置 Sozu 期望 PROXY 协议头:

    [[listeners]]
    address = "0.0.0.0:80"
    expect_proxy = true

    这使得客户端连接在读取任何数据之前先接收 PROXY 协议头。

  • 配置 Sozu 向后端发送 PROXY 协议头:

    [[listeners]]
    address = "0.0.0.0:81"
    
    [clusters]
    [clusters.NameOfYourTcpCluster]
    send_proxy = true
    frontends = [
      { address = "0.0.0.0:81" }
    ]

    注意: 仅适用于 TCP 集群 (HTTP 和 HTTPS 代理将使用转发头)。

  • 配置 Sozu 转发 PROXY 协议头:

    [[listeners]]
    address = "0.0.0.0:80"
    expect_proxy = true
    
    [clusters]
    [clusters.NameOfYourCluster]
    send_proxy = true
    frontends = [
      { address = "0.0.0.0:80" }
    ]

    Sozu 将接收客户端连接的 PROXY 协议头,验证其有效性,然后将其转发给上游后端。这允许代理链在不丢失客户端连接信息的情况下工作。

    注意: 仅适用于 TCP 集群。

5. 动态后端管理(服务发现)

在 Docker 等动态环境中,后端服务的 IP 地址可能会频繁变化。尽管 config.toml 在 Sozu 启动时解析 IP 地址,但您可以使用 Sozu 提供的命令行工具(CLI)来动态地添加、更新或移除后端,而无需重启 Sozu。

这个过程需要一个外部机制(例如一个简单的脚本、服务发现工具或自定义程序)来:

  1. 监控您的后端服务(例如,通过 Docker API 监听容器的启动/停止事件,或者查询 Docker 的内置 DNS 服务)。
  2. 获取后端服务的当前 IP 地址和端口。
  3. 使用 sozu CLI 工具向运行中的 Sozu 实例发送命令。

以下是使用 sozu CLI 管理后端的示例:

5.1 启动 Sozu 以接受命令

确保您的 config.tomlcommand_socket 配置正确,以便 CLI 工具可以连接到运行中的 Sozu 实例。例如:

command_socket = "/var/lib/sozu/command.sock"

5.2 查找 Docker 容器的 IP 地址

假设您的 Docker 网络名为 my-network,后端服务名为 my-backend-app,您可以使用 docker inspect 命令来获取其 IP 地址。

# 获取单个运行中容器的 IP 地址
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-backend-app

# 假设您的后端服务暴露在 8080 端口
export BACKEND_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-backend-app)
export BACKEND_PORT=8080
export BACKEND_ADDRESS="${BACKEND_IP}:${BACKEND_PORT}"

docker-compose 环境中,如果服务在同一个 user-defined bridge network 下,服务名通常可以直接作为主机名解析。但在 sozu 启动时解析 IP 的情况下,您仍然需要先获取 IP。

5.3 动态添加后端

使用 sozu backend add 命令将新的后端添加到指定的集群。

# 假设您的 Sozu 配置文件路径是 /etc/sozu/config.toml
# 并且该配置文件中已经设置了 command_socket
# 假设您的集群 ID 是 'komo'
CONFIG_PATH="/etc/sozu/config.toml"
CLUSTER_ID="komo"
NEW_BACKEND_ID="backend-1" # 为新后端提供一个唯一的ID
NEW_BACKEND_ADDRESS="172.17.0.5:9120" # 替换为您的后端实际 IP:端口

sozu --config "${CONFIG_PATH}" backend add --id "${CLUSTER_ID}" --backend-id "${NEW_BACKEND_ID}" --address "${NEW_BACKEND_ADDRESS}"
  • --config: 指定 Sozu 配置文件的路径,其中应包含 command_socket 的路径。
  • backend add: 表示要执行添加后端的操作。
  • --id: 指定要添加后端的集群 ID。
  • --backend-id: 为此后端实例提供一个唯一的标识符。
  • --address: 指定后端服务器的 IP 地址和端口。

5.4 动态移除后端

使用 sozu backend remove 命令从指定的集群中移除后端。

# 假设您的 Sozu 配置文件路径是 /etc/sozu/config.toml
CONFIG_PATH="/etc/sozu/config.toml"
CLUSTER_ID="komo"
OLD_BACKEND_ID="backend-1" # 要移除的后端的ID
OLD_BACKEND_ADDRESS="172.17.0.5:9120" # 替换为要移除的后端实际 IP:端口

sozu --config "${CONFIG_PATH}" backend remove --id "${CLUSTER_ID}" --backend-id "${OLD_BACKEND_ID}" --address "${OLD_BACKEND_ADDRESS}"
  • --config: 指定 Sozu 配置文件的路径。
  • backend remove: 表示要执行移除后端的操作。
  • --id: 指定要移除后端的集群 ID。
  • --backend-id: 要移除的后端的ID。
  • --address: 要移除的后端服务器的 IP 地址和端口。

5.5 查看 Sōzu 工作进程状态

您可以使用 sozu status 命令来查看 Sōzu 工作进程(workers)的运行状态。

# 假设您的 Sozu 配置文件路径是 /etc/sozu/config.toml
CONFIG_PATH="/etc/sozu/config.toml"
sozu --config "${CONFIG_PATH}" status --json

这将返回一个 JSON 格式的当前工作进程状态。要查看详细的集群、前端和后端配置,请参阅下一节。

5.6 自动化脚本(概念)

要实现真正的服务发现,您需要编写一个持续运行的脚本(例如使用 Python、Bash 或 Go),该脚本:

  1. 周期性地或通过 事件监听 Docker API 来检测后端容器的变化。
  2. 比较当前 Sozu 中的后端列表与 Docker 中实际运行的后端列表。
  3. 执行 sozu backend addsozu backend remove 命令来同步这两个列表。

这个脚本将作为您服务发现方案中的“控制平面”。

5.7 查看动态添加的前端和后端

当您通过命令行动态添加了 frontendbackend 后,您可能想验证它们是否已成功加载。Sōzu 的路由结构是 frontend -> cluster -> backend。您可以通过以下两步来追踪和查看这些动态添加的数据:

  1. 查找 frontend 对应的 cluster ID

    使用 sozu frontend list --json 命令可以列出所有已配置的前端。在返回的 JSON 数据中,找到您关心的 frontend,并记下其所属的 cluster_id

    # 将 <您的/config.toml/路径> 替换为您的配置文件路径
    sozu --config <您的/config.toml/路径> frontend list --json
  2. 根据 cluster ID 查找其包含的 backend

    获取到 cluster ID 后,使用 sozu cluster list --id <CLUSTER_ID> --json 命令来查看该特定集群的详细信息,其中包括了它所包含的所有 backend 列表。

    # 替换 <您的/config.toml/路径> 和 <您的_CLUSTER_ID>
    sozu --config <您的/config.toml/路径> cluster list --id <您的_CLUSTER_ID> --json

通过这个两步流程,您可以清晰地看到从 frontendbackend 的完整映射关系,并确认您的动态配置已生效。