Midlog中间件

node服务端开发中少不了日志打点,而在koa框架下的日志打点在多进程环境中日志信息往往无法对应上下文,而且在高并发下直接进行写buffer操作(内核调用writev)也会造成内存泄漏,因此Midlog就是为了缓解这种问题而产生的,其采用多种缓冲调度策略尽可能降低writev的代价,减缓内存溢出的速率。

日志系统的三个关键要素:稳定、性能和易用。


当前log4js遇到的问题。


设计新系统的前提。


回顾node原生模块--“流”的读与写,涉及到了多个缓冲区以及他们缓冲区的实现(stream2.0的 Transform流同时包括了读写缓冲区)


优化点与优化方式。


Midlog系统架构图,其中reqContainer收集同一个上下文的日志信息并转码;

StrategyMaker负责制定双缓冲缓存策略和超时刷新以及强制刷新策略;

Writeable则负责真正的写buffer操作,内部通过链表保存数据;


详细介绍每个模块的功能。


快速使用

app.js

  1. var koa = require('koa');
  2. var midlog = require('midlog');
  3. var app = koa();
  4. // 配置日志中间件
  5. var firstValve = midlog({
  6. env: 'online',
  7. exportGlobalLogger: true,
  8. appender: [{
  9. type: 'INFO',
  10. logdir: '/tmp/log/midlog',
  11. pattern: '%d %r %x{name}:%z %p - %m%n',
  12. rollingFile: false,
  13. duation: 60000,
  14. name: 'info.log',
  15. nameformat: '[info.]HH-mm-ss[.log]',
  16. tokens: {
  17. name: 'helloworld'
  18. },
  19. cacheSize: 5 * 1024 * 1024,
  20. flushTimeout: 15000
  21. },{
  22. type: 'ERROR',
  23. logdir: '/tmp/log/midlog',
  24. pattern: '%d %r %x{name}:%z %p - %m%n',
  25. rollingFile: false,
  26. duation: 60000,
  27. name: 'error.log',
  28. nameformat: '[info.]HH-mm-ss[.log]',
  29. tokens: {
  30. name: 'helloworld'
  31. },
  32. cacheSize: 10240,
  33. flushTimeout: 10000
  34. },{
  35. type: 'TRACE',
  36. logdir: '/tmp/log/midlog',
  37. pattern: '%d %r %x{name}:%z %p - %m%n',
  38. rollingFile: false,
  39. duation: 60000,
  40. name: 'trace.log',
  41. nameformat: '[info.]HH-mm-ss[.log]',
  42. tokens: {
  43. name: 'helloworld'
  44. },
  45. cacheSize: 5 * 1024 * 1024,
  46. flushTimeout: 10000
  47. }]
  48. });
  49. // 使用全局的logger接口
  50. logger.info('i am the global logger');
  51. // 将midlog放在中间件的前列
  52. app.use(firstValve);
  53. // 业务中间件
  54. app.use(function*(next){
  55. this.logger.info(this.url+' this is the first valve!! ');
  56. this.logger.error('midlog tracing' + this.url+' this is the first valve!! ');
  57. this.logger.trace('midlog tracing' + this.url+' this is the first valve!! ');
  58. yield next;
  59. });
  60. app.use(function*(){
  61. this.logger.info(this.url+' this is the 2cd valve!! ');
  62. this.logger.error('midlog tracing' + this.url+' this is the 2cd valve!! ');
  63. this.logger.trace('midlog tracing' + this.url+' this is the 2cd valve!!');
  64. this.body = '<h1>hello midlog</h1>';
  65. });
  66. app.listen(8888);

功能

midlog提供了3种日志刷新级别:

TRACE、INFO、ERROR

并且提供了两种写日志文件的方式:

  • 单文件写 (通过设置appender的rollingFile为false触发)

  • 文件分时间片写 (通过设置appender的rollingFile为true触发)

midlog采用和log4js相同的layout格式和语法,生成可定制的日志输出格式。

最后,midlog采用多级缓冲的架构(针对单文件写模式采用双缓冲,文件分时写模式采用单缓冲),可以有效的控制Stream写的频率,而缓冲的大小和刷新频率可以由开发者根据实际需要自由设置。

配置

  • env {String} 环境设置。若设置为development,则会在控制台和文件中同时输出日志

  • exportGlobalLogger {Boolean} 是否保留全局logger对象。设置为true,则在全局使用logger对象

  • appender {Array} 日志类型配置数组。数组每一项描述每种类型日志的相关信息及缓冲刷新频率

appender详解

  • type {String} 日志类型。可以为 “INFO、TRACE和ERROR” 任意一种

  • logdir {String} 日志文件所在的绝对目录

  • rollingFile {Boolean} 是否按照时间进行日志文件分割。设置为true时则按照设置的duration间隔分割文件

  • duration {Number} 分割日志文件的间隔。若rollingFile为true,则按照duration大小分割文件

  • name {String} 日志文件名称。name属性在单文件写模式下有效,在rollingFile == true时无效

  • nameformat {String} 日志文件格式匹配定义。nameformat属性在文件分时间片写模式下有效,即rollingFile == true

    格式定义的字符串意义如下所示:

  1. 'd': 日期和时间,
  2. 'h': 主机名称,
  3. 'm': 日志信息格式化,主要优化错误输出,
  4. 'n': 换行符,
  5. 'p': 日志级别,
  6. 'r': 时间输出,
  7. 'z': 进程号输出,
  8. '%': 百分号占位符,
  9. 'x': 用户自定义变量或函数,搭配{token}属性
  • tokens {Object} 与nameformat搭配使用,对象的属性值可为常亮,也可为函数

如定义nameformat为 pattern: '%d %r %x{name}:%z %p - %m%n' 且tokens设置为 {name: 'helloworld'}

则输出日志格式为:

  1. (%d) (%r) (%x{name}) (%z) (%p) (%m) (%n)
  2. 2017-01-16 10:59:55.611 10:59:55 helloworld:13736 INFO - / this is the first valve!!
  • cacheSize {Number} 缓冲大小,单位字节。midlog在单文件写模式下采用双缓冲结构控制I/O速率,因此开发者可以通过定义缓冲大小实现高效的写入流程,默认为10kB大小;在文件分时间片写模式下该选项无效

  • flushTimeout {Number} 缓冲刷新间隔。在单文件写文件分时间片写两种模式下都起作用,定点刷新缓冲

高吞吐koa日志中间件的更多相关文章

  1. 攻克数据库核心技术壁垒,实现百万级QPS的高吞吐

    CynosDB是腾讯云自研的新一代高性能高可用的企业级分布式云数据库.融合了传统数据库.云计算与新硬件的优势,100%兼容开源数据库,百万级QPS的高吞吐,不限存储,价格仅为商用数据库的1/10. C ...

  2. 高吞吐高并发Java NIO服务的架构(NIO架构及应用之一)

    高吞吐高并发Java NIO服务的架构(NIO架构及应用之一) http://maoyidao.iteye.com/blog/1149015   Java NIO成功的应用在了各种分布式.即时通信和中 ...

  3. dotnet core高吞吐Http api服务组件FastHttpApi

    简介 是dotNet core下基于Beetlex实现的一个高度精简化和高吞吐的HTTP API服务开源组件,它并没有完全实现HTTP SERVER的所有功能,而是只实现了在APP和WEB中提供数据服 ...

  4. 高吞吐低延迟Java应用的垃圾回收优化

    高吞吐低延迟Java应用的垃圾回收优化 高性能应用构成了现代网络的支柱.LinkedIn有许多内部高吞吐量服务来满足每秒数千次的用户请求.要优化用户体验,低延迟地响应这些请求非常重要. 比如说,用户经 ...

  5. Spark Streaming高吞吐、高可靠的一些优化

    分享一些Spark Streaming在使用中关于高吞吐和高可靠的优化. 目录 1. 高吞吐的优化方式 1.1 更改序列化的方式 1.2 修改Receiver接受到的数据的存储级别 1.3 广播配置变 ...

  6. 高吞吐、低延迟 Java 应用的 GC 优化实践

    本篇原文作者是 LinkedIn 的 Swapnil Ghike,这篇文章讲述了 LinkedIn 的 Feed 产品的 GC 优化过程,虽然文章写作于 April 8, 2014,但其中的很多内容和 ...

  7. Kafka是如何实现高吞吐率的

    Kafka是如何实现高吞吐率的 原创 2016-02-27 杜亦舒 性能与架构 Kafka是分布式消息系统,需要处理海量的消息,Kafka的设计是把所有的消息都写入速度低容量大的硬盘,以此来换取更强的 ...

  8. 深入探析koa之中间件流程控制篇

    koa被认为是第二代web后端开发框架,相比于前代express而言,其最大的特色无疑就是解决了回调金字塔的问题,让异步的写法更加的简洁.在使用koa的过程中,其实一直比较好奇koa内部的实现机理.最 ...

  9. 查看JAVA占用CPU高的线程日志

    # . 查看主进程占用cpu高 top # java # . 按照线程占用cpu由高到低进行排查: -o THREAD,tid, # USER %CPU PRI SCNT WCHAN USER SYS ...

随机推荐

  1. php框架Yaf路由重写

    php框架Yaf路由重写 通常为了友好的URL格式,会进行站点URL的重写,可以在webserver(Nginx)的配置中进行rewrite,也可在在程序端进行 以下使用Yaf框架进行URL的重写,进 ...

  2. 了解 : angular controller link ng-init 顺序

    controller 会先跑,接着是view 里的ng-init,最后是link (指令里的). 所有在指令里如果用link去拿$attr,会有拿不到ng-init想setup的值

  3. android性能优化的一些东西

    说到android性能优化,总觉得是一个很模糊的东西,因为app的性能始终适合手机本身的性能挂钩的,也许一些消耗内容的操作,在一些移动设备可以运行,但是在另外一些上面就会出现内存溢出的问题,但是不管怎 ...

  4. PHP链接Redis

    命令行下运行 redis-server.exe redis.windows.conf 此时,redis服务已经开启,然后我们可以再新开一个命令行,作为控制台 redis-cli.exe -h 127. ...

  5. Sass使用小技巧

    1.任何可以用作css属性值的赋值都可以用作sass变量值.如果变量值与属性不匹配,sass会当作普通字符串来处理. $family: "microsoft yahei", Ari ...

  6. jquery 的基础知识,以及和Javascript的区别

    想到之前所学的javascript 我们会想到这几个方面:找元素: 操作内容: 操作属性:操作样式:统一操作元素: jquery 也是从这几个方面来学习的. <head> <meta ...

  7. iOS集成友盟推送

    之前有写过利用Python自己写一个推送服务器, 今天说下如果集成友盟的推送服务 在这之前我们需要做一些准备动作 #1. 注册一个App ID #2. Enable Push Notification ...

  8. 关于JAVA中抽象类和接口的区别辨析

    今天主要整理一下新学习的有关于Java中抽象类和接口的相关知识和个人理解. 1 抽象类 用来描述事物的一般状态和行为,然后在其子类中去实现这些状态和行为.也就是说,抽象类中的方法,需要在子类中进行重写 ...

  9. 从Hash Killer I、II、III论字符串哈希

    首先,Hash Killer I.II.III是BZOJ上面三道很经典的字符串哈希破解题.当时关于II,本人还琢磨了好久,但一直不明白为啥别人AC的代码都才0.3kb左右,直到CYG神犇说可以直接随机 ...

  10. java利用url实现网页内容的抓取

    闲来无事,刚学会把git部署到远程服务器,没事做,所以简单做了一个抓取网页信息的小工具,里面的一些数值如果设成参数的话可能扩展性能会更好!希望这是一个好的开始把,也让我对字符串的读取掌握的更加熟练了, ...