You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Actix绑定Unix Socket并实现多子域名运行的配置问题

Actix绑定Unix Socket+多子域名路由隔离解决方案

1. 正确绑定Unix Socket

首先要搞定Unix Socket的创建与权限问题,/etc/server.sock属于系统目录,默认权限可能导致Nginx无法连接,得提前处理:

use actix_web::{web, App, HttpServer};
use tokio::net::UnixListener;
use std::path::Path;

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let socket_path = Path::new("/etc/server.sock");
    // 绑定前删除旧socket文件,避免"地址已被占用"错误
    if socket_path.exists() {
        std::fs::remove_file(socket_path)?;
    }

    // 创建UnixListener并绑定到目标路径
    let listener = UnixListener::bind(socket_path)?;

    // 设置socket权限为0o660,让Nginx进程能读写
    std::fs::set_permissions(socket_path, std::fs::Permissions::from_mode(0o660))?;
    // 额外将socket所属组改为www-data(对应Nginx运行用户),需提前确认组ID或手动执行`chown root:www-data /etc/server.sock`

    HttpServer::new(|| {
        App::new()
            // 后续添加子域名路由逻辑
    })
    .listen(listener)?
    .run()
    .await
}

2. 多子域名路由隔离核心:Host守卫

Actix自带Host路由守卫,能根据请求的Host头(即子域名)过滤请求,把不同子域名的路由完全隔离开,无需拆分多个服务器,从根源避免路由冲突。

固定子域名分组路由示例

给每个子域名创建独立的路由作用域,用守卫严格过滤,就算不同子域名有相同路径(比如都有/dashboard)也不会冲突:

HttpServer::new(|| {
    App::new()
        // api.example.com专属路由
        .service(
            web::scope("")
                .guard(web::guard::Host("api.example.com"))
                .route("/users", web::get().to(get_users))
                .route("/products", web::post().to(create_product))
        )
        // admin.example.com专属路由
        .service(
            web::scope("")
                .guard(web::guard::Host("admin.example.com"))
                .route("/dashboard", web::get().to(admin_dashboard))
                .route("/settings", web::put().to(update_admin_settings))
        )
        // www.example.com默认路由
        .service(
            web::scope("")
                .guard(web::guard::Host("www.example.com"))
                .route("/", web::get().to(home_page))
                .route("/about", web::get().to(about_page))
        )
})

动态子域名处理(多租户场景)

如果子域名是动态生成的,直接在请求处理中获取Host头做逻辑分支即可:

use actix_web::HttpRequest;

async fn dynamic_handler(req: HttpRequest) -> String {
    let host = req.host().unwrap_or("unknown");
    match host {
        "tenant1.example.com" => handle_tenant1(req).await,
        "tenant2.example.com" => handle_tenant2(req).await,
        _ => "Unknown subdomain".to_string(),
    }
}

// 注册通配路由匹配所有请求
// .route("/{tail:.*}", web::get().to(dynamic_handler))

3. 必注意的坑点

  • Socket权限:Nginx运行用户(通常是www-data)必须拥有socket的读写权限,否则会返回502错误。代码设置0o660权限后,需配合chown root:www-data /etc/server.sock确保组权限正确。
  • Nginx必须传Host头:反向代理配置里必须添加proxy_set_header Host $host;,否则Actix无法获取正确的子域名,路由守卫会失效。示例Nginx配置:
    server {
        server_name api.example.com;
        location / {
            proxy_pass http://unix:/etc/server.sock;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
    
    server {
        server_name admin.example.com;
        location / {
            proxy_pass http://unix:/etc/server.sock;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
    
  • 路由顺序无影响:每个路由作用域都有独立的Host守卫,Actix会自动匹配符合条件的请求,无需纠结路由注册顺序。

内容的提问来源于stack exchange,提问作者def750

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 02:06:26