您的位置:首页 > 编程语言 > C语言/C++

基于C++高性能、跨平台日志模块的分析与实现

2015-12-20 22:35 811 查看
很久没有写博客了,大概一年多的时间。当然部分原因是由于工作太忙,当然主要原因还是自己变的懒散了,哈哈。

在这一年多里有过不少思考,除去之前的原因,没有坚持跟大家分享是自己觉得之前的文章太过浅显,直到最近,

积累了一些东西,才有了和大家分享想法。之后我会坚持跟大家分享自己学习和思考后的成果。

这篇文章我想说一下关于C++高性能日志模块的设计和实现。

日志功能相信是每个有点规模的软件系统必须的模块,我认为日志功能非常重要,一个成熟高性能的C++日志模块需要具备以下几点:

1. 效率高

我们知道,日志最终是要写到磁盘文件的,不论是写到本地磁盘还是远程机器的磁盘,这个过程都少不了磁盘IO。如果想把日志通过网络发送到远端的机器,还要经历网络IO这个过程,IO操作是非常耗时的。所以我想说的是一个日志的性能必须要轻松跑满磁盘的IO带宽(100+M/s)

2. 支持多日志级别,且设置方便

日志级别要灵活,一般日志起码的级别至少分为六到七级,每个级别分别代表不同的意思。并且允许用户可以任何时间随意调整日志级别,比如调试级别,跟踪级别,系统错误级别等,举个例子来说明设置日志级别的必要性,如果我的程序级别设置为系统错误级别,那么程序会同时记录日志并把日志内容打印到终端。

3. 日志文件滚动

一般要求严格的软件系统要求能够7X24小时运行(如金融交易系统和大型设备的控制系统),这个过程中随时可以产生大量的日志,这时候就需要滚动日志文件,比如每个日志文件满10M字节就会重新滚动创建新的日志文件,避免过大的日志文件查看起来不太方便。

4. 多日志模式(同步日志和异步日志)

同步日志模式说的就是代码里每一条日志都会产生一次磁盘IO,换句话说就是每条日志写一次文件,无疑这种方式在需要记录大量日志的软件系统并对系统的实时性要求较高的软件系统是有很大影响的,比如我一个线程需要一直记录一段时间的日志,这个时候磁盘IO就会成为我们软件系统的瓶颈,导致软件执行效率变低。这是同步日志的缺点,当然同步日志模式也有它的优点,优点就是能保证每条打印的日志都能够记录到文件里,后面我们说了异步日志的模式之后再来说同步日志的优点,相信那时候理解起来更加容易。

异步日志模式一般分为前端和后端,前端每条日志的信息不是直接写日志文件,而是把前端日志信息先存放到一块缓冲区中,后端有专门的写日志的线程,负责将这个缓冲区的日志信息写到文件中,这样通过可以避免每条日志一次磁盘IO,提高了效率。相对于同步日志模式来说就是效率很高,但是异步日志模式的缺点就是当系统crash的时候,缓冲区里可能还留有日志信息,这个时候就相当于丢了最后的很多日志信息,不利于系统问题定位。当然同步日志模式就不存在这个问题,因为同步日志模式每条日志信息都会记录到日志文件,才会进行下一次日志。

这两种模式有利有弊,在使用的过程中要根据软件系统的情况灵活选择,比如说我软件系统很稳定,而且需要高性能的日志,这个时候理应选择异步模式。而当我系统软件不太稳定,而且日志量并不大,这个时候可以选择同步日志方式,记录没一条日志信息,来帮助我们进行问题的定位。当然同步异步日志模式的设置也要非常方便。

5. 多日志方式(本地磁盘日志,远程网络日志)

这个日志方式跟上面的日志模式不要混淆了,这里的日志方式说的是日志内容是存储到本地磁盘文件还是通过网络发送到远程的机器并记录到远程机器的磁盘文件中。而日志模式说的是用同步的方法记录日志还是用异步的方法记录日志。

如果是记录日志到本地磁盘就直接将日志内容按照上面的日志模式记录到本地磁盘文件,如果是通过网络Tcp/Ip记录日志到远程机器的磁盘文件,那么这个时候远程的机器还需要运行一个记录日志的Tcp/Ip服务器,本地日志模块是日志的客户端,负责将日志信息发送到远程服务器,远程服务器收到相应的日志信息记录到本地磁盘文件。这里面涉及到的东西有点多,日志服务器需要支持多日志客户端的连接,而且性能要达标。而且日志服务器也需要支持上面的同步写日志文件和异步写日志文件的方式。

6. 跨平台

这个没什么好说的,一个日志不能跨平台(至少支持windows, linux), 而且很容易移植到其他平台, 那么估计用的人也不会多。

我觉得以上几点是一个高性能的日志模块的必要条件,只有具备了以上几点才可能称得上是一个高性能日志系统。之前公司的日志系统比较乱,而且效率不高,导致整个软件系统日志量过大就会不稳定。日志这种基本模块可能比一般的业务逻辑更加难写,需要考虑的东西更多,所以也是考察一个程序员基本功的很重要的点。

以上最难实现的可能是第五点中的远程网络日志方式,因为远程网络日志需要一个远程网络日志服务器,这个日志服务器如果需要支持大量的日志客户端连接,那么就涉及到高性能服务端网络编程,这里面当然也会涉及到很多知识。目前我实现的日志服务器仅仅是每个客户端对应一个线程这种one thread per connection 网络编程模型,这样实现当并发量上去之后,肯定是满足不了需求的,后面我会实现一套基于事件驱动模型(reactor)的网络日志服务器,类似于基于c开发的libevent,
nginx,基于c++的作者陈硕的muduo,java的netty,python的twisted那种支持高并发的网络框架。这个框架我目前正在开发中,已经初步完成一版。

基于以上几点我实现了一个基本的日志模块,准备将其开源出来,最初我考虑使用c++11实现日志模块,当时没有考虑到第五条的远程网络日志的日志方式,所以仅仅只是实现了一个日志模块的客户端,只支持本地日志,github地址是:https://github.com/kevin-shanghai/Log_Cpp11,我是在vs2013和g++4.9上编译测试的。

后来考虑到c++11目前可能并不是很普及,用的人可能不多,所以我又用c++98重写了一次,并实现了上面的远程日志功能,github地址是:https://github.com/kevin-shanghai/Logging_Cpp98
在vs2010上测试通过,不过这个我没有再linux上测试,后面有空我会移植到linux,我没有使用过多的独立平台的api和系统调用,所以移植的工作量应该不大。由于水平有限,还请见谅,当然代码也是业余时间折腾出来的,没有经过充分的测试,相信也有不少bug,如果遇到任何问题,请给我写邮件。

我的邮件地址是:fuliangcheng1985@126.com或者kevinfu1985@gmail.com

作者:三儿

转载请注明出处
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ Log 高性能 跨平台