当前位置:首页 > 科技  > 软件

Rust中的信号处理:Unix信号 vs 信号服务器

来源: 责编: 时间:2024-04-02 17:19:16 289观看
导读如果你正在运行一个服务器,假设服务器需要从磁盘读取一些文件,比如证书或密钥。证书经常会发生变化,因此你的服务器必须重新加载它们。如何告诉服务器重新加载这些文件?传统的方法是使用Unix信号,你的服务器侦听特定的信号

如果你正在运行一个服务器,假设服务器需要从磁盘读取一些文件,比如证书或密钥。证书经常会发生变化,因此你的服务器必须重新加载它们。如何告诉服务器重新加载这些文件?jDu28资讯网——每日最新资讯28at.com

传统的方法是使用Unix信号,你的服务器侦听特定的信号,如SIGUSR1(用户定义的信号#1)或SIGHUP(挂起信号),并且可以在接收到信号时执行你编写的任何代码。因此,你的服务器等待适当的信号,接收它,然后重新加载证书。jDu28资讯网——每日最新资讯28at.com

这种方法工作得很好,但是在实际应用中出现了一些可用性的问题。使用单独的一个http服务器来处理信号会更好。jDu28资讯网——每日最新资讯28at.com

下面我们先来看一下使用Unix信号的例子,然后我们使用服务器处理信号来改进这个例子。jDu28资讯网——每日最新资讯28at.com

首先,我们先创建一个Rust项目:jDu28资讯网——每日最新资讯28at.com

cargo new signals-servers

jDu28资讯网——每日最新资讯28at.com

在Cargo.toml文件中加入以下依赖项:jDu28资讯网——每日最新资讯28at.com

[dependencies]axum = "0.7.2"tokio = { version = "1.25.0", features = ["macros", "rt-multi-thread", "signal"] }

在项目根目录下创建一个cert.pem文件,内容随便写,只是为了演示。jDu28资讯网——每日最新资讯28at.com

jDu28资讯网——每日最新资讯28at.com

jDu28资讯网——每日最新资讯28at.com

Unix信号处理

我们看一个完整的服务器侦听信号的示例,当你启动你的服务器时,也启动一个异步任务(或进程,或线程)来监听这个信号,当接收到信号时,重新加载证书。jDu28资讯网——每日最新资讯28at.com

创建一个src/bin/unix_signal.rs文件,代码如下:jDu28资讯网——每日最新资讯28at.com

use axum::{routing::get, Router};use std::process;use tokio::signal::unix::{signal, SignalKind};#[tokio::main]async fn main() {    let _cert = std::fs::read_to_string("cert.pem");    println!("已加载证书,正在启动web服务器");    println!("PID: {}", process::id());    tokio::select! {        _ = start_normal_server(8080) => {            println!("Web服务器关闭")        }        _ = listen_for_reload(SignalKind::hangup()) => {            println!("信号监听器停止")        }    }}async fn start_normal_server(port: u32) {    // 构建我们的应用程序    let app = Router::new().route("/hello", get(|| async { "Hello, world!" }));    let addr = format!("127.0.0.1:{port}");    let listener = tokio::net::TcpListener::bind(addr).await.unwrap();    axum::serve(listener, app).await.unwrap();}async fn listen_for_reload(signal_kind: SignalKind) -> Result<(), std::io::Error> {    // 监听信号    let mut stream = signal(signal_kind)?;    loop {        stream.recv().await;        match std::fs::read_to_string("cert.pem") {            Ok(_) => eprintln!("重新加载证书成功"),            Err(e) => eprintln!("无法重新加载证书: {e}"),        }    }}

jDu28资讯网——每日最新资讯28at.com

运行如下命令启动服务器:jDu28资讯网——每日最新资讯28at.com

cargo run --bin unix_signal已加载证书,正在启动web服务器PID: 41945

jDu28资讯网——每日最新资讯28at.com

然后打开一个新的终端,输入以下命令:jDu28资讯网——每日最新资讯28at.com

kill -s sighup 41945

jDu28资讯网——每日最新资讯28at.com

这是服务器的日志如下:jDu28资讯网——每日最新资讯28at.com

已加载证书,正在启动web服务器PID: 41945重新加载证书成功

jDu28资讯网——每日最新资讯28at.com

这是可行的,但对于发送信号的人来说,这不是一个很好的用户体验。假设你是SRE或系统管理员,当需要重新加载服务器证书时,首先查找进程的PID,并使用kill -s sighup pid发送信号。jDu28资讯网——每日最新资讯28at.com

服务器可能重新加载了,但也许它没有,可能出现了错误,例如新证书无效,或者服务器没有读取新证书的权限。系统管理员如何知道是否发生了这种情况?他们应该检查一下服务器的日志,但这需要切换窗口,或者打开一个不同的程序。jDu28资讯网——每日最新资讯28at.com

这不是一个很好的用户体验。通常,当你运行命令时,希望得到一些反馈。但是当你发送Unix信号时,终端不会给你任何响应。你必须查找服务器的日志并检查它们,以确保重新加载成功完成。阅读一个不熟悉的程序日志是很困难的,特别是当日志中有很多其他错误时。jDu28资讯网——每日最新资讯28at.com

Unix信号的主要问题是,它们让用户向进程发出信号,但程序不向用户发送响应。jDu28资讯网——每日最新资讯28at.com

jDu28资讯网——每日最新资讯28at.com

jDu28资讯网——每日最新资讯28at.com

更好的方法:信号服务器

因此,我们希望进程接受请求(“重新加载您的证书”),并响应(“是的,它成功了”或“它失败了,原因如下”)。这听起来很熟悉——它只是一个普通的请求-响应协议。没有必要重新发明轮子——我们可以在这个过程中启动第二个小HTTP服务器。jDu28资讯网——每日最新资讯28at.com

创建一个src/bin/http_signal.rs文件,代码如下:jDu28资讯网——每日最新资讯28at.com

use axum::{    http::StatusCode,    response::IntoResponse,    routing::{get, post},    Router,};#[tokio::main]async fn main() {    let _cert = std::fs::read_to_string("cert.pem");    println!("已加载证书,正在启动web服务器");    tokio::select! {        _ = start_normal_server(8080) => {            println!("Web服务器关闭")        }        _ = start_control_server(3000) => {            println!("信号服务器关闭")        }    }}async fn start_normal_server(port: u32) {    // 构建我们的应用程序    let app = Router::new().route("/hello", get(|| async { "Hello, world!" }));    let addr = format!("127.0.0.1:{port}");    let listener = tokio::net::TcpListener::bind(addr).await.unwrap();    axum::serve(listener, app).await.unwrap();}async fn start_control_server(port: u32) {    // 构建信号控制服务器    let app: Router = Router::new().route(        "/reload_certs",        post(|| async {            println!("重新加载证书");            match std::fs::read_to_string("cert.pem") {                Ok(_) => "重新加载证书成功".into_response(),                Err(e) => {                    let error = format!("无法重新加载证书: {e}");                    eprintln!("{error}");                    let resp = (StatusCode::INTERNAL_SERVER_ERROR, error);                    resp.into_response()                }            }        }),    );    let addr = format!("127.0.0.1:{port}");    let listener = tokio::net::TcpListener::bind(addr).await.unwrap();    axum::serve(listener, app).await.unwrap();}

jDu28资讯网——每日最新资讯28at.com

对于SRE或系统管理员来说,这是一个更好的用户体验。使用如下命令重新加载证书:jDu28资讯网——每日最新资讯28at.com

$ curl -X POST 0.0.0.0:3000/reload_certs重新加载证书成功%

如果没有找到证书,会立即得到有关错误的反馈:jDu28资讯网——每日最新资讯28at.com

$ curl -X POST 0.0.0.0:3000/reload_certs无法重新加载证书: No such file or directory (os error 2)

jDu28资讯网——每日最新资讯28at.com

jDu28资讯网——每日最新资讯28at.com

总结

如果你的程序不需要HTTP或网络,那么引入一个完整的HTTP框架来监听信号可能有点多余。因此,根据程序的大小,以及系统管理员的需求或SRE团队的大小,来决定是否添加HTTP服务器,因为这对于管理流程的人员和软件来说,它有更好的用户体验。jDu28资讯网——每日最新资讯28at.com

jDu28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-80844-0.htmlRust中的信号处理:Unix信号 vs 信号服务器

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 2024年最受欢迎的十个 Vue.js UI 库

下一篇: 我们一起聊聊如何三分钟学会异步任务基础

标签:
  • 热门焦点
  • 红魔电竞平板评测:大屏幕硬实力

    前言:三年的疫情因为要上网课的原因激活了平板市场,如今网课的时代已经过去,大家的生活都恢复到了正轨,这也就意味着,真正考验平板电脑生存的环境来了。也就是面对着这种残酷的
  • 服务存储设计模式:Cache-Aside模式

    Cache-Aside模式一种常用的缓存方式,通常是把数据从主存储加载到KV缓存中,加速后续的访问。在存在重复度的场景,Cache-Aside可以提升服务性能,降低底层存储的压力,缺点是缓存和底
  • 分布式系统中的CAP理论,面试必问,你理解了嘛?

    对于刚刚接触分布式系统的小伙伴们来说,一提起分布式系统,就感觉高大上,深不可测。而且看了很多书和视频还是一脸懵逼。这篇文章主要使用大白话的方式,带你理解一下分布式系统
  • 量化指标是与非:挽救被量化指标扼杀的技术团队

    作者 | 刘新翠整理 | 徐杰承本文整理自快狗打车技术总监刘新翠在WOT2023大会上的主题分享,更多精彩内容及现场PPT,请关注51CTO技术栈公众号,发消息【WOT2023PPT】即可直接领取
  • 一文掌握 Golang 模糊测试(Fuzz Testing)

    模糊测试(Fuzz Testing)模糊测试(Fuzz Testing)是通过向目标系统提供非预期的输入并监视异常结果来发现软件漏洞的方法。可以用来发现应用程序、操作系统和网络协议等中的漏洞或
  • 10天营收超1亿美元,《星铁》比《原神》差在哪?

    来源:伯虎财经作者:陈平安即便你没玩过《原神》,你一定听说过的它的大名。恨它的人把《原神》开服那天称作是中国游戏史上最黑暗的一天,有粉丝因为索尼在PS平台上线《原神》,怒而
  • 腾讯盖楼,字节拆墙

    来源 | 光子星球撰文 | 吴坤谚编辑 | 吴先之&ldquo;想重温暴刷深渊、30+技能搭配暴搓到爽的游戏体验吗?一起上晶核,即刻暴打!&rdquo;曾凭借直播腾讯旗下代理格斗游戏《DNF》一
  • 电博会上海尔智家模拟500平大平层,还原生活空间沉浸式体验

    电博会为了更好地让参展观众真正感受到智能家居的绝妙之处,海尔智家的程传岭先生同样介绍了展会上海尔智家的模拟500平大平层,还原生活空间沉浸式体验。程传
  • 利用职权私自解除被封帐号 Meta开除20多名员工

    11月18日消息,据外媒援引知情人士表示,过去一年时间内,Facebook母公司Meta解雇或处罚了20多名员工以及合同工,指控这些人通过内部系统以不当方式重置用户帐号,其
Top