MongoDB 日志记录

4
我正在构建一个日志系统,用来记录分布在多个应用程序节点的Web服务的请求和响应。我考虑使用MongoDB作为存储库,并实时记录日志,或更现实地说,在x个请求后将日志转储到数据库中。该应用程序旨在处理相当高的数据量,并且是用Perl构建的。有没有人做过类似的事情?有什么建议吗?还是说这是不可行的?
4个回答

3
我看到很多公司在使用MongoDB存储日志。它的无模式架构对应用程序日志非常灵活,因为模式通常会随时间变化而改变。此外,其固定集合功能非常有用,因为它会自动清除旧数据以保持数据适合内存。
人们通过普通分组或MapReduce聚合日志,但速度并不快。特别是MongoDB的MapReduce仅在单个线程内工作,其JavaScript执行开销巨大。新聚合框架可以解决这个问题。
另一个问题是高写入吞吐量。虽然MongoDB的插入默认为fire-and-forget样式,但调用大量插入命令会导致严重的写锁争用。这可能会影响应用程序性能,并防止读取器聚合/过滤存储的日志。
一种解决方案可能是使用日志收集器框架,例如Fluentd, LogstashFlume。这些守护程序应该在每个应用程序节点上启动,并从应用程序进程中获取日志。

fluentd plus mongodb

他们会缓冲日志并异步地将数据写入其他系统,如MongoDB / PostgreSQL等。写入是批处理完成的,因此比直接从应用程序中写入更有效率。此链接描述了如何从Perl程序将日志放入Fluentd中。

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,
    }
);

以下是来自固定集合的示例记录:

{
    "_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"
}

1

我已经在运行于两个应用服务器的Web应用程序上完成了这项工作。 MongoDB的写入默认情况下是非阻塞的(Java驱动程序只会为您获取请求并立即返回,我认为Perl也是如此,但您最好检查一下),这对于此用例非常完美,因为您不希望用户等待记录日志。

这样做的缺点是,在某些故障场景下,您可能会丢失一些日志(例如,在Mongo接收数据之前,您的应用程序崩溃)。


很好。你正在进行实时日志记录吗?你的日志服务器负载有多重? - MadHacker

0

如果你还没有的话,我推荐你看一下Graylog2,这是一些关于你的应用程序有趣思路的建议。他们非常有效地使用了MongoDB和Elasticsearch的组合。将强大的搜索引擎融入其中可以为您提供一些有趣的查询和分析选项。

供你参考,这里是一个Elasticsearch页面专门用于日志处理工具和技术。

如果您计划在处理之前排队日志条目(我建议这样做),我建议您选择一个可靠的消息队列选项Kestrel。这就是Gaug.es所使用的,我最近一直在测试它。这是一个Java应用程序,非常快速和原子性,并且方便地支持Memcache协议。这是横向扩展的好方法,内存缓存备份到一个日志文件中,以实现速度和耐久性的良好平衡。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接