公司在迁移Hadoop到新的集群,涉及到原数据流的迁移,以前是用syslog-ng去push日志,但是配置起来比较麻烦。正好淘宝开发了一个新的tengine,拿过来尝尝鲜,正好利用其pipe功能,可以将日志发送到scribe进行汇总收集,然后就可以舍弃syslog-ng了。反正syslog也是要被Linux抛弃的。
按说应该是直接把Scribe的API直接嵌套在程序中,但由于scribe是刚刚开始推广应用,而以前的日志分析都是基于weblog,大规模改造程序,成本太大,需要逐步推进,为了快速切换,只能这样用了。
安装scribe以前已经写过两个文章了,不再赘述。这次只讲讲是如何将nginx的日志通过scribe收集起来的。
说明:
配置tengine的服务器IP是192.168.1.14,远端的收集服务器IP是192.168.1.33。
scribe在192.168.1.14上的配置是发送一份日志到远端,再保存一份日志在本机。
scribe在远端服务器的配置就是默认就可以了。
./configure --prefix=/opt/modules/tengine --with-file-aio --with-syslog --with-http_sub_module --with-http_gzip_static_module --with-http_stub_status_module --with-pcre && make && make install
加上--with-syslog主要是为了将syslog作为备用方案,万一scribe全挂了,可以用syslog接上。
如果是用我以前发布的linux rpm在CentOS下安装scribe,默认是不好用的,所以需要在centos下改一下。
chkconfig --del scribe
echo "scribed -c /etc/scribe.conf &" >> /etc/rc.local
然后到/opt/modules/tengine下编辑conf/nginx.conf
server {
listen 80;
server_name 192.168.1.14;
access_log "pipe:/opt/modules/tengine/sbin/scribe_ngx -h 192.168.1.14:1463 collect-vv-175" main;
}
红色部分,是淘宝新开发出的pipe日志的功能。用这种办法,在nginx进程里调用一个收集用户输入的脚本
然后是scribe_ngx,其实就是scribe自带的scribe_cat改造了一下,从获取stdin改成了获取用户输入。但是用户输入是放到一个死循环里的,只要nginx不退出,scribe_ngx进程就不会退出。
#!/usr/bin/Python
import sys
from scribe import scribe
from thrift.transport import TTransport, TSocket
from thrift.protocol import TBinaryProtocol
if len(sys.argv) == 2:
category = sys.argv[1]
host = '127.0.0.1'
port = 1463
elif len(sys.argv) == 4 and sys.argv[1] == '-h':
category = sys.argv[3]
host_port = sys.argv[2].split(':')
host = host_port[0]
if len(host_port) > 1:
port = int(host_port[1])
else:
port = 1463
else:
sys.exit('usage (message is stdin): scribe_cat [-h host[:port]] category')
#log_entry = scribe.LogEntry(category=category, message=sys.stdin.read())
message = '%s'%raw_input()
while True:
log_entry = scribe.LogEntry(category=category, message=message)
socket = TSocket.TSocket(host=host, port=port)
transport = TTransport.TFramedTransport(socket)
protocol = TBinaryProtocol.TBinaryProtocol(trans=transport, strictRead=False, strictWrite=False)
client = scribe.Client(iprot=protocol, oprot=protocol)
transport.open()
result = client.Log(messages=[log_entry])
transport.close()
message = '%s'%raw_input()
然后将程序放到/opt/modules/tengine/sbin,然后启动nginx,你将会在进程里看到一个python的进程。