本文将会介绍如何使用 Flume、log4j、Kafka进行规范的日志采集。

Flume 基本概念

Flume是一个完善、强大的日志采集工具,关于它的配置,在网上有很多现成的例子和资料,这里仅做简单说明不再详细赘述。
Flume包含Source、Channel、Sink三个最基本的概念:

Source——日志来源,其中包括:Avro Source、Thrift Source、Exec Source、JMS Source、Spooling Directory Source、Kafka Source、NetCat Source、Sequence Generator Source、Syslog Source、HTTP Source、Stress Source、Legacy Source、Custom Source、Scribe Source以及Twitter 1% firehose Source。

Channel——日志管道,所有从Source过来的日志数据都会以队列的形式存放在里面,它包括:Memory Channel、JDBC Channel、Kafka Channel、File Channel、Spillable Memory Channel、Pseudo Transaction Channel、Custom Channel。

Sink——日志出口,日志将通过Sink向外发射,它包括:HDFS Sink、Hive Sink、Logger Sink、Avro Sink、Thrift Sink、IRC Sink、File Roll Sink、Null Sink、HBase Sink、Async HBase Sink、Morphline Solr Sink、Elastic Search Sink、Kite Dataset Sink、Kafka Sink、Custom Sink。

基于Flume的日志采集是灵活的,我们可以看到既有Avro Sink也有Avro Source,既有Thrift Sink也有Thrift Source,这意味着我们可以将多个管道处理串联起来,如下图所示:

串联的意义在于,我们可以将多个管道合并到一个管道中最终输出到同一个Sink中去,如下图:

上面讲述了Source和Sink的作用,而Channel的作用在于处理不同的Sink,假设我们一个Source要对应多个Sink,则只需要为一个Source建立多个Channel即可,如下所示:

一个Source如果想要输出到多个Sink中去,就需要建立多个Channel进行介入并最终输出,通过上面这几张图,我们可以很好的理解Flume的运行机制,我们在这里也就点到为止,详细的配置可以在官网或者在网上搜索到、查看到。

一般情况下,我们使用 Exec Source对log文件进行监控,这样做确实是比较简单,但是并不方便,我们需要在每一台要监控的服务器上部署Flume,对运维来讲万一目标日志文件发生IO异常(例如格式改变、文件名改变、文件被锁),也是很痛苦的,因此我们最好能让日志直接通过Socket发送出去,而不是存放在本地,这样一来,不仅降低了目标服务器的磁盘占用,还能够有效的防止文件IO异常,而Kafka就是一个比较好的解决方案,具体的架构如下图所示:

由上图可以看到,日志最终流向了两个地方:HBase Persistence和Realtime Processor,而至于为什么不用Kafka直接与Storm进行通信的原因是为了将Sotrm逻辑和日志源通过Flume进行隔离,在Storm中对日志进行简单的分析后,将结果扔进 Rabbit MQ 中供 WEB APP消费。

HBase Persistence就是将原始的日志记录在HBase中以便回档查询,而Realtime Processor则包含了实时的日志统计以及错误异常邮件提醒等功能。

为了能够准确的捕获到异常数据,我们还需要对程序进行一些规范化的改造,例如提供统一的异常处理句柄等等。

日志输出格式

既然打算要对日志进行统一处理,一个统一、规范的日志格式就是非常重要的,而我们以往使用的 PatternLayout 对于最终字段的切分非常的不方便,如下所示:

2016-05-08 19:32:55,572 [INFO ] [main] - [com.banksteel.log.demo.log4j.Demo.main(Demo.java:13)] 输出信息……
2016-05-08 19:32:55,766 [DEBUG] [main] - [com.banksteel.log.demo.log4j.Demo.main(Demo.java:15)] 调试信息……
2016-05-08 19:32:55,775 [WARN ] [main] - [com.banksteel.log.demo.log4j.Demo.main(Demo.java:16)] 警告信息……
2016-05-08 19:32:55,783 [ERROR] [main] - [com.banksteel.log.demo.log4j.Demo.main(Demo.java:20)] 处理业务逻辑的时候发生一个错误……
java.lang.Exception: 错误消息啊
at com.banksteel.log.demo.log4j.Demo.main(Demo.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

如何去解析这个日志,是个非常头疼的地方,万一某个系统的开发人员输出的日志不符合既定规范的 PatternLayout 就会引发异常。

为了能够一劳永逸的解决格式问题,我们采用 JsonLayout 就能很好的规范日志输出,例如LOG4J 2.X 版本中提供的 JsonLayout 输出的格式如下所示:

  1. {
  2. "timeMillis" : 1462712870612,
  3. "thread" : "main",
  4. "level" : "FATAL",
  5. "loggerName" : "com.banksteel.log.demo.log4j2.Demo",
  6. "message" : "发生了一个可能会影响程序继续运行下去的异常!",
  7. "thrown" : {
  8. "commonElementCount" : 0,
  9. "localizedMessage" : "错误消息啊",
  10. "message" : "错误消息啊",
  11. "name" : "java.lang.Exception",
  12. "extendedStackTrace" : [ {
  13. "class" : "com.banksteel.log.demo.log4j2.Demo",
  14. "method" : "main",
  15. "file" : "Demo.java",
  16. "line" : 20,
  17. "exact" : true,
  18. "location" : "classes/",
  19. "version" : "?"
  20. }, {
  21. "class" : "sun.reflect.NativeMethodAccessorImpl",
  22. "method" : "invoke0",
  23. "file" : "NativeMethodAccessorImpl.java",
  24. "line" : -2,
  25. "exact" : false,
  26. "location" : "?",
  27. "version" : "1.7.0_80"
  28. }, {
  29. "class" : "sun.reflect.NativeMethodAccessorImpl",
  30. "method" : "invoke",
  31. "file" : "NativeMethodAccessorImpl.java",
  32. "line" : 57,
  33. "exact" : false,
  34. "location" : "?",
  35. "version" : "1.7.0_80"
  36. }, {
  37. "class" : "sun.reflect.DelegatingMethodAccessorImpl",
  38. "method" : "invoke",
  39. "file" : "DelegatingMethodAccessorImpl.java",
  40. "line" : 43,
  41. "exact" : false,
  42. "location" : "?",
  43. "version" : "1.7.0_80"
  44. }, {
  45. "class" : "java.lang.reflect.Method",
  46. "method" : "invoke",
  47. "file" : "Method.java",
  48. "line" : 606,
  49. "exact" : false,
  50. "location" : "?",
  51. "version" : "1.7.0_80"
  52. }, {
  53. "class" : "com.intellij.rt.execution.application.AppMain",
  54. "method" : "main",
  55. "file" : "AppMain.java",
  56. "line" : 144,
  57. "exact" : true,
  58. "location" : "idea_rt.jar",
  59. "version" : "?"
  60. } ]
  61. },
  62. "endOfBatch" : false,
  63. "loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
  64. "source" : {
  65. "class" : "com.banksteel.log.demo.log4j2.Demo",
  66. "method" : "main",
  67. "file" : "Demo.java",
  68. "line" : 23
  69. }
  70. }

我们看到,这种格式,无论用什么语言都能轻松解析了。

日志框架的Kafka集成

我们这里只用log4j 1.x 和 log4j 2.x 进行示例。

log4j 1.x 与 Kafka 集成

首先POM.xml的内容如下:

  1. <dependencies>
  2. <dependency>
  3. <groupId>log4j</groupId>
  4. <artifactId>log4j</artifactId>
  5. <version>1.2.17</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>com.fasterxml.jackson.core</groupId>
  9. <artifactId>jackson-core</artifactId>
  10. <version>2.7.4</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>com.fasterxml.jackson.core</groupId>
  14. <artifactId>jackson-databind</artifactId>
  15. <version>2.7.4</version>
  16. </dependency>
  17. <dependency>
  18. <groupId>com.fasterxml.jackson.core</groupId>
  19. <artifactId>jackson-annotations</artifactId>
  20. <version>2.7.4</version>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.apache.kafka</groupId>
  24. <artifactId>kafka-clients</artifactId>
  25. <version>0.8.2.1</version>
  26. </dependency>
  27. <dependency>
  28. <groupId>org.apache.kafka</groupId>
  29. <artifactId>kafka_2.11</artifactId>
  30. <version>0.8.2.1</version>
  31. </dependency>
  32. </dependencies>

注意,我们这里使用的Kafka版本号是0.8.2.1,但是对应0.9.0.1是可以使用的并且0.9.0.1也只能用0.8.2.1才不会发生异常(具体异常可以自己尝试一下)。

而log4j 1.x 本身是没有 JsonLayout 可用的,因此我们需要自己实现一个类,如下所示:

  1. package com.banksteel.log.demo.log4j;
  2.  
  3. import com.fasterxml.jackson.core.JsonProcessingException;
  4. import com.fasterxml.jackson.databind.ObjectMapper;
  5. import org.apache.log4j.Layout;
  6. import org.apache.log4j.spi.LoggingEvent;
  7.  
  8. import java.util.LinkedHashMap;
  9. import java.util.LinkedList;
  10. import java.util.List;
  11. import java.util.Map;
  12.  
  13. /**
  14. * 扩展Log4j 1.x,使其支持 JsonLayout,与 log4j2.x 一样是基于Jackson进行解析,其格式也是完全参考 Log4J 2.x实现的。
  15. *
  16. * @author 热血BUG男
  17. * @version 1.0.0
  18. * @since Created by gebug on 2016/5/8.
  19. */
  20. public class JsonLayout extends Layout {
  21.  
  22. private final ObjectMapper mapper = new ObjectMapper();
  23.  
  24. public String format(LoggingEvent loggingEvent) {
  25. String json;
  26. Map<String, Object> map = new LinkedHashMap<String, Object>(0);
  27. Map<String, Object> source = new LinkedHashMap<String, Object>(0);
  28. source.put("method", loggingEvent.getLocationInformation().getMethodName());
  29. source.put("class", loggingEvent.getLocationInformation().getClassName());
  30. source.put("file", loggingEvent.getLocationInformation().getFileName());
  31. source.put("line", safeParse(loggingEvent.getLocationInformation().getLineNumber()));
  32.  
  33. map.put("timeMillis", loggingEvent.getTimeStamp());
  34. map.put("thread", loggingEvent.getThreadName());
  35. map.put("level", loggingEvent.getLevel().toString());
  36. map.put("loggerName", loggingEvent.getLocationInformation().getClassName());
  37. map.put("source", source);
  38. map.put("endOfBatch", false);
  39. map.put("loggerFqcn", loggingEvent.getFQNOfLoggerClass());
  40.  
  41. map.put("message", safeToString(loggingEvent.getMessage()));
  42. map.put("thrown", formatThrowable(loggingEvent));
  43. try {
  44. json = mapper.writeValueAsString(map);
  45. } catch (JsonProcessingException e) {
  46. return e.getMessage();
  47. }
  48. return json;
  49. }
  50.  
  51. private List<Map<String, Object>> formatThrowable(LoggingEvent le) {
  52. if (le.getThrowableInformation() == null ||
  53. le.getThrowableInformation().getThrowable() == null)
  54. return null;
  55. List<Map<String, Object>> traces = new LinkedList<Map<String, Object>>();
  56. Map<String, Object> throwableMap = new LinkedHashMap<String, Object>(0);
  57. StackTraceElement[] stackTraceElements = le.getThrowableInformation().getThrowable().getStackTrace();
  58. for (StackTraceElement stackTraceElement : stackTraceElements) {
  59. throwableMap.put("class", stackTraceElement.getClassName());
  60. throwableMap.put("file", stackTraceElement.getFileName());
  61. throwableMap.put("line", stackTraceElement.getLineNumber());
  62. throwableMap.put("method", stackTraceElement.getMethodName());
  63. throwableMap.put("location", "?");
  64. throwableMap.put("version", "?");
  65. traces.add(throwableMap);
  66. }
  67. return traces;
  68. }
  69.  
  70. private static String safeToString(Object obj) {
  71. if (obj == null) return null;
  72. try {
  73. return obj.toString();
  74. } catch (Throwable t) {
  75. return "Error getting message: " + t.getMessage();
  76. }
  77. }
  78.  
  79. private static Integer safeParse(String obj) {
  80. try {
  81. return Integer.parseInt(obj.toString());
  82. } catch (NumberFormatException t) {
  83. return null;
  84. }
  85. }
  86.  
  87. public boolean ignoresThrowable() {
  88. return false;
  89. }
  90.  
  91. public void activateOptions() {
  92.  
  93. }
  94. }

其实并不复杂,注意其中有一些获取不到的信息,用?代替了,保留字段的目的在于与log4j 2.x 的日志格式完全一致,配置log4j.properties如下对接 Kafka:

  1. log4j.rootLogger=INFO,console
  2. log4j.logger.com.banksteel.log.demo.log4j=DEBUG,kafka
  3. log4j.appender.kafka=kafka.producer.KafkaLog4jAppender
  4. log4j.appender.kafka.topic=server_log
  5. log4j.appender.kafka.brokerList=Kafka-01:9092,Kafka-02:9092,Kafka-03:9092
  6. log4j.appender.kafka.compressionType=none
  7. log4j.appender.kafka.syncSend=true
  8. log4j.appender.kafka.layout=com.banksteel.log.demo.log4j.JsonLayout
  9. # appender console
  10. log4j.appender.console=org.apache.log4j.ConsoleAppender
  11. log4j.appender.console.target=System.out
  12. log4j.appender.console.layout=org.apache.log4j.PatternLayout
  13. log4j.appender.console.layout.ConversionPattern=%d [%-5p] [%t] - [%l] %m%n

通过打印日志我们可以看到其输出的最终格式如下:

  1. {
  2. "timeMillis": 1462713132695,
  3. "thread": "main",
  4. "level": "ERROR",
  5. "loggerName": "com.banksteel.log.demo.log4j.Demo",
  6. "source": {
  7. "method": "main",
  8. "class": "com.banksteel.log.demo.log4j.Demo",
  9. "file": "Demo.java",
  10. "line": 20
  11. },
  12. "endOfBatch": false,
  13. "loggerFqcn": "org.slf4j.impl.Log4jLoggerAdapter",
  14. "message": "处理业务逻辑的时候发生一个错误……",
  15. "thrown": [
  16. {
  17. "class": "com.intellij.rt.execution.application.AppMain",
  18. "file": "AppMain.java",
  19. "line": 144,
  20. "method": "main",
  21. "location": "?",
  22. "version": "?"
  23. },
  24. {
  25. "class": "com.intellij.rt.execution.application.AppMain",
  26. "file": "AppMain.java",
  27. "line": 144,
  28. "method": "main",
  29. "location": "?",
  30. "version": "?"
  31. },
  32. {
  33. "class": "com.intellij.rt.execution.application.AppMain",
  34. "file": "AppMain.java",
  35. "line": 144,
  36. "method": "main",
  37. "location": "?",
  38. "version": "?"
  39. },
  40. {
  41. "class": "com.intellij.rt.execution.application.AppMain",
  42. "file": "AppMain.java",
  43. "line": 144,
  44. "method": "main",
  45. "location": "?",
  46. "version": "?"
  47. },
  48. {
  49. "class": "com.intellij.rt.execution.application.AppMain",
  50. "file": "AppMain.java",
  51. "line": 144,
  52. "method": "main",
  53. "location": "?",
  54. "version": "?"
  55. },
  56. {
  57. "class": "com.intellij.rt.execution.application.AppMain",
  58. "file": "AppMain.java",
  59. "line": 144,
  60. "method": "main",
  61. "location": "?",
  62. "version": "?"
  63. }
  64. ]
  65. }

测试类:

  1. package com.banksteel.log.demo.log4j;
  2.  
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5.  
  6. /**
  7. * @author 热血BUG男
  8. * @version 1.0.0
  9. * @since Created by gebug on 2016/5/8.
  10. */
  11. public class Demo {
  12. private static final Logger logger = LoggerFactory.getLogger(Demo.class);
  13.  
  14. public static void main(String[] args) {
  15. logger.info("输出信息……");
  16. logger.trace("随意打印……");
  17. logger.debug("调试信息……");
  18. logger.warn("警告信息……");
  19. try {
  20. throw new Exception("错误消息啊");
  21. } catch (Exception e) {
  22. logger.error("处理业务逻辑的时候发生一个错误……", e);
  23. }
  24. }
  25. }

log4j 2.x 与 Kafka 集成

log4j 2.x 天生支持 JsonLayout,并且与 Kafka 集成方便,我们只需要按部就班的配置一下就好了,POM.xml如下:

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.apache.logging.log4j</groupId>
  4. <artifactId>log4j-api</artifactId>
  5. <version>2.5</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.apache.logging.log4j</groupId>
  9. <artifactId>log4j-core</artifactId>
  10. <version>2.5</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>com.fasterxml.jackson.core</groupId>
  14. <artifactId>jackson-core</artifactId>
  15. <version>2.7.4</version>
  16. </dependency>
  17. <dependency>
  18. <groupId>com.fasterxml.jackson.core</groupId>
  19. <artifactId>jackson-databind</artifactId>
  20. <version>2.7.4</version>
  21. </dependency>
  22. <dependency>
  23. <groupId>com.fasterxml.jackson.core</groupId>
  24. <artifactId>jackson-annotations</artifactId>
  25. <version>2.7.4</version>
  26. </dependency>
  27. <dependency>
  28. <groupId>org.apache.kafka</groupId>
  29. <artifactId>kafka_2.11</artifactId>
  30. <version>0.9.0.1</version>
  31. </dependency>
  32. </dependencies>

log4j2.xml配置文件如下所示:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- Log4j2 的配置文件 -->
  3. <Configuration status="DEBUG" strict="true" name="LOG4J2_DEMO" packages="com.banksteel.log.demo.log4j2">
  4. <properties>
  5. <property name="logPath">log</property>
  6. </properties>
  7.  
  8. <Appenders>
  9. <!--配置控制台输出样式-->
  10. <Console name="Console" target="SYSTEM_OUT">
  11. <PatternLayout pattern="%highlight{%d{yyyy-MM-dd HH:mm:ss} %d{UNIX_MILLIS} [%t] %-5p %C{1.}:%L - %msg%n}"/>
  12. </Console>
  13. <!-- 配置Kafka日志主动采集,Storm会将日志解析成字段存放在HBase中。 -->
  14. <Kafka name="Kafka" topic="server_log">
  15. <!--使用JSON传输日志文件-->
  16. <JsonLayout complete="true" locationInfo="true"/>
  17. <!--Kafka集群配置,需要在本机配置Hosts文件,或者通过Nginx配置-->
  18. <Property name="bootstrap.servers">Kafka-01:9092,Kafka-02:9092,Kafka-03:9092</Property>
  19. </Kafka>
  20. </Appenders>
  21. <Loggers>
  22. <Root level="DEBUG">
  23. <!--启用控制台输出日志-->
  24. <AppenderRef ref="Console"/>
  25. <!--启用Kafka采集日志-->
  26. <AppenderRef ref="Kafka"/>
  27. </Root>
  28. </Loggers>
  29. </Configuration>

这样就Okay了,我们可以在Kafka中看到完整的输出:

  1. {
  2. "timeMillis" : 1462712870591,
  3. "thread" : "main",
  4. "level" : "ERROR",
  5. "loggerName" : "com.banksteel.log.demo.log4j2.Demo",
  6. "message" : "处理业务逻辑的时候发生一个错误……",
  7. "thrown" : {
  8. "commonElementCount" : 0,
  9. "localizedMessage" : "错误消息啊",
  10. "message" : "错误消息啊",
  11. "name" : "java.lang.Exception",
  12. "extendedStackTrace" : [ {
  13. "class" : "com.banksteel.log.demo.log4j2.Demo",
  14. "method" : "main",
  15. "file" : "Demo.java",
  16. "line" : 20,
  17. "exact" : true,
  18. "location" : "classes/",
  19. "version" : "?"
  20. }, {
  21. "class" : "sun.reflect.NativeMethodAccessorImpl",
  22. "method" : "invoke0",
  23. "file" : "NativeMethodAccessorImpl.java",
  24. "line" : -2,
  25. "exact" : false,
  26. "location" : "?",
  27. "version" : "1.7.0_80"
  28. }, {
  29. "class" : "sun.reflect.NativeMethodAccessorImpl",
  30. "method" : "invoke",
  31. "file" : "NativeMethodAccessorImpl.java",
  32. "line" : 57,
  33. "exact" : false,
  34. "location" : "?",
  35. "version" : "1.7.0_80"
  36. }, {
  37. "class" : "sun.reflect.DelegatingMethodAccessorImpl",
  38. "method" : "invoke",
  39. "file" : "DelegatingMethodAccessorImpl.java",
  40. "line" : 43,
  41. "exact" : false,
  42. "location" : "?",
  43. "version" : "1.7.0_80"
  44. }, {
  45. "class" : "java.lang.reflect.Method",
  46. "method" : "invoke",
  47. "file" : "Method.java",
  48. "line" : 606,
  49. "exact" : false,
  50. "location" : "?",
  51. "version" : "1.7.0_80"
  52. }, {
  53. "class" : "com.intellij.rt.execution.application.AppMain",
  54. "method" : "main",
  55. "file" : "AppMain.java",
  56. "line" : 144,
  57. "exact" : true,
  58. "location" : "idea_rt.jar",
  59. "version" : "?"
  60. } ]
  61. },
  62. "endOfBatch" : false,
  63. "loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
  64. "source" : {
  65. "class" : "com.banksteel.log.demo.log4j2.Demo",
  66. "method" : "main",
  67. "file" : "Demo.java",
  68. "line" : 22
  69. }
  70. }

为了减少日志对空间的占用,我们通常还会设置JSONLayout的compact属性为true,这样在kafka中获得的日志将会排除掉空格和换行符。

最后

由于在实际开发中,我们会引入多个第三方依赖,这些依赖往往也会依赖无数的log日志框架,为了保证测试通过,请认清本文例子中的包名以及版本号,log4j 1.x 的 Json 输出是为了完全模拟 2.x 的字段,因此部分字段用?代替,如果想要完美,请自行解决。

随便解释一下日志级别,以便建立规范:

log.error 错误信息,通常写在 catch 中,可以使用 log.error("发生了一个错误",e) 来记录详细的异常堆栈

log.fatal 严重错误,该级别的错误用来记录会导致程序异常退出的错误日志。

log.warn 警告

log.info 信息

log.trace 简单输出文字

log.debug 调试信息

基于Flume+LOG4J+Kafka的日志采集架构方案的更多相关文章

  1. Flume+LOG4J+Kafka

    基于Flume+LOG4J+Kafka的日志采集架构方案 本文将会介绍如何使用 Flume.log4j.Kafka进行规范的日志采集. Flume 基本概念 Flume是一个完善.强大的日志采集工具, ...

  2. kafka和flume进行整合的日志采集的confi文件编写

    配置flume.conf 为我们的source channel sink起名 a1.sources = r1 a1.channels = c1 a1.sinks = k1 指定我们的source收集到 ...

  3. Spring cloud微服务安全实战-7-10ELK日志采集架构优化

    ELK搭建起来.采集日志,展示.但是这个架构还有一些问题. 可用性的问题,springboot的应用,随着业务的增长会越来越多.logstash压力就会越来越大.大到一定的程度可能就会吧logstas ...

  4. 基于logstash+elasticsearch+kibana的日志收集分析方案(Windows)

    一 方案背景     通常,日志被分散的储存不同的设备上.如果你管理数十上百台服务器,你还在使用依次登录每台机器的传统方法查阅日志.这样是不是感觉很繁琐和效率低下.开源实时日志分析ELK平台能够完美的 ...

  5. Openresty+Lua+Kafka实现日志实时采集

    简介 在很多数据采集场景下,Flume作为一个高性能采集日志的工具,相信大家都知道它.许多人想起Flume这个组件能联想到的大多数都是Flume跟Kafka相结合进行日志的采集,这种方案有很多他的优点 ...

  6. flink---实时项目--day02-----1. 解析参数工具类 2. Flink工具类封装 3. 日志采集架构图 4. 测流输出 5. 将kafka中数据写入HDFS 6 KafkaProducer的使用 7 练习

    1. 解析参数工具类(ParameterTool) 该类提供了从不同数据源读取和解析程序参数的简单实用方法,其解析args时,只能支持单只参数. 用来解析main方法传入参数的工具类 public c ...

  7. MySQL金融应用场景下跨数据中心的MGR架构方案(2)

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 如何在多个数据中心部署多套MGR集群,并实现故障快速切换. 上篇文章介绍了如何在多数据中心部署多套MGR集群,并构建集群间 ...

  8. 基于Flume的美团日志收集系统(一)架构和设计

    美团的日志收集系统负责美团的所有业务日志的收集,并分别给Hadoop平台提供离线数据和Storm平台提供实时数据流.美团的日志收集系统基于Flume设计和搭建而成. <基于Flume的美团日志收 ...

  9. 基于Flume的美团日志收集系统(一)架构和设计【转】

    美团的日志收集系统负责美团的所有业务日志的收集,并分别给Hadoop平台提供离线数据和Storm平台提供实时数据流.美团的日志收集系统基于Flume设计和搭建而成. <基于Flume的美团日志收 ...

随机推荐

  1. JDBC与JAVA数据库编程

    一.JDBC的概念 1. JDBC (Java DataBase Connectivity) Java数据库连接 a) 主要提供java数据库应用程序的API支持 2. JDBC的主要功能 a) 创建 ...

  2. [ROS] Studying Guidance

    Reference: https://www.zhihu.com/question/35788789 安装指南:http://wiki.ros.org/indigo/Installation/Ubun ...

  3. 使用phpstorm来进行svn提交

    macbook上找一款好用的免费的SVN真是难呀,要么就是非常模糊的画面,本想用Xcode的,但是折腾了一会想打开一个php项目文件夹,不会搞.最后想还是用phpstorm吧.没想到还挺好用的. 首先 ...

  4. WebWorker的importScripts方法

    简述 在<JavaScript高级程序设计(第三版)>中,提到WebWorker的importScripts方法是异步执行的,然而在 另一本书<Javascript权威指南>中 ...

  5. HP-UX 11g RAC安装 记录

    环境:HP-UX 11.31 + GI 11.2.0.4 + Oracle 11.2.0.4 背景:本文只对HP-UX平台安装11g RAC环境过程中,针对一些跟Linux平台有差异的地方进行简单记录 ...

  6. C#的网络适配器操作

    网络的相关设置在项目开发中有较多的应用,有时候需要在项目中对网络信息进行相关设置. 现在提供提供几种相关的辅助方法类. (1).IP地址 /// <summary> /// IP地址 // ...

  7. 大型网站提速关键技术(页面静态化,memcached,MySql优化)(二)

    一:页面静态化 几个概念: 静态网址:(比如:http://localhost/abc.html) 特点:1.利用seo(search engine optimization) 搜索引擎优化;2:访问 ...

  8. SpringMVC 参数注入

    写一个web service, 总是400. 说是request有问题,server不识别.然而检查了很多次都没问题.最终问题指向spring对参数的解析和注入. 一个controller中可以自定义 ...

  9. jquery如何判断checkbox(复选框)是否被选中 ...

    <script type="text/javascript" src="../lib/jQuery1.11.1.js"></script> ...

  10. [Q&A] MySQL Error 1050(42S01): Table already exist

    [环境说明] 1:MySQL Server 5.5 2:MyEclipse 2014 3:JDK 1.7 造成该问题的可能原因: 1:用 Java 读取 SQL 文件,并执行其中的 sql 语句,但是 ...