我之前的做法很明显比较麻烦,多绕了几圈的,但我这环境复杂了些,也有其他方面需求。
其实入库最简便的方式就是用lua的log_by_lua,在nginx的server段增加这么几行:
log_by_lua_block { local mysqlDriver = require "luasql.mysql" local mysqlenv = mysqlDriver.mysql() local conn = mysqlenv:connect(dbname,dbusrname,dbusrpwd,dbaddr,dbport) local sql=[[insert into test (request_uri,fmt_localtime) values(']] .. ngx.var.request_uri .. [[',']] .. ngx.var.fmt_localtime .. [[');]] local re,err=conn:execute(sql) mysqlenv:close() }
在这之前,需要装上mysql或者mariadb的客户端dev库,以及luasql-mysql:
apt install default-libmysqlclient-dev luarocks install luasql-mysql MYSQL_INCDIR=/usr/include/mariadb
库名和具体的包含路径各个系统可能有所不同,找到自己系统对应的就行了。
字段名和连接信息自己改一下,表的结构根据自己情况调整就是了。
ngx.var.xxx是直接使用nginx的变量,具体有哪些去搜一下就知道了,信息很丰富的。
nginx的Lua是异步的,所以用阻塞的写法也没问题,不用考虑这方面的。而且log_by_lua是在请求处理完以后的阶段,所以不管是否出问题,都不会对用户浏览产生影响,放心去干就是了。
还有就是,我以往测试发现,luasql-mysql这个库在拼凑sql语句的时候应该用大段文本的[[]]进行连接,而不要用引号,否则偶尔会产生一些莫名其妙的问题。
这个事情我建议还是要做好规划。虽然出了问题不影响提供服务,但是遇到极端情况,比如请求量大而mysql性能较低,或者mysql干脆就挂了,那nginx再怎么异步也最终会把系统资源耗尽的。这也是我自己不愿在这个阶段入库的原因。
同时应该考虑将某些url(比如静态文件之类)过滤掉,不然请求数量很大的时候,mysql有可能会被撑死……
而这部分过滤最好放在lua里面,不然呢,还需要对某些路径进行php或者后端转发的特别定制,会有些麻烦。
引擎建议用myisam,因为日志这玩意,大概没什么并发读写的需求,所以myisam的读写性能以及占内存少的特点是很适合的。如果给日志库弄个innodb之类的,我只能说,你赢了……
个人看法呢,日志做为一个事后的分析手段,重要性肯定没有正常提供服务来的重要,所以宁愿记录日志出错,也要最大限度确保服务器能正常运行。
我估计,nginx一直不做tcp的日志底层协议也是有这方面考虑,因为udp的话,只管把数据包丢出去就完事了,而如果用tcp,则维护连接也会消耗资源。