简单说一下,Scribe是Facebook开源的分布式日志搜集系统,架构简单,日志格式灵活,且支持异步发送消息和队列。非常适合用于用户行为分析的基础数据收集,支持hadoop。配合thrift,可以跨语言和平台进行数据收集,非常优秀,性能也非常卓越。
记录日志的程序框架由thrift自动生成,只需include或者import即可。
Scribe提供两种不同的架构可供选择,单Server,或C/S。从系统调用上说,Scribe之所以性能卓越,是因为采用了epoll方式,这个就不解释了。简单描述一下Scribe可以设置的几种架构方式。
不过要明确一个概念,Scribe不是抓取日志的东西,而是Push日志的东西
一、架构设计
1. Server,适用于压力较小的网站或服务。日志流程如下
用户 --> WebServer --> Scribe --> 存储 --> 分析 --> 展示
用户 --> WebServer -------|
用户 --> WebServer -------|
2.C/S结构,适合访问量大的网站和服务,并可根据需要进行平行扩展,采用散列的方式分配服务器压力。
用户 --> WebServer1 --> ScribeClient --> ScribeServer-->存储-->分析-->展示
用户 --> WebServer2--------|
用户 --> WebServer3--------|
用户 --> WebServer2--------|
用户 --> WebServer3--------|
Client及Server均可进行水平扩展,在程序中设置hash访问。
二、安装配置及使用方法(FreeBSD为例)
1.安装Scribe
最新的ports列表中,Scribe及fb303均配置为损坏,所以我们用直接安装二进制的方式进行,事实上,这样更加简单快捷。
#pkg_add -r scribe
#pkg_add -r thrift
#pkg_add -r fb303
#pkg_add -r thrift
#pkg_add -r fb303
这样就完事了。
在ubuntu下,你需要apt-get依赖包,在centos下,抱歉,yum太糟糕了。你需要自己下一堆的依赖文件,然后rpm安装或者花几个小时去逐个编译。
主要的依赖包包括,python,python-dev,boost,boost-lib,perl,libtool,pkgconfig,m4,autoconf,automake,g++,ruby,ruby-dev.再多的我也记不清了。
FreeBSD下还需要做一件事,就是提取配置文件,我建议你下载scribe和thrift的源码包,然后解压缩,但不要编译安装,我们需要的只是他的配置文件。
然后执行
#cd /usr/ports/net/scribe/work/scribe-2.2/examples
#cp example* /usr/local/etc/
#cd /usr/local/etc/
#mv example1.conf scribe.conf
#cd /usr/local/etc/rc.d
#./scribe start
#cp example* /usr/local/etc/
#cd /usr/local/etc/
#mv example1.conf scribe.conf
#cd /usr/local/etc/rc.d
#./scribe start
这样你的scribe server就启动了。
2.生成你的头文件
这需要用到thrift
请找到fb303.thrift和scribe.thift,至于怎么找,自己想办法把。放到相同的目录下,修改scribe.thrift中包含fb303的路径为当前路径。然后执行
#thrift -r --gen php scribe.thrift
会在当前目录下生成gen-php的文件夹,你所需要的php框架文件都在这个文件夹下。
如果你需要生成c++,java,python,ruby甚至erlang, haskball,就将命令行中的php替换为这些单词。
3.编写你的第一个scribe收集程序。
把你的gen-php mv 成thrift或者其他你喜欢的名字然后vi一个文件,内容如下:
<?
$GLOBALS['THRIFT_ROOT'] = './thrift';
include_once $GLOBALS['THRIFT_ROOT'] . '/scribe/scribe.php';
include_once $GLOBALS['THRIFT_ROOT'] . '/transport/TSocket.php';
include_once $GLOBALS['THRIFT_ROOT'] . '/transport/TFramedTransport.php';
include_once $GLOBALS['THRIFT_ROOT'] . '/protocol/TBinaryProtocol.php';
$msg1['category'] = 'Test';
$msg1['message'] = "a,b,c,d,e,f,g";
$entry1 = new LogEntry($msg1);
$messages = array($entry1);
$socket = new TSocket('localhost', 1463, true);
$transport = new TFramedTransport($socket);
$protocol = new TBinaryProtocol($transport, false, false);
$scribe_client = new scribeClient($protocol, $protocol);
$transport->open();
$scribe_client->Log($messages);
$transport->close();
?>
$GLOBALS['THRIFT_ROOT'] = './thrift';
include_once $GLOBALS['THRIFT_ROOT'] . '/scribe/scribe.php';
include_once $GLOBALS['THRIFT_ROOT'] . '/transport/TSocket.php';
include_once $GLOBALS['THRIFT_ROOT'] . '/transport/TFramedTransport.php';
include_once $GLOBALS['THRIFT_ROOT'] . '/protocol/TBinaryProtocol.php';
$msg1['category'] = 'Test';
$msg1['message'] = "a,b,c,d,e,f,g";
$entry1 = new LogEntry($msg1);
$messages = array($entry1);
$socket = new TSocket('localhost', 1463, true);
$transport = new TFramedTransport($socket);
$protocol = new TBinaryProtocol($transport, false, false);
$scribe_client = new scribeClient($protocol, $protocol);
$transport->open();
$scribe_client->Log($messages);
$transport->close();
?>
通过web浏览器访问这个程序,我现在假设你已经有一个webserver了。然后去/tmp/scribetest/下查看生成日志文件,正常的话,会生成一个叫Test的文件夹,下面有一个叫Test_00000的文件,内容就是:a,b,c,d,f,g。你可以写任何的东西,只要你觉得将来统计起来方便。
3.配置scribe
当然仅仅这样是不够的,我们需要自定义配置文件好完成诸如日志的rotate,存储路径的设定,甚至是直接往hadoop里面写数据。
我给出一个典型的配置文件,这里包含了rotate,路径设定,多重存储等。
port=1463
max_msg_per_second=2000000
check_interval=3
< store >
category=default
type=multi
target_write_size=20480
max_write_interval=1
buffer_send_rate=2
retry_interval=30
retry_interval_range=10
< store0 >
type=file #类型,文件
fs_type=std #方式,包括std和hdfs
file_path=/data/logs #存储路径
base_filename=thisisoverwritten
max_size=1000000000 #日志文件最大,超过将自动rotate,字节计算
rotate_period=daily #以时间rotate,可以写成300s(秒),hourly
add_newlines=1
create_symlink=no #不创建符号链接
</ store0 >
< store1 >
type=file
fs_type=hdfs
file_path=hdfs://localhost:9090/logs
base_filename=thisisoverwritten
max_size=1000000
add_newlines=1
create_symlink=no
</ store1 >
</ store >
max_msg_per_second=2000000
check_interval=3
< store >
category=default
type=multi
target_write_size=20480
max_write_interval=1
buffer_send_rate=2
retry_interval=30
retry_interval_range=10
< store0 >
type=file #类型,文件
fs_type=std #方式,包括std和hdfs
file_path=/data/logs #存储路径
base_filename=thisisoverwritten
max_size=1000000000 #日志文件最大,超过将自动rotate,字节计算
rotate_period=daily #以时间rotate,可以写成300s(秒),hourly
add_newlines=1
create_symlink=no #不创建符号链接
</ store0 >
< store1 >
type=file
fs_type=hdfs
file_path=hdfs://localhost:9090/logs
base_filename=thisisoverwritten
max_size=1000000
add_newlines=1
create_symlink=no
</ store1 >
</ store >
用到hadoop的话,你需要为scribe编译libhdfs。
二、日志分析
由于日志格式是由你自己定义的,所以分析起来会比较轻松。
1.一个日志文件,1.log,字段以","分割。
202.163.4.5,12345678901,111,123
202.153.3.6,12345678901,111,124
202.153.7.3,12345678901,112,125
202.17.23.3,12345678901,112,126
211.98.76.5,12345678901,113,127
218.22.24.5,13330080923,113,128
202.153.3.6,12345678901,111,124
202.153.7.3,12345678901,112,125
202.17.23.3,12345678901,112,126
211.98.76.5,12345678901,113,127
218.22.24.5,13330080923,113,128
需要统计第四列非空的行数(awk实现):
#cat 1.awk
BEGIN{ total=0;FS="," }
{
$4!~//;
total+=1;
}
END{ print total}
#awk -f 1.awk 1.log
6
#
BEGIN{ total=0;FS="," }
{
$4!~//;
total+=1;
}
END{ print total}
#awk -f 1.awk 1.log
6
#
统计第三列去重,并统计出现的次数
#cat 2.awk
BEGIN{FS=","}
{
a[$3]++;
}
END {for(i in a)print i,":" a[i]}
#awk -f 2.awk 1.log
111:2
112:2
113:2
#
BEGIN{FS=","}
{
a[$3]++;
}
END {for(i in a)print i,":" a[i]}
#awk -f 2.awk 1.log
111:2
112:2
113:2
#
计算第四列的总和
#cat 3.awk
BEGIN{FS=",";sum=0}
{
sum+=$4;
}
END{print sum}
#awk -f 3.awk 1.log
753
#
BEGIN{FS=",";sum=0}
{
sum+=$4;
}
END{print sum}
#awk -f 3.awk 1.log
753
#
基本的使用和统计就是这样,非常轻松就能统计很多数据,比分析NCSA的日志方便太多了。
hadoop要写的话就太多了,另开篇幅吧。
2011-11-19更新
特别说明:不要认为Scribe只能用于网站应用,他可以用于任何方面的数据收集,如果你有客户端程序,可以用thrift生成C++ header,加入到你的源码中,然后编译生成客户端,进行用户数据收集。亦或生成java源码,加入到android应用中进行分发并收集数据。
目前thrift支持的语言包括C++,C#,php,python,cocoa,haskell,erlang,as3,java,javame,javascript,html,ocaml,perl,ruby,smalltalk和xsd。
包括hadoop在内的一系列系统,都使用thrift来生成语言接口。