首页 文章 精选 留言 我的

精选列表

搜索[加密工具],共10000篇文章
优秀的个人博客,低调大师

从零开始编写一个类nginx工具, 配置数据的热更新原理及实现

wmproxy wmproxy是由Rust编写,已实现http/https代理,socks5代理, 反向代理,静态文件服务器,内网穿透,配置热更新等, 后续将实现websocket代理等,同时会将实现过程分享出来, 感兴趣的可以一起造个轮子法 项目地址 gite: https://gitee.com/tickbh/wmproxy github: https://github.com/tickbh/wmproxy 配置数据 数据通常配置在配置文件中,如果需要变更配置,我们通常将配置文件进行更新,并通知程序重新加载配置以便生效。 nginx的变更方式 在nginx中,我们通常用 nginx -s reload 进行数据的安全无缝的重载。在nginx中,是多进程的模式,也就是在nginx -s reload信号发出后master进程通知之前的work进程停止接收新的流,也就是accpet暂停,但是会服务完当前的数据请求,并同时会启用新的work进程来接受新的请求 缺点:nginx只能整体的配置做全部重置,且无法查看当前的配置(除非看配置文件,配置可能被重新修改过和内存中的值可能不匹配) 当前选取的方式 当前选择的是用HTTP请求的方式,也就是对本地的端口进行监听(http://127.0.0.1:8837),对本地端口监听也不会造成对外暴露端口带来的安全问题,这样子可以高度的自定义。具有比较高的活跃性,也可以实时查询内存中的数据。 例如访问: http://127.0.0.1:8837/reload即可通知目标进程重载当前的配置 http://127.0.0.1:8837/now即可以知道当前的所有的配置列表 http://127.0.0.1:8837/stop即可以关闭当前的进程,停止服务,类似于nginx中的nginx -s stop。 http://127.0.0.1:8837/adapt加载当前配置,看是否错误,但是不进行应用。 等功能。 功能实现的原理 单进程 单进程模式的缺点:如果存在内存泄漏之类的情况,无论如何重载进程都无法将内存恢复,会始终保持较高的内存值直到最终不可用的阶段。如果发生未正确处理的异常,可能会使该进程崩溃的风险,处于无服务状态。 单进程模式的优点:在当前进程存储的一些有利于加速服务的将会很好的被保留下来(如健康检查的数据),异步进程里正在处理的数据等。无需进行进程间通讯,配合tokio的异步处理可以将单进程的优势完美发挥出来。 端口复用 无论哪种模式,都需要处理数据重载时,绑定对象的转移TcpListener或者重新绑定TcpListener,在Rust中转移绑定对象相对来说较麻烦后续如果拓展成多进程模式也无法进行转移,所以不考虑用转移所有权的问题。那么此时我们的解决方法就是set_reuse_address及set_reuse_port,不同平台该方法上有不同的表现,我们用的是socket2的封装,用该方法的注意事项: 在windows平台上,不存在set_reuse_port方法,仅调用set_reuse_address即可实现一个地址多次绑定 在linux上,不同的版本上,有些只需调用set_reuse_address即可端口复用,有些需要同时调用set_reuse_port 在macos上,需要调用set_reuse_address和set_reuse_port函数才可实现端口复用 所以这里涉及一个分平台的编码,我们在此使用的是,这和C/C++中的#ifdef WINDOWS类似,但是只能在函数级的做调整,所以此处额外在封装了两个函数来做调用。 /// 非windows平台 #[cfg(not(target_os = "windows"))] fn set_reuse_port(socket: &Socket, reuse: bool) -> io::Result<()> { socket.set_reuse_port(true)?; Ok(()) } /// windows平台,空实现 #[cfg(target_os = "windows")] fn set_reuse_port(_socket: &Socket, _sreuse: bool) -> io::Result<()> { Ok(()) } 然后将原来的TcpListener::bind(addr)函数改成Helper::bind即可无缝切换到支持端口复用的功能,针对代理端及反向代理端: /// 可端口复用的绑定方式,该端口可能被多个进程同时使用 pub async fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> { let addrs = addr.to_socket_addrs()?; let mut last_err = None; for addr in addrs { let socket = Socket::new(Domain::IPV4, Type::STREAM, None)?; socket.set_nonblocking(true)?; let _ = socket.set_only_v6(false); socket.set_reuse_address(true)?; Self::set_reuse_port(&socket, true)?; socket.bind(&addr.into())?; match socket.listen(128) { Ok(_) => { let listener: std::net::TcpListener = socket.into(); return TcpListener::from_std(listener); } Err(e) => { log::info!("绑定端口地址失败,原因: {:?}", addr); last_err = Some(e); } } } Err(last_err.unwrap_or_else(|| { io::Error::new( io::ErrorKind::InvalidInput, "could not resolve to any address", ) })) } 测试功能 测试配置加载reload,一开始我们绑定81的端口 进程启动后改为绑定82的端口,然后调用reload(curl.exe http://127.0.0.1:8837/reload) 此时,再调用stop(curl.exe http://127.0.0.1:8837/stop),正确的预期应该显示关闭,且82端口不可再访问 符合功能预期,初步测试完毕 相关源码实现 以下是启动及发送重载配置的流程示意图 以下是中控的定义,消息的通知主要通过Sender/Receiver来进行数据的通知。 /// 控制端,可以对配置进行热更新 pub struct ControlServer { /// 控制端当前的配置文件,如果部分修改将直接修改数据进行重启 option: ConfigOption, /// 通知服务进行关闭的Sender,服务相关如果收到该消息则停止Accept server_sender_close: Option<Sender<()>>, /// 通知中心服务的Sender,每个服务拥有一个该Sender,可反向通知中控关闭 control_sender_close: Sender<()>, /// 通知中心服务的Receiver,收到一次则将当前的引用计数-1,如果为0则表示需要关闭服务器 control_receiver_close: Option<Receiver<()>>, /// 服务的引用计数 count: i32, } 启动控制终端,接收HTTP的指令和关闭的指令,此时control已经变成了Arc<Mutex<ControlServer>>,方便在各各线程间传播,同步修改数据。 pub async fn start_control(control: Arc<Mutex<ControlServer>>) -> ProxyResult<()> { let listener = { let value = &control.lock().await.option; TcpListener::bind(format!("127.0.0.1:{}", value.control)).await? }; loop { let mut receiver = { let value = &mut control.lock().await; value.control_receiver_close.take() }; tokio::select! { Ok((conn, addr)) = listener.accept() => { let cc = control.clone(); tokio::spawn(async move { let mut server = Server::new_data(conn, Some(addr), cc); if let Err(e) = server.incoming(Self::operate).await { log::info!("反向代理:处理信息时发生错误:{:?}", e); } }); let value = &mut control.lock().await; value.control_receiver_close = receiver; } _ = Self::receiver_await(&mut receiver) => { let value = &mut control.lock().await; value.count -= 1; log::info!("反向代理:控制端收到关闭信号,当前:{}", value.count); if value.count <= 0 { break; } value.control_receiver_close = receiver; } } } Ok(()) } 处理相关消息: if req.path() == "/reload" { // 将重新启动服务器 let _ = value.do_restart_serve().await; return Ok(Response::text() .body("重新加载配置成功") .unwrap() .into_type()); } if req.path() == "/stop" { // 通知控制端关闭,控制端阻塞主线程,如果控制端退出后进程退出 if let Some(sender) = &value.server_sender_close { let _ = sender.send(()).await; } return Ok(Response::text() .body("关闭进程成功") .unwrap() .into_type()); } 以下是主要的启动代码: async fn inner_start_server(&mut self, option: ConfigOption) -> ProxyResult<()> { let sender = self.control_sender_close.clone(); let (sender_no_listen, receiver_no_listen) = channel::<()>(1); let sender_close = self.server_sender_close.take(); // 每次启动的时候将让控制计数+1 self.count += 1; tokio::spawn(async move { let mut proxy = Proxy::new(option); // 将上一个进程的关闭权限交由下一个服务,只有等下一个服务准备完毕的时候才能关闭上一个服务 if let Err(e) = proxy.start_serve(receiver_no_listen, sender_close).await { log::info!("处理失败服务进程失败: {:?}", e); } // 每次退出的时候将让控制计数-1,减到0则退出 let _ = sender.send(()).await; }); self.server_sender_close = Some(sender_no_listen); Ok(()) } 结语 此时以不同于nginx的另一种配置的加载已经开发完毕,配置的热加载可以让您更从容的保护好您的系统。 点击 <font color=green>[关注]</font>,<font color=green>[在看]</font>,<font color=green>[点赞]</font> 是对作者最大的支持

优秀的个人博客,低调大师

主机集群监控工具 WGCLOUD v3.4.4 支持拓扑图数据流动和代码语法高亮显示

WGCLOUD是一款集成度较高的分布式运维监控平台,具有集群监控,易部署、易上手使用、轻量、高效、自动化等特点,server 端基于springboot 开发,agent 端使用 go 编写。核心模块包括:主机系统信息监控,CPU 监控,CPU 温度监控,内存监控,网络流量监控,磁盘 IO 监控,磁盘空间监测,系统负载监控,硬盘 smart 健康检测,应用进程监控,端口监控,docker 监控,日志文件监控,文件防篡改保护,数据可视化监控,自动生成拓扑图、大屏可视化,数通设备监测,服务接口监测,web ssh 堡垒机,指令下发,告警信息(邮件、钉钉、微信等)推送。 码云仓库:https://gitee.com/wanghouhou/wgcloud GITHUB 仓库:https://github.com/tianshiyeben/wgcloud WGCLOUD 唯一官网:http://www.wgstart.com WGCLOUD 支持监测的操作系统平台 支持监测 Linux 系列:Debian、RedHat、CentOS、Ubuntu、Fedora、麒麟、统信 (UOS)、龙芯 (mips) 等 支持监测 Windows 系列:Windows Server 2008 R2,2012,2016,2019,2022,Windows 7,Windows 8,Windows 10,Windows 11 支持监测 Unix 系列:solaris,FreeBSD,OpenBSD 支持监测 MacOS 系列:macOS amd64,macOS arm64 其他支持:ARM,Android(安卓),riscv64,s390x,树莓派等 WGCLOUD-v3.4.4 更新说明 2023-01-29发布 1. 新增,服务接口监测,增加采集响应 body 体积大小 2. 新增,指令下发和自定义监控项模块,支持同时下发多条指令 3. 新增,FTP/SFTP,服务接口,数通监测列表添加开始监控和停止监控按钮 4. 新增,成员账号增加迁移功能,可以将某个账号的所有监控资源迁移到其他账号 5. 新增,公众看板的监控概要和主机列表页面,可以设置自动刷新 (10 分钟一次),查看说明 6.bug 修复,删除成员账号时候,同时解绑该账号的主机、服务接口、PING、SNMP、数据库、FTP 的账号信息 7.bug 修复,snmp 列表搜索跳转到 ping 列表 8.bug 修复,主机列表按照 cpu%,内存 % 排序不准确的问题 9. 改造,指令下发、自定义监控项、服务接口、数据监控、日志监控模块,原文本域改造为在线代码编辑器 (主要用于语法高亮显示) 10. 改造,数通拓扑图菜单,拆分为 PING 拓扑图和 SNMP 拓扑图 11. 优化,主机判定下线机制更灵敏 12. 优化,主机图表中增加显示告警线 13. 优化,数据开放接口:主机列表、主机 CPU 使用率、主机内存使用率、主机系统负载、主机系统网络流量等接口,增加排序参数 14. 优化改进,日志监控模块性能,主要针对监控体积较大的日志文件时候自动优化,保护系统性能 15. 一些已知的 bug 修复,优化 UI,代码结构优化

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册