scribe - 日志收集器 分析

来源:互联网 发布:淘宝网德国过滤水壶 编辑:程序博客网 时间:2024/06/05 18:16

1.General  description

我们知道,使用日志系统是为了使系统变得更健壮,能够应对各种错误并能从错误中较快地恢复。一个大型的分布式系统生成的日志数量是巨大的,所以需要一个有效的工具对其进行管理。Scribe就是这样一个日志收集服务器,使用它可以对大型的系统进行监控。它是Facebook的一个开源组件,使用的是Facebook另一个框架—Thrift。Thrift 在我的理解就是一个高效的跨语言 rpc 框架,所以它可以支持通过 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk, and OCaml 给服务器汇报。

总的来说,Scribe由两部分组成:central  Scribe server 和 local Scribe server。在分布式系统中,每个结点都会有一个local Scribe server运行在上面,收集此结点的日志信息,并将其发送给central  Scribe server。这里的central和local是相对的,是针对一个组内的。

 

2. Download and Install

Scribe并不大,但其安装是一个非常繁琐的过程。通过我不断的努力,最终还是没有安装成功(源代的example不能正常运行)。虽说没有产出的劳动是徒劳的,但这也不是绝对的,至少对其具体的安装过程倒是耳熟能详了。

 

Scribe运行于Linux系统下,试验中我所使用的是Ubuntu 9.10,通过虚拟机安装的。Scribe安装前需要很多Environment  Dependency,具体如下所示:

(1)安装ruby:
           install:   sudo apt-get install ruby-full build-essential
           test:       ruby -v          显示 版本 号
                          which ruby    显示安装的位置
                          新建一个test.rb文件,里面输入如下内容:           
                                         #!/usr/bin/env ruby
                                         puts "hello world!"
                          然后进入该目录,输入如下命令:./test.rb。如果ruby安装成功则会    
                          输出hello world!

(2)安装python:
           一般来讲,Ubuntu系统里已经安装了python。查看是否已经安装,使用如下
          命令:python    显示安装的版本号   
                       which python   显示安装的位置
          系统自带的,其安装目录是在/usr/bin下。如果是自安装的,则会在
          /usr/local/bin下。就如接下来要安装的Thrift和Scribe。

(3)安装libevent:
           下载http://www.svn8.com/linux/accidence/20100218/22428.html
            tar xzfv libevent-1.4.8-stable.tar.gz
            cd libevent-1.4.8-stable
            ./configure
            make
            make install
(4)安装剩下的dependency:
           sudo apt-get install libboost-dev=1.38.1 flex bison libtool automake autoconf pkg-  
           config && wget -O thrift.tgz 
           "http://gitweb.thrift-rpc.org/?p=thrift.git;a=snapshot;h=HEAD;sf=tgz" 
           && tar -xzf thrift.tgz && cd thrift &&./bootstrap.sh && ./configure && make 
           && sudo make install 
           && cd  contrib/fb303/ && ./bootstrap.sh && sudo make && sudo make install
           实际上是将多条命令合为一条而已。

           至此为止,所有的依赖已经安装完成。

(5 )安装Scribe
            首先下载Scribe,这里我所使用的是Scribe2.2。接下来的安装就非常简单了:
            ./bootstrap.sh
            make
            make install

  至此为止,Scribe就成功安装上了。接下来就可以跑Example内的例子了。

 

3. Example:

网上关于Scribe的资料较少,所以阅读源代码是一个很有效的途径。在此之前先运行Example内的例子。

源代码里所给的example很简单,但大体上了模拟了其运行的过程,分三个部分。可参考里面的README文件:
Configurarion(配置)、Running Scribe Server(运行服务器)、Logging messages(记录日志)


3.1 配置:
Scribe Server是通过配置文件启动的。

null:丢弃所有消息
multi:给所有multi类型的store传递消息
file:将消息写入文件
thriftfile:类似于file,但写入的文件类型为thrift  TfileTransport文件
network:将消息转发给另外一个scribe server
buffer:包含两个子store(主、次),在主store工作时,直接使用主store记录日志,只  
                有当主store不可用时,才使用次store记录。而且一旦主store恢复工作,次
                 stroe记录的日志将转移到主store。
bucket:包含一系列的其他类型的stroe,具体使用哪个是由所定义的Hash函数决定的

 

3.2  运行Scribe Server:

 

1)启动:进入到Scribe源码中的根目录,执行如下命令
 scribed examples/example1.conf
如果scribe安装成功的话,则会出现如下提示信息:

 

2) 查看状态:在另外一个终端执行如下命令:
./scribe_ctrl  status
ALIVE

3)停止:开启另外一个终端,执行如下命令:
./scribe_ctrl  stop
在另外一个终端会看到状态信息:

“STATUS: STOPPING"

 

3.3    记录日志:

1)Example1:向已经启动的Server发送消息,验证是否被记录下来。
Server启动后,开启另外一个终端向Server发送信息:使用scribe_cat
 mkdir  /tmp/scribetest
echo  "hello world"| ./scribe_cat   test 
这时你很可能会出现如下错误提示:

也就是说python导入模块scribe失败,但我们打开/usr/lib/python2.6/site-packages,发现里面是有scribe的模块的,所以很可能是PYTHONPATH没有配置正确。使用如下命令进行配置:
进入到/etc目录,然后输入命令gedit  profile(profile文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行),在此文件中添加如下内容:
export  PYTHONPATH= ”/usr/lib/python2.6/site-packages”
然后注销重新登录。
输入echo  $PYTHONPATH命令进行测试。
再次执行echo命令,查看结果:
cat  /tmp/scribetest/test/test_current
或者直接打开查看。—hello world!

 

2) Example2:启动中心服务器和客户端服务器,然后开启一个终端并输入三条命令,并查看结果:
mkdir /tmp/scribetest2
scribed examples/example2central.conf
scribed examples/example2client.conf
echo "test message" | ./scribe_cat -h localhost:1464 test2
echo "this message will be ignored" | ./scribe_cat -h localhost:1464 ignore_me

echo "123:this message will be bucketed" | ./scribe_cat -h localhost:1464 bucket_me

查看结果:
cat /tmp/scribetest/test2/test2_current

cat /tmp/scribetest/bucket*/bucket_me_current

./scribe_ctrl status 1463    

./scribe_ctrl status 1464    

./scribe_ctrl counters 1463   #查看中心服务器的统计数据

./scribe_ctrl counters 1464   #查看客户端服务器的统计数据


当客户端服务器讲收到的信息发送给中心服务器后,会删除本地的存储。
结果显示:客户端收到三条消息,发送了三条消息;
          服务器端收到三条消息,忽略了一条消息。

 

3) Example3:如同Example2启动中心服务器和客户端服务器,但本例测试的是在中心服务器突然down掉的情况下,客户端服务器的缓冲存储功能。

echo  "test message 1" | ./scribe_cat -h localhost:1464 test3   #发送消息1
cat  /tmp/scribetest/test3/test3_current                     #结果:test  message 1
./scribe_ctrl stop 1463                                                     #down掉中心服务器
./scribe_ctrl  status 1463                                                #结果:Failed to get status
echo "test message 2" | ./scribe_cat -h localhost:1464 test3      #发送消息2
./scribe_ctrl status 1464                           #结果:WARNING - Failed to connect
echo "test message 3" | ./scribe_cat -h localhost:1464 test3     #发送消息3
scribed examples/example2central.conf                      #重新启动中心服务器
./scribe_ctrl status 1463                           #结果:ALIVE
./scribe_ctrl status 1464                           #结果:ALIVE
cat /tmp/scribetest/test3/test3_current


#结果:
test message 1

test message 2

test message 3
全部正常接收

 

4.Source Analyse:
4.1  整体类图:

 

4.2  store 和  storeConf


 

4.3  scribeHandler和storeQueue

 

 

 

4.4  配置文件的解析
在server启动的过程中,会调用StoreConf中的parseConfig函数,具体实现是先调用readConfig函数将配置文件的内容逐行读入到一个队列中,然后再调用parseStore函数从队列中逐行解析,并将解析的内容存入StoreConf中的两个Map变量: values和stores。

 

                             类型

                解释

values

std::map<std::string, std::string>

每个store里的<参数,值>对

stores

std::map<std::string, pStoreConf>

存放所有的store

 


 

 

4.5  Server的启动过程的流程图:

 

Main函数是入口点,端口号port和配置文件config_file作为声明一个server实例:
new scribeHandler(port, config_file);然后执行一系列的初始化工作,初始化的流程图如下:

 

4.6 Log过程的流程图:
客户端调用Log(messages)函数发送消息,通过thrift框架的实现,远程方法
scribeHandler:: Log(const vector<LogEntry>& messages)函数被调用,过程如下:

 

 

 

Reference:
http://github.com/facebook/scribe   

http://hi.baidu.com/you5a_com/blog/item/ed62ee3fd1228d0bbba167d5.html

http://snippets.notmyidea.org/2009/07/29/howto-install-scribe-the-facebook-log-system-on-debian/

http://highscalability.com/product-scribe-facebooks-scalable-logging-system

http://sameerparwani.com/posts/facebook-scribe-server-documentation-and-tutorials#comments

原创粉丝点击