zlog改进建议,日志系统是否需要是异步多进程架构?

难易 发布于 2012/05/28 11:32
阅读 3K+
收藏 2

这是我收到的一封关于zlog的来信,我把来信及回答贴出来供大家参考

——————————

难易兄弟,
   您好,最近下载了您开发的zlog日志函数库,进行了试用,感觉不错。但是我觉
得可能有些地方值得改进,
我们在unix类操作系统下开发的软件,很可能是多进程并发的,如果进程比较多(我
用test_press运行300个进程,每个写5000条日志,发现用了1分30多秒)时,就比较
慢,且是大多数进程运行完都需要1分多钟,比较重要的原因是,每个进程都以append
方式打开那个日志文件来写。
   我们是否可以换给思路来考虑,启用一个专门的写日志到文件的进程,而其他工
作进程只将日志写到共享内存或者消息队列里,这样工作进程的操作速度应该会快很

多。


——————————

 

你好,谢谢你对zlog的关注!


关于测试是这样的:

这是在我的机器上测试的结果,
$ time ./test_press_zlog 300 5000 
real 0m9.465s
user 0m8.500s
sys 0m9.570s

我机器的CPU是,ubuntu操作系统
Intel(R) Core(TM)2 Duo CPU     P8700  @ 2.53GHz
我猜测你的系统是某种嵌入式操作系统吧?

测试程序test_press跑了1分多种,实际上是等待所有的子进程都结束的时间,单个进程其实是不需要这么多时间的
可以在press.log里面试着grep某个进程的pid,看看第一条日志和最后日志的时间差。

-----------

关于方案是这样的:

你的方案很好,其实我也考虑过,但是在权衡下我还采用了写文件的做法
因为如果单开一个写日志的进程,然后再在这个进程前面放共享内存或者消息队列,那么写日志就变成了一个复杂的需要进程间数据交换的系统,

需要解决下面几个问题:

1.用什么ipc,ipc的效率会高吗?
     共享内存没有消息互斥,锁定功能,需要自己实现。
     消息队列有大小限制。
     unix域套接字没有这些问题,但效率较低,实际上,syslog就是通过/dev/log这个unix本地域套接字来通信的,但实际测下来,当有多个进程同时往这个套接字写数据的时候,速度只会更加慢,瓶颈在域套接字和写日志的进程上,反而不如直接写文件。

2.可靠性问题如何保证?
     多个进程交换数据,你不能保证所有进程都能一定正常工作,一个系统经过的步骤越多,那么出错的可能性就越大,万一写日志的进程挂了,那么所有的日志都不会写出来。而对于一个日志库来说,这种错误是致命的。其他系统都等着从日志里面找出错误的原因,而日志系统本身如果是脆弱的话,如何保证可靠?所以越简单的做法,直接写文件,是最可靠的保留进程活动情况的方法。可能这不是最有效率的做法,但我认为是最可靠的做法。

3.其他的日志函数库,如何达到高效率?(当然这一定是牺牲某种可靠性为前提的)
这里我要推荐一下log4cplus,  http://log4cplus.sourceforge.net/projstatus.html, 我的竞争对手(也是我认为c++最靠谱的日志库)
呵呵, 不过他们是用C++写的,你可以试试能不能在你们的环境下用c程序来链接c++的库,如果可以的话可以试试这个库
他们的解决方案是 AsyncAppender,异步写文件的appender,或许会速度快一点,我没有研究

4.实际上,我推荐的方案是
   在开发的时候无所谓效率,完全可以把所有日志都写到文件中
   在生产时,把日志同时分两种方式输出:
    1.warn或error及以上级别的日志直接写入本地文件,追求高可靠性。
    2.info级别及以上的日志(包括warn,error等),通过某种异步的消息方式(高效率),送到某个集中日志管理系统,这是为了集中管理及监控查错。

--------

zlog将如何发展:

目前我正在编写zlog 1.0 版,估计这两周就能发布。
zlog把自身定位为一个简单的日志库,

1.不会采用log4j系列的模型而是syslog的模型。
2.基本上内置的输出只有syslog,管道,和文件。
3.但是将会提供扩展,允许用户自己个输出函数嵌入,这样就能充分发挥用户的主观能动性,并能解决我上面第4点提出的方案。并且异步的进程间通信方式,在posix系统下并无较好的一致的规范,所以把这个输出函数交给用户来实现是合适的。这样,zlog只需要专注于日志本身的分类过滤及格式化。这也是符合unix操作系统的设计哲学的:一个工具把一件事情做好,复杂的功能通过工具组合来实现。

加载中
0
clonne
clonne

换个思路,为什么写日志就一定要和文件打交道?

我建议所有的日志操作在内存中进行,只在必须读写文件时才操作文件(文件最好是顺序读写,一次读写。频繁的读写会降低很多效率,因为绝大部分时间都浪费在磁盘读写中。),或者,根本就不需要操作文件,以一个内存映射文件作为日志更好。

“一个工具把一件事情做好,复杂的功能通过工具组合来实现。”这倒是对的。不过你至少需要提供性能优化的接口能让该库的使用者自行优化(就是说,把文件、日志的内存管理或者其他能分离的都运行日志库的使用者自己提供,日志库仅提供最基本最核心的功能,当然,是可选择的)

0
难易
难易

引用来自“clonne”的答案

换个思路,为什么写日志就一定要和文件打交道?

我建议所有的日志操作在内存中进行,只在必须读写文件时才操作文件(文件最好是顺序读写,一次读写。频繁的读写会降低很多效率,因为绝大部分时间都浪费在磁盘读写中。),或者,根本就不需要操作文件,以一个内存映射文件作为日志更好。

“一个工具把一件事情做好,复杂的功能通过工具组合来实现。”这倒是对的。不过你至少需要提供性能优化的接口能让该库的使用者自行优化(就是说,把文件、日志的内存管理或者其他能分离的都运行日志库的使用者自己提供,日志库仅提供最基本最核心的功能,当然,是可选择的)

因为只有文件是安全可靠的阿。内存只要一掉电,就灰灰了。

zlog的操作就是在内存里面进行的,并且基本是单条日志一次成形,然后写到文件。这样即使在最坏的情况下,机器挂掉了,最多损失一条日志(这是不可避免的,即使程序自己写文件,也是如此)。如果把几百条日志都缓存在内存里面,速度是快了,但有可靠性的问题。

当然,现在流行redis这样的数据结构服务器,在集群情况下能既可靠又高速,但这种是用来放业务数据的。redis程序自己的运行还是需要写日志,用来查错。其他程序也是一样。

任何日志的操作都要考虑可靠性和速度。以前我以为写tcp的速度比文件快,后来测试的结果发现本地文件的速度其实比tcp、管道等都要快,并能保证可靠性。当然,我也开放了接口,让用户能挂接自己的输出函数。

难易
难易
没有偏差,所谓的其他线程通过消息队列,其实是通过/dev/log这个unix域套接字
难易
难易
目前我基本上找不出问题。zlog总体还是用于解决C程序写本地日志文件的,如果可能,我希望能实现zlog-redis的挂载包,让zlog通过某种方式实现集中日志系统。
刘畅1987
刘畅1987
还有一点,似乎你把zlong的各种优点都有罗列,不知道,现阶段zlog还存在的问题有那些,能说说吗?
刘畅1987
刘畅1987
弱弱地问下,我见有的地方说,” syslog的做法,建立一个监听线程专门负责该文件写入,其他线程通过向该线程发送消息队列来写入数据。“ 和你上面说的 “ syslog就是通过/dev/log这个unix本地域套接字来通信的 ” 这点上是否有偏差,能给小弟解释下吗?
返回顶部
顶部