- 浏览: 511332 次
- 性别:
- 来自: 深圳
最新评论
-
di1984HIT:
学习了~~
jackson JSON对象映射出多余字段的bug -
lvye351:
当然,在tomcat还有JPDA这种方式 ,来远程debug: ...
配置linux下tomcat的远程debug -
hety163:
好,语言简单明了易懂
Http和Socket连接区别 -
高军威:
<b>行不行</b>
XSS转码 && struts2 property标签的bug -
chjy1983:
请教下,我这样:JSONObject jsonObject = ...
HttpClient4 POST数据及问题
一份好的代码,从良好的注释习惯开始。接触的东西多了,愈有感触。
最近调试一些c++的接口,20多个字段的接口,居然没有一个字的注释,字段间的层级依赖关系也一字不提。后果当然是可想而知了,抓3,5个人的群一个个字段的问过去,答过来。调用一次,沟通一次,耗时2天有余,至今不通,挫折感非常强。
/** * The AsyncAppender lets users log events asynchronously. * <p/> * <p/> * The AsyncAppender will collect the events sent to it and then dispatch them * to all the appenders that are attached to it. You can attach multiple * appenders to an AsyncAppender. * </p> * <p/> * <p/> * The AsyncAppender uses a separate thread to serve the events in its buffer. * </p> * <p/> * <b>Important note:</b> The <code>AsyncAppender</code> can only be script * configured using the {@link org.apache.log4j.xml.DOMConfigurator}. * </p> * * @author Ceki Gülcü * @author Curt Arnold * @since 0.9.1 */
先看构造函数:
/** * Create new instance. */ public AsyncAppender() { appenders = new AppenderAttachableImpl(); // // only set for compatibility aai = appenders; dispatcher = new Thread(new Dispatcher(this, buffer, discardMap, appenders)); // It is the user's responsibility to close appenders before // exiting. dispatcher.setDaemon(true); // set the dispatcher priority to lowest possible value // dispatcher.setPriority(Thread.MIN_PRIORITY); dispatcher.setName("Dispatcher-" + dispatcher.getName()); dispatcher.start(); }
构造了一个叫despatcher的最低级别守护进程。
其实唯一需要关注的方法就是append,我们看它怎么做异步append
/** * {@inheritDoc} */ public void append(final LoggingEvent event) { // // if dispatcher thread has died then // append subsequent events synchronously // See bug 23021 // 如果dispatcher线程不在了,直接调用各个appender的同步写方法,确保日志的写入 if ((dispatcher == null) || !dispatcher.isAlive() || (bufferSize <= 0)) { synchronized (appenders) { appenders.appendLoopOnAppenders(event); } return; } // Set the NDC and thread name for the calling thread as these // LoggingEvent fields were not set at event creation time. event.getNDC(); event.getThreadName(); // Get a copy of this thread's MDC. event.getMDCCopy(); if (locationInfo) { event.getLocationInformation(); } synchronized (buffer) { //这里将buffer资源对象当锁,可以想象到所有操作buffer的方法都必须做同步。 while (true) { int previousSize = buffer.size(); if (previousSize < bufferSize) { buffer.add(event); // // if buffer had been empty // signal all threads waiting on buffer // to check their conditions. // if (previousSize == 0) { buffer.notifyAll(); //notifyAll()方法是Object对象的方法,而不是Thread对象的方法。 } break; } // // Following code is only reachable if buffer is full // 如果buffer写满了,才会走到下面的代码流程 // // if blocking and thread is not already interrupted // and not the dispatcher then // wait for a buffer notification boolean discard = true; if (blocking //buffer满就阻塞的标志位 && !Thread.interrupted() && Thread.currentThread() != dispatcher) { try { buffer.wait(); //满了就等待把 discard = false; } catch (InterruptedException e) { // // reset interrupt status so // calling code can see interrupt on // their next wait or sleep. Thread.currentThread().interrupt(); //这里处理interrupt的方法值得体会:)当然可以学会套用这个模板 } } // // if blocking is false or thread has been interrupted // add event to discard map. // if (discard) { //如果没能成功进入wait(),放到丢弃消息map中保存 String loggerName = event.getLoggerName(); DiscardSummary summary = (DiscardSummary) discardMap.get(loggerName); if (summary == null) { summary = new DiscardSummary(event); discardMap.put(loggerName, summary); } else { summary.add(event); } break; } } } }
这里出现了2个新的东西,dispatcher 和DiscardSummary,下面分析dispatcher线程的实现:比较简单看懂,也就不写注释了。、
/** * Event dispatcher. */ private static class Dispatcher implements Runnable { /** * Parent AsyncAppender. */ private final AsyncAppender parent; /** * Event buffer. */ private final List buffer; /** * Map of DiscardSummary keyed by logger name. */ private final Map discardMap; /** * Wrapped appenders. */ private final AppenderAttachableImpl appenders; /** * Create new instance of dispatcher. * * @param parent parent AsyncAppender, may not be null. * @param buffer event buffer, may not be null. * @param discardMap discard map, may not be null. * @param appenders appenders, may not be null. */ public Dispatcher( final AsyncAppender parent, final List buffer, final Map discardMap, final AppenderAttachableImpl appenders) { this.parent = parent; this.buffer = buffer; this.appenders = appenders; this.discardMap = discardMap; } /** * {@inheritDoc} */ public void run() { boolean isActive = true; // // if interrupted (unlikely), end thread // try { // // loop until the AsyncAppender is closed. // while (isActive) { LoggingEvent[] events = null; // // extract pending events while synchronized // on buffer // synchronized (buffer) { int bufferSize = buffer.size(); isActive = !parent.closed; while ((bufferSize == 0) && isActive) { buffer.wait(); bufferSize = buffer.size(); isActive = !parent.closed; } if (bufferSize > 0) { events = new LoggingEvent[bufferSize + discardMap.size()]; buffer.toArray(events); // // add events due to buffer overflow // int index = bufferSize; for ( Iterator iter = discardMap.values().iterator(); iter.hasNext();) { events[index++] = ((DiscardSummary) iter.next()).createEvent(); } // // clear buffer and discard map // buffer.clear(); discardMap.clear(); // // allow blocked appends to continue buffer.notifyAll(); } } // // process events after lock on buffer is released. // if (events != null) { for (int i = 0; i < events.length; i++) { synchronized (appenders) { appenders.appendLoopOnAppenders(events[i]); } } } } } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } } }
看完整个类的分析,发现其实是一个非常典型的“生产消费模型”,需要3个角色:
生成者(通常是前台实时线程),
中转服务(可以是缓冲区buffer,也可以是离线存储演化成JMS,加上逻辑处理),
消费者()
AsyncAppender则是对这种模型的一种实践:
1.生产者通常基于资源限制和时间性能的考量,往往需要在生产环节很快的得到调用返回值。
2.生产者、消费者会将业务逻辑全部剥离,由中转服务去做。
3..中转服务会成为整个系统设计的精髓。 需要根据业务的性能指标、可靠性期望指标、以及异常流程处理(比如是否去重、掉线补发)上下功夫。
4.消费者通常需要和生成者独立开。由于系统的控制逻辑全部在中转服务层,所以消费者完全可以使用低优先级别的守护线程。
5. 这种模型一定要做定量分析,因为消费速度一旦跟不上生成速度,中转buffer的溢出处理是非常麻烦的一件事情。在AsyncAppender中的DiscardSummary就是为此而设计。
发表评论
-
Nginx rewrite permanent
2014-03-19 16:43 1764fpm之后,尝试兼容url错误的一段redirect失效。具 ... -
ZmEu漏洞扫描
2014-02-21 16:59 7478挺黑的,nginx抓出来的日志。扫描各种php软件、数据库 ... -
Continuous Integration with Xcode 5
2014-01-09 15:04 996xcode5 及持续集成, 花了20分钟上手配置, 效果非 ... -
Httpclient4.3实例。 每个版本接口变更都巨大
2014-01-08 17:55 33531.新增简单的url请求内容返回, 比较时髦的链调用 ... -
nginx proxy_http_version
2014-01-07 16:10 6375nginx转 apache ,发现HTTP协议版本 从1.1 ... -
ubuntu一键升级到13.10的教训
2013-12-16 11:51 1106从13.04升级到13.10,主要两个变化非常蛋疼: 1 ... -
【PHP】Codeigniter : Unable to locate the model you have specified
2013-12-10 11:36 1916产生这个问题一般两个原因: 1. google到的结果,类 ... -
springMVC + jsonP
2013-11-20 12:58 4198/** * 根据分类id,取新闻列表 ... -
PC端 浏览器Agent切换工具
2013-11-18 11:04 1057插件比较方便,技术流还是推荐fiddler -
Spring3.x中的几个异步执行
2013-08-22 15:00 29041.servlet3 细节可以阅读http://www.i ... -
Mybatis Cache探究
2013-08-22 12:01 1983这里先不讨论第三方的cache集成(有memcach ... -
spring3-基于注解的AOP
2013-08-02 11:58 1044要点: 1.aop的概念真的很多。。。其实从使用出发无非 ... -
HttpClient4 POST数据及问题
2012-05-23 18:03 33599post 方式挂参数的三种格式, mark一下。 ... -
struts2-ognl mark
2011-12-29 16:49 1580暂时mark在这,后面再补充 1. 关于漏洞的问 ... -
类模板语言的变量替换~简易java实现
2011-04-06 15:25 3722场景1:数据库存有 xx,y ... -
XSS转码 && struts2 property标签的bug
2011-03-25 15:36 6683一。了解背景 下面两张图,比较html转义和js的转义。 ... -
小折腾一下swing
2011-03-23 16:23 1214近来看美剧《Lost》,可惜下载的rm文件名太长,很难找到自己 ... -
FileUploadInterceptor ~mark陷阱
2011-03-17 15:45 165503/17 14:25:40 [ERRO ... -
新浪微博技术架构分析-转载
2011-03-07 17:07 2135中国首届微博开发者大会在北京举行,这是国内微博行业的首场技术盛 ... -
谨慎使用SocketChannel的read方法
2011-01-13 18:02 6047下面的代码是一个实例化SocketChannel的过程: ...
相关推荐
此外,Log4j2的AsyncAppender利用了LMAX Disruptor库,这是一个高性能的线程间通信库,能进一步降低同步开销。 总的来说,Log4j2的异步日志功能对于需要高性能日志记录的系统来说是一个强大的工具。通过源码测试和...
"(转)Log4j的AsyncAppender能否提升性能"这个标题涉及到Log4j的一个特性——AsyncAppender,它是Log4j为了提高日志处理性能而引入的一种异步日志写入机制。 AsyncAppender的主要工作原理是通过使用单独的线程池来...
Log4j2引入了异步日志记录器,通过使用后台线程处理日志事件,从而避免了这种阻塞,极大地提升了应用的性能。 **多线程支持** 在多线程环境中,Log4j2能够确保日志事件的正确性和顺序。每个线程都有自己的日志上...
分别有disruptor-3.3.4.jar(Log4j2异步日志的底层实现)、log4j-api-2.19.0.jar(log4j门面)、log4j-core-2.19.0.jar(log4j实现)、log4j-slf4j-impl-2.19.0.jar(SLF4J与Log4j绑定)、slf4j-api-1.7.30.jar(SLF...
总结来说,Log4j2异步写日志通过`AsyncAppender`实现,配置文件`log4j2.xml`是关键,它定义了日志的输出方式和异步处理。`TestController.java`中的日志调用则实际触发了异步日志记录过程。这种机制在高并发环境下...
下面我们将从配置文件类型、核心JAR包、文件渲染和Log调用四个方面来比较Log4j和Log4j2的区别。 配置文件类型 Log4j通过一个.properties文件作为主配置文件,而Log4j2则弃用了这种方式,采用的是.xml、.json或者....
Log4j是一个广泛使用的Java日志记录框架,它允许开发者在应用程序中轻松地记录各种级别的日志信息,如DEBUG、INFO、WARN、ERROR等。在2021年底,一个重大的安全漏洞(CVE-2021-44228)被发现在Log4j2的早期版本中,...
3. **强大的异步日志功能**:Log4j2提供了基于LMAX Disruptor库的强大异步日志处理能力,显著提高了日志记录的性能。 4. **插件式架构**:Log4j2采用了插件式的软件架构,这使得框架易于扩展而无需修改其核心代码。...
针对Log4j 2 远程代码执行漏洞,需要用到的升级资源包,适用于maven资源库,包括log4j,log4j-core,log4j-api,log4j-1.2-api,log4j-jpa等全套2.15.0 maven资源库jar包。如果是maven本地仓库使用,需要将zip包解压...
此次提及的`log4j-api-2.12.4.jar`和`log4j-core-2.12.4.jar`是Log4j 2框架的两个关键组件,版本号为2.12.4,这个版本主要修复了之前版本中可能存在的安全漏洞。 **log4j-api-2.12.4.jar** 是Log4j 2框架的API模块...
apache-log4j-1.2.15.jar, apache-log4j-extras-1.0.jar, apache-log4j-extras-1.1.jar, apache-log4j.jar, log4j-1.2-api-2.0.2-javadoc.jar, log4j-1.2-api-2.0.2-sources.jar, log4j-1.2-api-2.0.2.jar, log4j-...
Log4j2作为Log4j的升级版,提供更好的性能和更丰富的特性,如异步日志记录,JSON布局,以及可插拔的日志配置。 #### 配置Log4j2 1. **添加依赖**:在`pom.xml`中,添加Log4j2的依赖。 ```xml <groupId>org....
2. **配置Log4j**:在项目的类路径下创建`log4j.properties`或`log4j.xml`配置文件,指定日志级别、输出目的地等。例如: ```properties # log4j.properties log4j.rootLogger=DEBUG, stdout log4j.appender....
此外,Log4j2还引入了异步日志记录,通过使用LMAX Disruptor库来提高性能,尤其是在高并发环境中。 2.17.1版本的更新主要是为了修复安全漏洞。在2021年底,Log4j2被发现存在一个严重漏洞(CVE-2021-44228),这个远程...
Log4j、Log4j2和Fastjson的安全性问题在过去曾引起广泛关注,例如Log4j2的CVE-2021-44228(也被称为Log4Shell漏洞),这是一个远程代码执行漏洞,影响了许多使用Log4j2的系统。这个插件可能就是为了检测和利用这些...
Apache log4j2零日漏洞,根据 log4j-2.15.0-rc2 版本编译生成log4j-api-2.15.0.jar 1.解压你的jar jar xvf XXX.jar 2. 删除旧版本jar cd ./BOOT-INF/lib rm -rf log4j-api-*.jar 3. 上传新版本log4j-api-2.15.0....
1. **异步日志记录**:Log4j支持异步日志记录,通过AsyncAppender可以在不阻塞主线程的情况下高效地处理日志。 2. **自定义Appender和Layout**:如果内置的Appender和Layout无法满足需求,用户可以创建自己的实现。...
**日志框架Log4j详解** 在Java编程中,日志记录是不可或缺的一部分,它用于追踪应用程序的运行状态,帮助开发者在出现问题时定位错误、调试程序。Log4j是一款广泛使用的开源日志框架,由Apache软件基金会开发。本文...
Log4j 2是Log4j的下一代版本,它引入了大量新特性,包括异步日志记录、可插拔的日志格式化器、动态配置以及丰富的API。相较于Log4j 1.x,Log4j 2不仅在性能上有所增强,而且在用户体验和安全性上都有显著改进。 2....