在用C编写的服务器中,最有效的文件记录是什么?

时间:2011-01-11 14:02:43

标签: c logging

我想知道用C编写的服务器中最有效的文件记录策略是什么?

我可以看到以下选项:

  • fopen()追加然后fwrite()表示1小时的时间范围内的数据,然后是fclose()?

  • 缓存数据然后偶尔打开()追加write()和close()?

4 个答案:

答案 0 :(得分:2)

为什么不在事件发生时直接记录您的数据?

  • 如果您的服务器崩溃,您希望在崩溃时检索这些数据。如果您每小时只刷新一次缓冲日志,那么您将错过有趣的日志。
  • 文件流通常由操作系统缓冲。

如果您认为由于硬盘写入而导致服务器速度变慢,您可能会考虑登录单独的线程。但我想知道这是不是问题。过早的优化?

答案 1 :(得分:2)

使用线程通常是一个很好的解决方案,我们采用了有趣的结果 需要记录的主线程准备日志字符串并将其传递给第二个线程。为了提供第二个线程,我们使用无锁队列+循环存储器,以便最小化alloc / free和等待时间 secon线程等待无锁队列可用。当它发现有一些工作要做时,会消耗无锁队列的新插槽并记录数据 使用单独的线程可以节省大量时间。

在我们决定使用secon线程后,我们不得不面对另一个问题。同一程序的许多问题(全文搜索引擎)必须在同一文件上记录所有内容,以便在服务器的每个实例之间定期共享资源。 我们可以决定使用信号量或其他同步方法,但我们找到了另一种解决方案:第二个线程将UDP数据包发送到侦听已知端口的本地日志服务器。此服务器读取每条消息并将其记录在文件中(服务器实际上是唯一一个在写入文件时拥有该文件的服务器)。 UDP套接字本身授予日志序列化。

我已经使用这个解决方案超过10年了,从来没有丢失我的日志文件的一行,使用第二个线程我也为每个操作节省了很大一部分时间(我们用来记录大量信息对于服务器接收的任何单个命令。)

HTH

答案 2 :(得分:2)

除非您已进行基准测试并发现它是瓶颈,否则请使用fopenfprintf。没有理由将自己的复杂缓冲层置于顶部,除非stdio对您来说太慢(如果它太慢,您可能会考虑是否重新考虑您的服务器正在运行的OS / C库)。

答案 3 :(得分:1)

编写系统日志的最慢部分是对物理磁盘的输出操作。

必须对日志记录进行缓冲和校验和,以确保您不会丢失任何日志数据,并且事后分别无法篡改日志数据。