New World

过一日,少一日,生命有穷;求一点,得一点,学无止境.

系统中何时上异步消息架构

系统中何时上异步消息?!

JEE架构中异步消息是为了使系统有更好的伸缩性、可扩展性,能够提高业务的处理效率。一个经常出现的场景是日志的异步记录:系统的每一个交易都会有大量的日志记录,日志系统会导致整个系统的反应变慢,写日志也是需要获取appender同步锁,对appender写入信息的过程中需要synchronized来同步数据,如果:

1    appender为文件日志,大量磁盘的I/O操作。

2    appender为数据库,大量的jdbc连接。

12所消耗的时间也是很客观的。

3appenderConsoleAppender,一般的flush属性为true,直接将日志信息从系统io中打印出来。

在实际情况中,是否采用异步日志是需要考虑以下情况,测试才能确定的。

1    如果一个日志记录线程被中断,如何应对这种情况?

2    如果系统突然中断或者人为中断,异步缓存中的日志记录如何处理?

3    怎样保证日志生成者和日志消费者(日志处理线程)数量的平衡

 

Log4j中有一个AsyncAppender可以做一个桥接的方式将其他的Appender连接起来。而这个AsyncAppender的作用就是是Log4j对所有的LogEvent的事件实际输出是异步的。AsyncAppender默认的Buffer Size128条。

              AsyncAppender中日志数据是缓存在buffer:ArrayList中,日志线程发现需要记日志时独占缓存(与此同时各线程等待,此时各线程是被阻塞住的,线程的同步很消耗资源,缓存bufferresize要根据实际情况设定才能更有效率),从缓存中取出日志信息,获得输出流进行输出,将缓存解锁(各线程收到提醒,可以接着写日志了)。这个流程和同步写数据类似。

              磁盘I/O操作、网络I/O-socket创建操作、数据库JDBC操作都是非常消耗资源的,如果在写日志的时候涉及到这3种操作,采用异步日志效果更好,异步日志AsyncAppender能够将这些耗时的操作从主业务流程中分离。

 

我在实际的编码中出现过这种情况:每次业务完成之后,需要将业务相关的操作人、操作时间、业务类型、业务操作结果(成功/失败:失败原因)。

编码方式1

height=323

这种编码方式,在一个双核2.0Ghz2G内存的小型机上的大概的业务量为1k/s

 

通过编码方式2

height=383

这种编码方式,在一个双核2.0Ghz2G内存的小型机上的大概的业务量依然为为1k/s

通过监控工具发现有2个原因:

1    同一台机子的运算能力在方式1下已经快到峰值了,而且加上新的异步消费者管理器:线程的创建、切换、jdbc连接的创建、连接,都是消耗资源的-后来通过jdbc connection pool解决jdbc创建和连接的问题。

2    如果机子的资源没有被完全使用的情况下,在同一台机子上作异步消息处理能够提升些许效率。在我这种情况,机子的硬件资源已经被充分利用了,使用异步操作并不能有太大的提升。

但是采用这个方式的好处是每一笔的业务的应答速度变快了,例如方式1每笔业务从开始到结束需要3s,方式2一般需要1-2秒就可以搞定。

 

方式3

height=348

这种编码方式在使用socket缓存的情况下,处理效率有些许提高。因为没有认真测试,就不给出数据了。

              毕竟,通过socket缓存,真正的资源消耗是在对象的序列化上,纯正的网络I/O并不会消耗太多资源(和System.out.println()一样)。

 

总体来说,异步操作能够使系统架构更优美,但是也要考虑到相应的资源消耗,建议是用异步操作之前一定要经过大量的压力测试来证明系统使用这种架构。

ps:

              1、方式23异步消息框架为ActiveMQ,方式2异步消费者管理器为jdk5的线程池。

2、系统的数据是Oracle,如果换为Mysql,效率更低……,可能是我的mysql配置的问题?!

 

 

阅读更多
个人分类: J2EE
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭