2012-01-16 230 views
4

我正在构建一个日志记录系统,它将记录请求并响应分布在多个应用程序节点上的Web服务。我正在考虑使用MongoDB作为存储库并实时登录,或者在x次请求后更真实地将日志转储到数据库。该应用程序的设计是相当高的量,并建立在Perl。有没有人有这样的经验?建议?或者这是否定的?MongoDB日志记录

回答

1

我已经在一个运行在两个应用程序服务器上的webapp上完成了这项工作。在mongodb中写入默认情况下是非阻塞的(java驱动程序只是为您获取请求并立即返回,我认为它与perl相同,但您最好检查一下),因为您不想要您的用户等待记录日志。

这样做的缺点是,在某些故障情况下,您可能会丢失一些日志(例如,在mongo获取数据之前,您的应用程序失败)。

+0

大。你在做实时记录吗?您的日志记录服务器如何负载密集? – MadHacker 2012-01-17 04:01:41

3

我见过很多公司都在使用MongoDB来存储日志。它的无模式对于应用程序日志非常灵活,在这种日志中架构往往会随时间变化。此外,它的Capped Collection功能非常有用,因为它会自动清除旧数据以保持数据适合内存。

人们通过正常分组或聚合MapReduce来聚合日志,但速度并不快。特别是MongoDB的MapReduce只能在一个线程内工作,并且其JavaScript执行开销很大。 New aggregation framework可以解决这个问题。

另一个问题是高通写。尽管默认情况下MongoDB的插入方式是“即忘即忘”风格,但调用大量insert命令会导致严重的写入锁争用。这可能会影响应用程序性能,并阻止读者聚合/筛选存储的日志。

一种解决方案可能使用日志收集器框架,如FluentdLogstashFlume。这些守护进程应该在每个应用程序节点上启动,并从应用程序进程获取日志。

fluentd plus mongodb

他们缓冲日志和异步写入数据至其他系统,如MongoDB的/ PostgreSQL的/等写入分批进行,所以这是一个很大比直接从应用程序编写效率更高。该链接描述了如何将日志从Perl程序放入Fluentd中。

0

为您的应用程序的一些有趣的想法,我建议检查出Graylog2,如果你还没有准备好。他们相当有效地结合使用了MongoDB和Elasticsearch。在组合中添加强大的搜索引擎可以为您提供一些有趣的查询和分析选项。

仅供您参考,以下是专门用于记录处理工具和技术的Elasticsearch page

如果您打算在处理之前排队日志条目(我会推荐),我建议Kestrel作为一个固定的消息队列选项。这就是Gaug.es所使用的,最近我一直在通过它。一个Java应用程序,它非常快速和原子化,它可以方便地说出Memcache协议。这是一种横向扩展的好方法,并且内存缓存备份到一个日记文件中,以实现速度和耐用性的良好平衡。

2

我通过Log::Dispatch::MongoDB在多个应用中使用它;奇迹般有效!

# Declaration 
use Log::Dispatch; 
use Log::Dispatch::MongoDB; 
use Log::Dispatch::Screen; 
use Moose; 

has log => (is => 'ro', isa => 'Log::Dispatch', default => sub { Log::Dispatch->new }, lazy => 1) 

... 

# Configuration 
$self->log->add(
    Log::Dispatch::Screen->new(
     min_level => 'debug', 
     name  => 'screen', 
     newline  => 1, 
    ) 
); 
$self->log->add(
    Log::Dispatch::MongoDB->new(
     collection => MongoDB::Connection->new(
      host => $self->config->mongodb 
     )->saveme->log, 
     min_level => 'debug', 
     name  => 'crawler', 
    ) 
); 

... 

# The logging facility 
$self->log->log(
    level => 'info', 
    message => 'Crawler finished', 
    info => { 
     origin => $self->origin, 
     country => $self->country, 
     counter => $self->counter, 
     start => $self->start, 
     finish => time, 
    } 
); 

而且这里距离capped collection一个样本记录:

{ 
    "_id" : ObjectId("50c453421329307e4f000007"), 
    "info" : { 
      "country" : "sa", 
      "finish" : NumberLong(1355043650), 
      "origin" : "onedayonly_sa", 
      "counter" : NumberLong(2), 
      "start" : NumberLong(1355043646) 
    }, 
    "level" : "info", 
    "name" : "crawler", 
    "message" : "Crawler finished" 
}