6个版本 (3个重大更改)
0.7.1 | 2024年6月20日 |
---|---|
0.7.0 | 2023年3月13日 |
0.6.1 | 2022年9月21日 |
0.5.0 | 2022年8月17日 |
0.4.0 | 2022年1月25日 |
#185 in HTTP服务器
每月307次下载
16KB
206 行
tailsrv
tailsrv 监视单个文件,并在文件增长时将其内容流式传输到多个客户端。它就像 tail -f
,但作为一个服务器。
- 当客户端连接时,tailsrv 会向它发送文件数据。
- 如果没有新数据要发送,tailsrv 会等待文件增长。
- 如果套接字已满,tailsrv 会等待客户端消耗一些数据后再发送更多。
- 客户端可以在连接时指定一个初始字节偏移量。
一些实现细节
- 所有数据都是通过 sendfile 发送的。这意味着数据是直接由内核从页缓存发送到网卡。从不将数据复制到用户空间。这使 tailsrv 具有很好的吞吐量。然而,这也意味着 tailsrv 只能在 Linux 上运行。
- 我们使用 inotify 跟踪文件的修改。这意味着如果文件没有增长(并且没有新的客户端连接),tailsrv 不会做任何工作。
- 我们为每个客户端启动一个线程。这意味着缓慢的客户端可以以自己的速度接收数据,而不会影响其他客户端。
如果您想了解 tailsrv 与 Kafka 的比较,请参阅 这里 的比较。
使用示例
假设您有一台名为 webserver
的机器。选择一个端口号并启动 tailsrv
$ tailsrv -p 4321 /var/log/nginx/access.log
tailsrv 现在正在监视 access.log。您可以从您的笔记本电脑连接到 tailsrv 并流式传输文件的内容
$ echo "1000" | nc webserver 4321
您将立即看到 access.log 的内容,从字节 1000 开始,到文件末尾。连接保持打开,等待新数据。一旦 nginx 将一行写入 access.log,它就会出现在您的笔记本电脑上。这大致与这样做相同
$ ssh webserver -- tail -f -c+1000 /var/log/nginx/access.log
然而,您可能希望直接从您的日志消耗应用程序连接到 tailsrv。
let sock = TcpStream::connect("webserver:4321")?;
writeln!(sock, "{}", 1000)?;
for line in BufReader::new(sock).lines() {
/* handle log data */
}
上面的示例是用 rust 编写的,但如您所见,它非常简单:您可以从任何编程语言中这样做,而无需特殊的客户端库。
协议
步骤 1:客户端向 tailsrv 发送头部信息
头部信息是一个 ASCII 码整数,以换行符结束。如果整数是正数,它表示初始字节数偏移量。如果整数是负数,它表示“从文件末尾开始计数”。示例
0\n
- 从文件开头开始1000\n
- 从第 1000 个字节开始-1000\n
- 发送最后 1000 个字节
步骤 2:tailsrv 向客户端发送数据
一旦它收到头部信息,tailsrv 将开始向您发送文件数据。
...这就是整个协议的内容。tailsrv 将忽略您在换行符之后发送的任何内容。当您完成时,只需关闭连接即可。除非 tailsrv 正在关闭,否则它不会终止连接。
没有内带会话控制:如果您想跳转到文件中的不同位置,请关闭连接并打开一个新的连接。
文件
tailsrv 期望一个将被附加的文件。如果被监视的文件被删除或移动,tailsrv 将退出。如果您修改了文件的中间部分 - 嗯,不会发生灾难性的事情,但您的客户端可能会感到困惑。
功能
tracing-journald
启用对 tracing-journald 库的依赖,并添加了一个新的 --journald
命令行标志。这将把所有跟踪输出重定向到系统 journald
,它比默认输出格式化程序提供的信息更丰富。如果您计划以 tailsrv
作为 systemd 服务运行,特别有用。
sd-notify
启用对 sd-notify 库的依赖。《tt class="src-rs">tailsrv 将在开始接受客户端连接后发送 systemd 准备就绪通知。这与 notify
systemd 服务类型结合使用时很有用。
许可
本软件属于公共领域。有关详细信息,请参阅 UNLICENSE。
依赖项
~8–18MB
~238K SLoC