习惯每周写一篇基于技术的帖子,描述一些本身的想法和故事,一方面是整理本身的思路,另外一方面是欢迎拍砖。
这几天看到一些论坛里的技术帖子,顺便梳理了一下2016全部的技术精英大赛的C++帖子。
把一些好的思想,结合本身的实践,变为本身的,非常愉快。
有时间,好好的和Billing的同事去学习一下区块链,那里真是一个宝库,呵呵。
说正文吧,
有几篇帖子说到日志的难管理,以及问题出现了,运维人员只能打电话给程序,让他们帮忙分析问题。
这是不少项目的通病。
程序通常喜欢打日志,这里打一点,那里打一点,弄的处处都是日志。
而实际运维系统上的人,基本看不懂这些日志,以致于日积月累,巨大量的日志,哪一个能够删,哪一个不能够删?
你让程序员本身去清理?靠谱么?可能这个开发说,"那天出问题了我还要用呢,别删!!"
又好比,周末,程序员正在休息,运维发现问题,打电话给程序,每每最多说的是。"XXX目前不正常", 负责一点的,"XXX进程好像挂了",程序听了这些,内心多半会说:"和没说同样,什么还得本身去看。"
这样的问题,我遇到过好屡次了。
运维抱怨研发弄的乱七八糟,而研发抱怨运维只是一个高级传话筒。
这种隔阂,形成了不少项目的"内伤",这种"内伤"就像大堤的裂缝,那天说不定就形成大事件。
2008年,我开源了一套本身的服务器引擎,基于ACE的。
一开始用途就是想把本身从无尽的IO重写中拯救出来。当时作了好几个系统,因为接口关系,本身写了无数遍的select epoll。虽然说都那么几百行代码反过来调过去,就是不爽。当时想法很简单,别人用不用我无论,我只要本身用的爽就好了。反正我是不想再每次都重复写IO了。
2011年,没想到民生银行的一个开发和我联系,问我关于这个开源系统的一些实现细节,他们要用。
当时以为颇有趣,就帮助他们借助个人工具实现了一些东西,权当提升本身的能力。
其中有一个细节特别值得我记忆和总结。
他们遇到的问题,就是外包的有些模块,日志处处都是,再加上各类交接,有些日志谁也不清楚究竟是什么,有没有用。以致于不敢动,身为运维很是的头痛。
结合本身的经历,回想起本身的项目写的日志,时间一长,不看代码,都不知道在干什么的,本身有些脸红。
因而开始思考,如何让运维硬起来?(好的设计,必须从问题产出者的出发点去思考)
因而设计出了一套运维插件规则,直接理顺了当时的整合项目,起到了很好的效果。
今天先说日志部分。
在我看来,日志必须是运维的关键性检查指标之一。
甚至,在某些时候,它的强度和研发是一致的。运维懂研发的日志,那么更加就能直接的反应问题了。再也不受必须研发出现的制约。
因而我就提出,身为运维,必须提供一个日志插件体系,全部的研发必须只能用此体系。
怎么理解这句话?
也就是,运维提供一个基于C++的日志系统插件,供研发使用。全部的研发不得使用本身的写日志文件。所有必须使用此日志接口的API实现本身的日志记录。(当时的项目是C++的,后来,这个插件扩展到支持Java和python)
再说的细一点,运维必须提供一个日志记录的功能代码集合,甚至是能够加载的so文件。具体根据项目而定。
分级日志插件系统就这么出来了。
首先,我写的这个日志插件,就是实现研发平常的日志记录。和程序员本身使用的记录日志代码本质上没有什么区别。
可是有一条,个人这个插件,支持规则限制。
什么叫规则限制?
也就是能够作到,运维能够任意配置日志规则,而这个配置规则,彻底不须要研发参与。
怎么理解?
来看看,个人日志插件依赖的是一个XML的配置文件。python
这个配置文件,在测试阶段,是研发配置的,可是在生产环境,彷佛运维配置的。
这里有几个参数稍微解释一下。
这是描述生成一个日志文件的具体描述。(文件规则目前是一天一个,以日期为后缀)
logid是惟一的数字标识,用于匹配指定的日志文件模块,下面我会介绍如何使用它。
logtype目前支持两种状态,一种是正常流水日志(0),一种是异常日志(1)。这个由具体日志的使用者配置。
Display表示的是当前输出的日志,是否输出到屏幕,仍是输出到文件。0是文件,1是屏幕
Level当前日志级别,这个和整个日志系统互动。一会我会详细说明。
logname日志文件名称,实际生成的日志名称的主词,我会根据这个名称自动生成一个子目录,并在里面根据天天的日志自动生成日志信息。
好了,有了这个,再说明一下运维须要设置的关键参数
CurrLevel当前日志插件的运行模式级别,这个怎么理解?每一个日志模块都有一个Level字段。在进程运行的时候,凡是大于此级别的日志才会被输出,这样作,就等于放权给了运维,你决定,那些级别的日志在生产环境是输出成文件的,低于此级别的日志,所有不会生成文件。
全部的日志配置文件,所有由运维和研发商量给出定级标准。
而最终日志配置文件如何配置,由运维给出。
在开发运行过程当中,严禁使用诸如printf,fprint之类的东西,或者本身的日志类。全部日志输出必须使用此插件的输出。
目前对研发,它支持3个API接口。研发不用知道日志是怎么实现的,只要先会用就好了。
//nLogType对应logid字段,研发只管写就好了,你不用管运维是如何配置你的日志文件级别。
int WriteLog(int nLogType, const char* fmt, ...);
//二进制字段的输出
int WriteLogBinary(int nLogType, const char* pData, int nLen);
//邮件输出
int WriteToMail(int nLogType, uint32 u4MailID, char* pTitle, const char* fmt, ...);
这里三个API基本能知足全部的日志要求了,文本,二进制,你们都知道。
那么第三个邮件输出,是指,你能够配置一个邮件服务器,当某些日志产生(研发决定),将会将当前日志输出成一封邮件发送出来给指定的邮箱。这个能够权当报警事件或者事件通知事件来处理,运维在生产环境下,能够经过xml来配置本身的邮箱实现对研发的某些约定进行邮件通知的机制。
运维在生产环境上配置的日志插件文件,决定了运维知道哪些日志是干什么的。那么,为何要运行级别呢?有意思的来了。
咱们在实际运行任务中,常常会发现某些数据不正常,须要打印出日志。
可是,若是咱们在全部的地方都打印日志,就未免太多了,运维人员也会看花眼。
那么怎么办呢?
咱们可让运维在全部的日志等级上设置级别。
启动进程的时候,好比大于5级的日志,才会输出。
那么当出现问题的时候怎么办?
咱们须要运维能够手动的"降级"当前生产环境的日志。这个阶段,进程不须要中止。发送一个指令,让日志插件从5级降到3级,输出全部大于3级的日志。
而后能够导出给研发,或者本身分析后给研发。
导出后,能够再将日志级别"升级"为正常的运维级别(不停机)。保留最少最必要的日志。
这样,就实现了,运维提供日志插件,而研发执行日志输出。至于实际生产环境如何配置,研发不用知道,只要协调好了便可。
这个思惟后来被我扩展了,那就是,运维"插件化"的思想。
有时候,并非全部的东西,都须要研发同事去作的,有些东西,彻底能够从运维出发去作,作成可独立封装的类,交付研发,达到本身的目的,谁说运维不会编程?有些高级核心运维写程序比研发还要强呢。
插件化运维的核心思想,就是把本身要收集的资料收集到本身的手里。合理的分配权限,日志可不止只有你研发去看,运维也在看,而更多的是,运维能够动态的决定日志的输出,将极大的提升运维自己的效率。
最后的结果是,民生银行采用了这套运维架构,直接要求全部的第三方产生使用统一的日志模块,并接受日志管理。极大的减轻了运维"低级传话筒"的角色,经过日志的动态"升级" "降级"。甚至能够在不停机的时候导出必要的分析数据。直接升级到了更高级的管理者。而且,结合日志,运维能够开发各类工具实现"表格展现",好比一些通用的开源的图表展现系统,在这里就不介绍了,github本身搜搜吧。
运维人员决定,那些日志,我如今是须要的。而不是研发,毕竟,研发更专一的是实现,而不是运维过程。你们物尽其用,互不干扰。
好了,个人话说完了,但愿你们多多提提意见。
哦,固然,我知道,或许大家也想知道代码是怎么实现的是吧,没问题。
附件就是日志插件的源码,有兴趣能够玩玩,你玩的越愉快,我越高兴。固然,欢迎交流git