当前位置: 首页 > news >正文

Rpc异步日志模块

Rpc异步日志模块作用

在一个大型分布式系统中,任何部署的分布式节点都可能发生崩溃,试想如果用普通的办法,即先排查哪个节点down掉了,找到down掉的节点后采取调试工具gdb调试该节点,进而排查宕机的原因。这中排查方法对于人力物力都是无法接受的。
那么由此记录日志就变得至关重要,分布式RPC框架必定存在一个异步日志模块,用于记录所有分布式站点的调试信息。通过日志分析就能很容易排查出哪个节点出了问题

Rpc异步日志模块实现思路

一个日志模块必须是异步的,不能影响主程序的运行,例如在RPC框架中显然不能阻塞了RPCProvider(服务提供者)和RPCConsumer(服务调用者)的运行
RPCProvider是一个能接受高并发rpc请求的高性能服务器(epoll+多线程),那么存在多个线程同时写日志的情况,这里的“写日志”并不是真正意义上的写磁盘文件的操作,因为磁盘IO会严重拖累该线程原本执行的其他任务。所以这里的写日志 只是多个线程将日志写入一个异步缓冲队列(这个操作是在内存进行的非常快),并且这个队列必须是线程安全的。
此外,应该另起一个线程来读取队列里面的日志数据进行真正的磁盘写文件操作,这样写日志线程是单独工作的,它只是依赖于异步缓冲队列里面的数据,不会影响RPC服务线程和其他IO线程。
在这里插入图片描述

Rpc异步日志模块实现

下面提供一个简单版本的实现
异步缓冲队列类:

#pragma once#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>//异步写日志的日志队列
template<typename T>
class LockQueue
{public://多个work线程都会写日志queuevoid Push(const T& data){std::lock_guard<std::mutex> lock(m_mutex);m_queue.push(data);m_condvariable.notify_one();}//一个线程读日志queue,写日志文件T Pop(){std::unique_lock<std::mutex> lock(m_mutex);while(m_queue .empty()){//日志队列为空, 线程进入wait状态m_condvariable.wait(lock);}T data = m_queue.front();m_queue.pop();return data;}
private:std::queue<T> m_queue;std::mutex m_mutex;std::condition_variable m_condvariable;};

Logger.h类:

#pragma once#include "lockqueue.h"
#include <utility>//日志级别
enum LogLevel{INFO = 1, //普通信息ERROR  //错误信息
};//Mprpc框架提供的日志系统
class Logger
{
public://获取日志的单例static Logger& GetInstance();//写日志void Log(std::pair<LogLevel,std::string> msg);private:LockQueue<std::pair<LogLevel,std::string>> m_lckQue; //日志缓冲队列Logger();Logger(const Logger&) = delete;Logger(Logger&& ) = delete;Logger& operator=(const Logger&) = delete;
};//定义宏  LOG_XXX("xxx %d %s", 20, "sdasd");
#define LOG_INFO(logmsgformat, ...) \do \{ \Logger &logger = Logger::GetInstance(); \char c[1024] = {0};           \snprintf(c, 1024, logmsgformat, ##__VA_ARGS__); \std::pair<LogLevel,std::string> pr = std::make_pair(INFO, std::string(c)); \logger.Log(pr); \} while (0);#define LOG_ERR(logmsgformat, ...) \
do \
{ \Logger &logger = Logger::GetInstance(); \char c[1024] = {0};           \snprintf(c, 1024, logmsgformat, ##__VA_ARGS__); \std::pair<LogLevel,std::string> pr = std::make_pair(ERROR, std::string(c)); \logger.Log(pr); \
} while (0);

Logger.cc

#include "logger.h"
#include <time.h>
#include <iostream>//获取日志的单例
Logger& Logger::GetInstance()
{static Logger logger;return logger;
}Logger::Logger()
{//启动专门的写日志线程std::thread writeLogTask([&](){for(;;){//获取当前的日期,然后取日志信息,写入相应的日志文件当中 a+time_t now = time(nullptr);tm *nowtm = localtime(&now);char file_name[128];sprintf(file_name, "%d-%d-%d-log.txt", nowtm->tm_year + 1900, nowtm->tm_mon + 1, nowtm->tm_mday);FILE* pf = fopen(file_name, "a+");if(pf == nullptr){std::cout<<"logger file:" << file_name <<"open error" << std::endl;exit(EXIT_FAILURE);}std::pair<LogLevel,std::string> msg = m_lckQue.Pop();char time_buf[128] = {0};sprintf(time_buf, "%d-%d-%d => [%s]", nowtm->tm_hour, nowtm->tm_min, nowtm->tm_sec,(msg.first == INFO ? "info" : "error"));msg.second.insert(0, time_buf);msg.second.append("\n");fputs(msg.second.c_str(), pf);fclose(pf); }});//设置分离线程, 守护线程writeLogTask.detach();}//写日志,把日志信息写入到lockqueue缓冲区当中
void Logger::Log(std::pair<LogLevel,std::string> msg)
{m_lckQue.Push(msg);
}

使用:

...
LOG_INFO("NotifyService UserService success");
LOG_ERR("eeeeeerrror%d", 9999999);
LOG_INFO("NotifyService GetFriendListService success");
...查看日志文件:cat 2023-8-2-log.txt 
21-35-26 => [info]NotifyService UserService success
21-35-26 => [error]eeeeeerrror9999999
21-35-26 => [info]NotifyService GetFriendListService success

相关文章:

Rpc异步日志模块

Rpc异步日志模块作用 在一个大型分布式系统中&#xff0c;任何部署的分布式节点都可能发生崩溃&#xff0c;试想如果用普通的办法&#xff0c;即先排查哪个节点down掉了&#xff0c;找到down掉的节点后采取调试工具gdb调试该节点&#xff0c;进而排查宕机的原因。这中排查方法…...

python-pip

pip 路径 python 下载后自带pip ,在scripts 下&#xff0c;如 D:\install\python\Scripts numpy pip3 install numpy scipy matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simplepandas D:\install\python\Scripts>pip3 install pandas -i https://pypi.tuna.tsingh…...

无涯教程-Perl - getppid函数

描述 该函数返回父进程的进程ID。 语法 以下是此函数的简单语法- getppid返回值 该函数返回父进程的进程ID。 例 以下是显示其基本用法的示例代码- #!/usr/bin/perl$ppidgetppid();print "Parent Process ID $ppid\n";执行上述代码后,将产生以下输出- Paren…...

AUTOSAR规范与ECU软件开发(基础篇)1.2 汽车电子控制系统的基本构成

目录 前言 1、 传感器 2、 电子控制单元(ECU) 3、 执行器 前言 汽车电子控制系统主要由传感器(Sensor) 、 电子控制单元(Electronic Control Unit, ECU) 和执行器(Actuator) 组成(图1.1) ,对被控对象(Controlled Object)...

一个可以通过多个条件筛选的系统界面是如何实现的(springboot+mybatis)

比如我们有一个订单记录管理界面 条件可以通过订单号、商品名称、创建日期范围、价格范围。。。来进行筛选查询。 首先我们先确定数据库订单表&#xff08;我这里就不做连表了&#xff0c;都放在一个表中&#xff09;模拟一个订单表 order表 订单号商品名称创建日期价格地址…...

WebRTC | 实现数据流的一对一通信

目录 一、浏览器对WebRTC的支持 二、MediaStream与MediaStreamTrack 三、RTCPeerConnection 1. RTCPeerConnection与本地音视频数据绑定 2. 媒体协商SDP 3. ICE &#xff08;1&#xff09;Candidate信息 &#xff08;2&#xff09;WebRTC收集Candidate &#xff08;3&…...

基于MATLAB小波变换的信号突变点检测

之前在不经意间也有接触过求突变点的问题。在我看来&#xff0c;与其说是求突变点&#xff0c;不如说是我们常常玩的"找不同"。给你两幅图像&#xff0c;让你找出两个图像中不同的地方&#xff0c;我认为这其实也是找突变点在生活中的应用之一吧。回到找突变点位置上…...

JUC并发编程(JUC核心类、TimeUnit类、原子操作类、CASAQS)附带相关面试题

目录 1.JUC并发编程的核心类 2.TimeUnit&#xff08;时间单元&#xff09; 3.原子操作类 4.CAS 、AQS机制 1.JUC并发编程的核心类 虽然java中的多线程有效的提升了程序的效率&#xff0c;但是也引发了一系列可能发生的问题&#xff0c;比如死锁&#xff0c;公平性、资源管理…...

个人用C#编写的壁纸管理器 - 开源研究系列文章

今天介绍一下笔者自己用C#开发的一个小工具软件&#xff1a;壁纸管理器。 开发这个小工具的初衷是因为Windows操作系统提供的功能个人不满意&#xff0c;而且现在闲着&#xff0c;所以就随意写了个代码。如果对读者有借鉴参考作用就更好了&#xff0c;能够直接代码段复用即可。…...

iTextSharp 生成PDF

示例代码定义了一个名为PdfController的API控制器&#xff0c;其中的GeneratePdf方法创建了一个新的PDF文档&#xff0c;并将内容添加到文档中。最后&#xff0c;将文档内容转换为字节数组&#xff0c;并通过File方法返回给前端。 注意&#xff0c;你需要在你的项目中添加对iT…...

基于微信小程序的传染病酒店隔离平台设计与实现(Java+spring boot+MySQL+微信小程序)

获取源码或者论文请私信博主 演示视频&#xff1a; 基于微信小程序的传染病酒店隔离平台设计与实现&#xff08;Javaspring bootMySQL微信小程序&#xff09; 使用技术&#xff1a; 前端&#xff1a;html css javascript jQuery ajax thymeleaf 微信小程序 后端&#xff1a;…...

vue3中用watch监听响应式数据的注意点

如果你在vue3中使用reactive()方法创建响应式数据&#xff0c;然后又用torefs()方法将响应式数据解构成单一的ref响应式数据。 此时&#xff0c;如果你想用watch监听解构出来单一的响应式数据&#xff0c;watch不起作用。 此时&#xff0c;你需要用watch监听之前的reactive()…...

Jmeter(五) - 从入门到精通 - 创建网络计划实战和创建高级Web测试计划(详解教程)

1.简介 上一篇中已经将其的理论知识介绍了一下&#xff0c;这一篇就带着大家一步一步的把上一篇介绍的理论知识实践一下&#xff0c;然后再说一下如何创建高级web测试计划。 2.网络计划实战 通过上一篇的学习&#xff0c;将其分类为&#xff1a; &#xff08;1&#xff09;不需…...

【单片机】51单片机,TLC2543,驱动程序,读取adc

TLC2543 是一款 12 位精密模数转换器 (ADC)。 1~9、11、12——AIN0&#xff5e;AIN10为模拟输入端&#xff1b; 15——CS 为片选端&#xff1b; 17——DIN 为串行数据输入端&#xff1b;&#xff08;控制字输入端&#xff0c;用于选择转换及输出数据格式&#xff09; 16——…...

誉天HCIE-Cloud_Computing3.0课程简介

课时&#xff1a;60 第一天 1. 华为云 Stack 解决方案及架构介绍 3. 华为云 Stack 的安装流程解析及规划设计 4. 华为云 Stack 的网络平面的规划解析 5. 华为云 Stack Deploy 部署工具的安装&#xff0c;配置&#xff0c;创建工程&#xff0c;下载 LLD 表 6. 华为云 Stack 的 …...

Unity之ShaderGraph 节点介绍 Procedural节点

程序化 噪声Gradient Noise&#xff08;渐变或柏林噪声&#xff09;Simple Noise&#xff08;简单噪声&#xff09;Voronoi&#xff08;Voronoi 噪声&#xff09; 形状Ellipse&#xff08;椭圆形&#xff09;Polygon&#xff08;正多边形&#xff09;Rectangle&#xff08;矩形…...

期权定价模型系列【1】—BSM通用式模型

这是期权定价模型专栏的第一篇文章&#xff0c;此专栏旨在分享一些期权定价模型&#xff0c;将会从最基础的BSM模型开始写起&#xff0c;逐步扩散到蒙特卡洛模拟、二叉树等数值法模型&#xff0c;以及跳跃扩散模型、随机波动率模型&#xff0c;神经网络模型等等。 如果你觉得有…...

HA3 SQL样本实验:一种混合计算查询的全新样本解决方案

作者&#xff1a;陆唯一(芜霜) HA3&#xff08;对外开源代号&#xff1a;Havenask &#xff09;是阿里智能引擎团队自研的大规模分布式检索系统&#xff0c;广泛应用于阿里内部的搜索业务&#xff0c;是十多年来阿里在电商领域积累下来的核心竞争力产品。Ha3 SQL 是在原有Ha3引…...

Linux(Web与html)

域名 DNS与域名&#xff1a; 网络是基于tcp/ip协议进行通信和连接的 tcp/ip协议是五层协议&#xff1a;应用层–传输层—网络层----数据链路层----物理层每一台主机都有一个唯一的地址标识&#xff08;固定的ip地址&#xff0c;用于区分用户和计算机。 ip地址&#xff1a;由…...

SpringBoot 底层机制分析[上]

文章目录 分析SpringBoot 底层机制【Tomcat 启动分析Spring 容器初始化Tomcat 如何关联Spring 容器】[上]搭建SpringBoot 底层机制开发环境Configuration Bean 会发生什么&#xff0c;并分析机制提出问题&#xff1a;SpringBoot 是怎么启动Tomcat &#xff0c;并可以支持访问C…...

忍者像素绘卷开源可部署实践:私有云部署+API网关安全加固方案

忍者像素绘卷开源可部署实践&#xff1a;私有云部署API网关安全加固方案 1. 项目概述与技术特点 忍者像素绘卷是一款基于Z-Image-Turbo深度优化的图像生成工作站&#xff0c;专为像素艺术创作设计。它融合了16-Bit复古游戏美学与现代AI图像生成技术&#xff0c;为创作者提供了…...

自动化测试中的“等待”策略:聪明地等待,而不是傻等

一、为什么等待策略是自动化测试的命脉 在自动化测试中&#xff0c;等待策略直接决定脚本的稳定性和执行效率。当测试代码以毫秒级速度运行时&#xff0c;浏览器渲染、网络请求和异步加载往往需要秒级响应。若缺乏合理的等待机制&#xff0c;将引发三大致命问题&#xff1a; 元…...

别再只画静态图了!用Qt QChart实现可交互波形图的5个高级技巧

别再只画静态图了&#xff01;用Qt QChart实现可交互波形图的5个高级技巧 在数据可视化领域&#xff0c;静态图表已经无法满足现代应用对用户体验的严苛要求。想象一下&#xff0c;当用户面对一个温度监测系统时&#xff0c;如果只能被动地观看一条固定不变的曲线&#xff0c;而…...

C#怎么使用ArraySegment和切片 C#如何用Range和Index对数组和字符串进行切片操作【语法】

<p>ArraySegment 是仅记录起始位置和长度的数组视图&#xff0c;不复制数据、无内存安全检查&#xff0c;越界不抛异常&#xff1b;Range/ Index 是 C# 8.0 语法糖&#xff0c;依赖类型实现对应索引器&#xff0c;字符串切片需防代理对越界。</p>ArraySegment 不是…...

OpenClaw人人养虾:对话模式

Talk Mode&#xff08;对话模式&#xff09;是 OpenClaw 的实时语音交互功能&#xff0c;让你可以像和真人对话一样与 Agent 进行语音沟通。启动对话模式openclaw node --type audio --talk快速启动对话模式会自动启用音频节点的 STT 和 TTS 功能&#xff0c;无需单独配置。对话…...

VisionPro图像掩膜进阶技巧:3步优化PMAlign工具匹配准确率(附真实案例)

VisionPro图像掩膜进阶技巧&#xff1a;3步优化PMAlign工具匹配准确率&#xff08;附真实案例&#xff09; 在精密视觉检测领域&#xff0c;PMAlign工具的准确率直接决定了整个系统的可靠性。上周在调试某半导体晶圆检测项目时&#xff0c;遇到一个典型问题&#xff1a;当检测图…...

《QMT量化实战系列》多因子策略进阶:动态权重调优与回测验证,年化收益再突破

1. 多因子策略的动态权重调优原理 我第一次接触动态权重调优时&#xff0c;就像发现了一个新大陆。传统的多因子策略就像给每个因子固定分配座位&#xff0c;而动态调优则是让这些因子根据市场环境自动调整位置。想象你在管理一支篮球队&#xff0c;固定权重就像让中锋永远站在…...

emGUI:嵌入式轻量级Widget GUI框架解析

1. 项目概述 ESP8266 emGUI 是一款专为资源受限嵌入式平台设计的轻量级 C 语言图形用户界面&#xff08;GUI&#xff09;库&#xff0c;其核心目标并非替代成熟的 GUI 框架&#xff08;如 LVGL 或 TouchGFX&#xff09;&#xff0c;而是提供一套高度可裁剪、零依赖、可深度集成…...

STM32G474的COMP比较器,除了保护电路还能这么玩?一个LED灯搞定电压监测

用STM32G474的COMP比较器玩转电压监测&#xff1a;一个LED灯就够了 在嵌入式开发中&#xff0c;我们常常需要监测电压变化&#xff0c;比如电池电量、传感器输出等。传统做法是使用ADC采样&#xff0c;然后通过软件判断阈值。但这种方法需要占用CPU资源&#xff0c;响应速度也受…...

用phpstudy在Win11上快速搭建DVWA:一个视频+这篇图文就够了

Win11下DVWA靶场极速搭建指南&#xff1a;phpstudy全流程详解与避坑手册 每次在本地搭建渗透测试环境时&#xff0c;最头疼的就是各种组件的版本冲突和配置问题。直到发现了phpstudy这个神器&#xff0c;配合DVWA靶场&#xff0c;终于能实现一键式部署。本文将带你用最简洁的步…...