Monthly Archives: February 2017

遭遇MongoDB勒索

最近测试环境表现得不正常,MongoDB的数据展现不出来。 查了日志,发现有这么几条: 2017-02-08T23:28:32.384+0000 I COMMAND [conn773] dropDatabase PLEASE_READ_ME starting 2017-02-08T23:28:32.388+0000 I COMMAND [conn773] dropDatabase PLEASE_READ_ME finished 2017-02-08T23:28:34.581+0000 I COMMAND [conn773] dropDatabase iwesee starting 2017-02-08T23:28:34.601+0000 I COMMAND [conn773] dropDatabase iwesee finished 我的代码中不可能有dropDatabase的操作,也没这么手动操作过。 既然PLEASE_READ_ME,那我去就读。 在数据库中发现了PLEASE_READ_ME库,库下有PLEASE_READ_ME集合,集合中有这么个文档: { “_id” : ObjectId(“58a06f3a6d3d693e86ae59da”), “info” : “Don’t … Continue reading

Posted in Uncategorized | Tagged | 1 Comment

实现golang程序热升级

简单定义热升级就是:让运行中的服务改为执行新的程序代码逻辑,且不中断服务。 目前现有的开源热升级程序主要有endless,和beego的grace组件。 经过测试,grace在热升级时,会掐掉当前处理中的连接,自然无法接受。endless的问题在于每次热升级都是创建子进程后,原进程就退出了,这点显然不符合守护进程的要求。 于是自己实现个新的。逻辑参考了endless。其实endless和grace也是相互“借鉴”,相互copy了很多代码。我在“借鉴”时,力求逻辑尽可能简单,自己编写全部代码,并后续完善一些关键细节。 首先要解决多个进程监听同一地址+端口。我首先想到的是nginx、node.js的端口复用方案。但golang尚不支持端口复用。好在golang支持文件描述符和listener的互转,和文件描述符的继承。方案为主进程创建listener,取得文件描述符,子进程再继承listener文件描述符。 新进程应该执行新程序的逻辑。要实现这点,就不能用fork,不然新进程还是执行旧的程序逻辑。 支持守护进程。这点是我重新实现热升级的关键。endless和grace的逻辑是,创建子进程,然后原进程退出。我的方案是一个master进程,一个worker进程。每次只升级worker进程。 master进程与worker进程在外部看起来应该是一体的。这里沿袭了erlang任其崩溃的思想,一个退出,另一个跟随。如果worker进程退出码非0,master进程以相同的退出码结束。 还有很重要的一点,退出worker进程,首先关闭listener,一并关闭listener关联的文件描述符,再等待所有连接关闭。 支持自动升级。这个不是很必要,以后再说。 相比endless,我的实现的另一个优势是:只提供listener接口,而不是ListenAndServe函数。也就是该实现不仅支持http/https,同时支持其它基于tcp的应用层协议,比如grpc。

Posted in Uncategorized | Tagged | 4 Comments

自定义tornado日志格式

第一次玩tornado。版本4.x。为了解决日志格式的问题,google了很多,没一个有效的。 tornado日志格式分两块,一块是logging的格式,一块是tornado请求消息格式。 tornado默认的访问日志输出是这样的: WARNING:tornado.access:404 GET / (127.0.0.1) 167.93ms 其中,WARNING:tornado.access:404为logger日志内容,GET / (127.0.0.1) 167.93ms为访问消息。 根据enable_pretty_logging函数,可知tornado默认采用logging的root logger,并且,如果logger没有配置handler,则为其添加一个默认的StreamHandler。 因而,应该为logging root logger预创建Handler,并指定日志格式。 依据tornado文档,输出访问日志的为Application.log_request,如果要自定义访问日志输出,可以继承Application并重写log_request,或者自定义log_request函数,并设置为Application.settings的log_function属性。 当然选择后者。log_function函数的写法,参照原版Application.log_request就行。 最后贴上我的代码供Google到此的朋友参考: import logging import tornado.log # 日志格式 logging.getLogger().setLevel(logging.INFO) formatter = logging.Formatter(fmt=”%(levelname).4s %(asctime)s %(name)s %(message)s”, datefmt=”%Y-%m-%d %H:%M:%S”) handler = logging.StreamHandler() handler.setFormatter(formatter) logging.getLogger().addHandler(handler) … Continue reading

Posted in Uncategorized | Tagged , | Leave a comment