10 个版本 (5 个稳定)
3.0.0 | 2024 年 5 月 7 日 |
---|---|
2.1.0 | 2024 年 4 月 18 日 |
2.0.0 | 2024 年 3 月 24 日 |
1.1.0 | 2022 年 11 月 9 日 |
0.1.1 | 2022 年 4 月 22 日 |
#275 在 网络编程
每月 281 次下载
用于 3 个 Crates(2 个直接使用)
27KB
450 行
service-binding
提供了一种方式,允许服务器和客户端以结构化格式描述它们的服务绑定和客户端端点。
此 Crates 自动解析和绑定到 TCP 套接字、Unix 套接字和 Windows 命名管道。
设计上,此 Crates 非常精简,主要依赖于 std
中的内容(除 macOS launchd 服务绑定外)。
URI 方案绑定深受 Docker Engine 指定方案的影响。
use service_binding::{Binding, Listener};
let host = "tcp://127.0.0.1:8080"; // or "unix:///tmp/socket"
// parse the URI into a Binding
let binding: Binding = host.parse().unwrap();
// convert the binding into a Listener
match binding.try_into().unwrap() {
#[cfg(unix)]
Listener::Unix(listener) => {
// bind to a unix domain socket
},
Listener::Tcp(listener) => {
// bind to a TCP socket
}
Listener::NamedPipe(pipe) => {
// bind to a Windows Named Pipe
}
}
支持的方案
URI 格式 | 示例 | 描述 | 绑定 | 监听器 / 流 |
---|---|---|---|---|
tcp://ip:port |
tcp://127.0.0.1:8080 |
TCP IP 地址 | 套接字 |
Tcp |
tcp://address:port |
tcp://localhost:8080 |
具有地址解析的主机名 [^1] | 套接字 |
Tcp |
unix://path |
unix:///run/user/1000/test.sock |
Unix 域套接字 [^2] | 文件路径 |
Unix |
fd:// |
fd:// |
systemd 首次套接字激活 [^3][^4] | 文件描述符 |
Unix |
fd://<number> |
fd://3 |
精确的文件描述符数字 | 文件描述符 |
Unix |
fd://<socket-name> |
fd://http |
通过名称激活套接字 [^4] | 文件描述符 |
Unix |
npipe://<name> |
npipe://agent |
Windows 命名管道 [^5] | 命名管道 |
命名管道 |
^[1] 绑定到第一个成功的地址(见 TcpListener::bind
) [^2] 目前在Windows上通过 std
不可用(见 #271 和 #56533) [^3] 等同于 fd://
但如果传递了更多套接字则会失败 [^4] 仅为监听器 [^5] 转换为 \\.\pipe\test
示例
以下示例使用 clap
和 actix-web
,并使其能够使用Unix域套接字(包括systemd套接字激活)和绑定到TCP端口的常规TCP套接字组合运行服务器
use actix_web::{web, App, HttpServer, Responder};
use clap::Parser;
use service_binding::{Binding, Listener};
#[derive(Parser, Debug)]
struct Args {
#[clap(
env = "HOST",
short = 'H',
long,
default_value = "tcp://127.0.0.1:8080"
)]
host: Binding,
}
async fn greet() -> impl Responder {
"Hello!"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let server = HttpServer::new(move || {
App::new().route("/", web::get().to(greet))
});
match Args::parse().host.try_into()? {
#[cfg(unix)]
Listener::Unix(listener) => server.listen_uds(listener),
Listener::Tcp(listener) => server.listen(listener),
_ => Err(std::io::Error::other("Unsupported listener type")),
}?.run().await
}
systemd 套接字激活
此crate还支持systemd的 套接字激活。如果要解析的参数是 fd://
,则返回的 Listener
对象将是一个包含systemd提供的监听器的 Unix
变体。
例如以下文件定义了一个套接字单元:~/.config/systemd/user/app.socket
[Socket]
ListenStream=%t/app.sock
FileDescriptorName=service-name
[Install]
WantedBy=sockets.target
当启用时,它将在 $XDG_RUNTIME_DIR
目录中创建一个新的套接字文件。当此套接字连接到systemd时,将启动服务;fd://
读取正确的systemd环境变量并返回Unix域套接字。
服务单元文件 ~/.config/systemd/user/app.service
[Service]
ExecStart=/usr/bin/app -H fd://
由于套接字已命名(FileDescriptorName=service-name
),因此也可以使用其显式名称选择它:fd://
。
launchd 套接字激活
在macOS上,尽管需要通过 fd://
语法显式命名套接字,但launchd套接字激活也是可用的。
相应的 plist
文件(可以放置在 ~/Library/LaunchAgents
并通过 launchctl load ~/Library/LaunchAgents/service.plist
加载)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>EnvironmentVariables</key>
<dict>
<key>RUST_LOG</key>
<string>debug</string>
</dict>
<key>KeepAlive</key>
<true/>
<key>Label</key>
<string>com.example.service</string>
<key>OnDemand</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>/path/to/service</string>
<string>-H</string>
<string>fd://socket-name</string> <!-- activate socket by name -->
</array>
<key>RunAtLoad</key>
<true/>
<key>Sockets</key>
<dict>
<key>socket-name</key> <!-- the socket name here -->
<dict>
<key>SockPathName</key>
<string>/path/to/socket</string>
<key>SockFamily</key>
<string>Unix</string>
</dict>
</dict>
<key>StandardErrorPath</key>
<string>/Users/test/Library/Logs/service/stderr.log</string>
<key>StandardOutPath</key>
<string>/Users/test/Library/Logs/service/stdout.log</string>
</dict>
</plist>
许可证
本项目根据您的选择受以下之一许可:
。
贡献
除非您明确声明,否则根据Apache-2.0许可证定义,您提交给此crate的任何有意贡献,都应按上述方式双许可,不附加任何额外条款或条件。