玩转mongodb(九):通过log4jmongo来实现分布式系统的日志统一管理

背景

  在分布式系统中,我们有多个web app,这些web app可能分别部署在不同的物理服务器上,并且有各自的日志输出。当生产问题来临时,很多时候都需要去各个日志文件中查找可能的异常,相当耗费人力。日志存储多以文本文件形式存在,当有需求需要对日志进行分析挖掘时,这个处理起来也是诸多不便,而且效率低下。

  为了方便对这些日志进行统一管理和分析,我们可以将日志统一输出到指定的数据库系统中,再由日志分析系统去管理。由于这里是mongodb的篇章,所以主观上以mongodb来做日志数据存储;客观上,一是因为它轻便、简单,与log4j整合方便,对系统的侵入性低。二是因为它与大型的关系型数据库相比有很多优势,比如查询快速、bson存储结构利于扩展、免费等。

解决方案

整合mongodb和log4j

1、安装mongodb数据库,并在本地启动,默认端口是27017,详细请参考:玩转mongodb(一):初识mongodb

2、新建一个maven(maven版本要求3.0以上)工程,选择maven-archetype-quickstart,工程名:log4j2mongo

3、在pom.xml文件中,添加log4j、log4mongo-java、mongo-java-driver三个依赖。具体代码如下:

 1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 2   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 3   <modelVersion>4.0.0</modelVersion>
 4
 5   <groupId>com.manyjar</groupId>
 6   <artifactId>log4j2mongo</artifactId>
 7   <version>0.0.1-SNAPSHOT</version>
 8   <packaging>jar</packaging>
 9
10   <name>log4j2mongo</name>
11   <url>http://maven.apache.org</url>
12
13   <properties>
14     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
15     <junit.version>3.8.1</junit.version>
16     <log4j.version>1.2.17</log4j.version>
17     <log4mongo.version>0.7.4</log4mongo.version>
18     <mongo-java-driver.version>2.8.0</mongo-java-driver.version>
19   </properties>
20
21   <dependencies>
22     <dependency>
23       <groupId>junit</groupId>
24       <artifactId>junit</artifactId>
25       <version>${junit.version}</version>
26       <scope>test</scope>
27     </dependency>
28
29       <dependency>
30           <groupId>log4j</groupId>
31           <artifactId>log4j</artifactId>
32           <version>${log4j.version}</version>
33       </dependency>
34
35       <dependency>
36           <groupId>org.log4mongo</groupId>
37           <artifactId>log4mongo-java</artifactId>
38           <version>${log4mongo.version}</version>
39       </dependency>
40
41       <dependency>
42           <groupId>org.mongodb</groupId>
43           <artifactId>mongo-java-driver</artifactId>
44           <version>${mongo-java-driver.version}</version>
45       </dependency>
46   </dependencies>
47 </project>

pom.xml

4、在resources文件夹中,添加log4j.properties文件。文件中主要添加log4j对mongodb的适配器org.log4mongo.MongoDbAppender。这里的适配器是log4mongo-java这个jar包提供。mongodb数据库的ip:127.0.0.1,port:27017,库名:logs,集合名:log。具体配置如下:

 1 log4j.rootLogger=DEBUG,MongoDB
 2 log4j.appender.MongoDB=org.log4mongo.MongoDbAppender
 3 log4j.appender.MongoDB.databaseName=logs
 4 log4j.appender.MongoDB.collectionName=log
 5 log4j.appender.MongoDB.hostname=127.0.0.1
 6 log4j.appender.MongoDB.port=27017
 7
 8 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
 9 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
10 log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n

log4j.properties

5、在java文件夹中,com.manyjar.log4j2mongo这个包中,添加Main.java文件,观察文件中的代码可以发现,和我们平时用log4j来写日志一模一样,把日志流到mongodb这件事情,对业务开发的程序员完全透明。具体代码如下:

 1 package com.manyjar.log4j2mongo;
 2
 3 import org.apache.log4j.Logger;
 4
 5 import com.mongodb.BasicDBObject;
 6 import com.mongodb.DBObject;
 7
 8 public class Main {
 9
10     public static void main(String[] args) {
11         Logger logger = Logger.getLogger(Main.class);
12
13             for (int i = 0; i < 10000000; i++) {
14                 DBObject bson = new BasicDBObject();
15                 bson.put("name", "ryan"+i);
16                 logger.debug(bson);
17             }
18     }
19 }

Main.java

6、步骤5中,我们执行了1000万次的日志插入,数据结构如下:

默认的数据量大小有10G:

这里,我们可以看到,日志的数据存储量相对不小。如果需要修改日志数据的存储结构,可以用log4mongo的源代码进行二次开发。

如果数据量过大,我们可以用TTL索引(过期自动删除)或固定集合大小两种方式来解决:

TTL索引:db.log_events.createIndex({"timestamp": 1},{expireAfterSeconds: 60*60*24*30}) #1个月后过期后删除

将log集合修改成固定大小集合:db.runCommand({"convertToCapped":"log",size:10000})。

时间: 2024-12-31 05:17:17

玩转mongodb(九):通过log4jmongo来实现分布式系统的日志统一管理的相关文章

Java-Shiro(九):Shiro集成Redis实现Session统一管理

声明:本证项目基于<Java-Shiro(六):Shiro Realm讲解(三)Realm的自定义及应用>构建项目为基础. 在实际应用中使用Redis管理Shiro默认的Session(SessionManager)是必要的,因为默认的SessionManager内部默认采用了内存方式存储Session相关信息():当配置了内部cacheManager时(默认配置采用EhCache--内存或磁盘缓存),会将已经登录的用户的Session信息存储到内存或磁盘.无论是采用纯内存方式或者EhCach

玩转mongodb(四):细说插入、更新、删除和查询

插入: 使用insert或save方法想目标集合插入一个文档: db.person.insert({"name":"ryan","age":30}); 使用batchInsert方法实现批量插入,它与insert方法非常类似,只是它接受的是一个文档数组作为参数.一次发送数十,数百乃至数千个文档会明显提高插入的速度. db.person.batchInsert([{"name":"ryan","ag

玩转mongodb(五):mongodb 3.0+ 查询性能分析

mongodb性能分析方法:explain() 为了演示的效果,我们先来创建一个有200万个文档的记录.(我自己的电脑耗了15分钟左右插入完成.如果你想插更多的文档也没问题,只要有耐心等就可以了.) 1 for(var i=0;i<2000000;i++){ 2 db.person.insert({"name":"ryan"+i,"age":i}); 3 } MongoDB 3.0之后,explain的返回与使用方法与之前版本有了很大的变化

玩转mongodb(二):mongodb基础知识

常用基本数据类型: null null用于表示空值或者不存在的字段: {"data":null} 布尔型 布尔类型只有两个值,true和false: {"data":true}.{"data":false} 字符串 字符串类型的数据是由UTF-8字符组成: {"data":"pingan"} 正则表达式 查询时,使用正则表达式作为限定条件,语法和javascript的正则表达式一样: {"data

MongoDB (九) MongoDB 投影

mongodb 投影意思是只选择必要的数据而不是选择一个文件的数据的整个.如果一个文档有5个字段,需要显示只有3个,然后选择其中只有3个字段. find() 方法 MongoDB 的find()方法,在 MongoDB查询 文档解释接受第二个可选参数是要检索的字段列表.在MongoDB中,当执行find()方法,那么它会显示一个文档所有字段.要限制这一点,需要设置的字段列表值1或0. 1用来显示字段而0是用来隐藏字段. 语法: find()方法具有投影基本语法如下 >db.COLLECTION_

易宝典文章——玩转Office 365中的Exchange Online服务 之十三 怎样管理Exchange Online的邮件用户和联系人

在前面文章的描述过程中,提到了这样两个概念--联系人和组.接下来,就专门来讲关于Exchange Online的收件人对象的问题.对于Exchange Online来讲,所有能够接收邮件的对象都叫做收件人对象,它们具有一个共同的特点就是都具有邮件地址.虽然这些对象在Exchange Online中都具有邮件地址但不一定都有用于存储邮件的邮箱. 邮件用户和联系人就是属于在Exchange Online中只有邮件地址而没有邮箱存储的收件人对象.在ExchangeOnline中创建这类对象的目的,就是

10、《每天5分钟玩转Docker容器技术》学习-Docker命令之本地镜像管理

a) Docker images 命令 docker images : 列出本地镜像. docker images [OPTIONS] [REPOSITORY[:TAG]] -a :列出本地所有的镜像(含中间映像层,默认情况下,过滤掉中间映像层): --digests :显示镜像的摘要信息: -f :显示满足条件的镜像: --format :指定返回值的模板文件: --no-trunc :显示完整的镜像信息: -q :只显示镜像ID. l 实例 查看本地镜像列表. 列出本地镜像中REPOSITO

windows下mongodb基础玩法系列二CURD操作(创建、更新、读取和删除)

windows下mongodb基础玩法系列 windows下mongodb基础玩法系列一介绍与安装 windows下mongodb基础玩法系列二CURD操作(创建.更新.读取和删除) 简单说几句 在mongodb中3元素:db(数据库).collection(集合).document(文档) 其中collection类似于数据库中的表,document类似于行,这样一来我们就将内容对比起来记忆学习了. 数据格式 MongoDB documents是BSON格式(一种类json的一种二进制形式的存

玩转spring boot——properties配置

前言 在以往的java开发中,程序员最怕大量的配置,是因为配置一多就不好统一管理,经常出现找不到配置的情况.而项目中,从开发测试环境到生产环境,往往需要切换不同的配置,如测试数据库连接换成生产数据库连接,若有一处配错或遗漏,就会带来不可挽回的损失.正因为这样,spring boot给出了非常理想的解决方案——application.properties.见application-properties的官方文档:http://docs.spring.io/spring-boot/docs/curr