Gearmand研究

来源:百度文库 编辑:神马文学网 时间:2024/10/04 02:16:01
所有用到的软件:
gearman-0.10
MySQL-5.1.39
libdrizzle-0.5
----------------------------------------------------------------------------------------------------
【需要解决的问题】
1. 安装遇到的: undefined reference to `PQescapeStringConn'  ---- 见【安装】
2. 持久化存储 --- 见 【2009-11-12的前半段】
3. 取得任务的状态以及数据 ---- 主要是异步的模式; ---- 见【2009-11-12的后半段】
    3.1、通过backgroundjob方式,可以保存在数据库中,同时前台get的时候也即可返回;
4. 如何进行多台并行运行 --- 见【2009-11-16】
    4.1 如果多台gearmand服务器运行,有一台down了,这台机器上已经接收到job是否可以恢复--在这台服务器不重启的情况下?
54. 对gearmand的一些执行情况要有了解:
      如:后台有多个worker,gearmand给他们只发一次?
            有多个gearmand,是其中一个gearmand给worker发送?
            如果只有一个worker,而且通过publish/subscribe方式进行注册的,如果客户端发送很快,gearmand是发送一个等worker完成了以后,再发下一个?

----------------------------------------------------------------------------------------------------

 【安装】:
安装Gearmand的问题:

安装Gearmand,在configure的时候没有问题,但是make的时候报:
queue_libpq.c:364: warning: implicit declaration of function `PQescapeStringConn'
  CC     libgearman_server_la-protocol_http.lo
  CC     libgearman_server_la-gearmand.lo
  CC     libgearman_server_la-gearmand_thread.lo
  CC     libgearman_server_la-gearmand_con.lo
  CCLD   libgearman-server.la
make[2]: Leaving directory `/root/software/gearmand-0.10/libgearman-server'
Making all in gearmand
make[2]: Entering directory `/root/software/gearmand-0.10/gearmand'
  CC     gearmand.o
  CCLD   gearmand
../libgearman-server/.libs/libgearman-server.so: undefined reference to `PQescapeStringConn'
collect2: ld returned 1 exit status
make[2]: *** [gearmand] 错误 1
make[2]: Leaving directory `/root/software/gearmand-0.10/gearmand'
make[1]: *** [all-recursive] 错误 1
make[1]: Leaving directory `/root/software/gearmand-0.10'
make: *** [all] 错误 2

网上查了一下资料,PQescapeStringConn的问题一般都是PostgreSQL的,在本地安装了一个PostgreSQL8.4,还是不行。


在configure的时候,增加以下参数:--with-lib-prefix=/opt/PostgreSQL/8.4   我安装PostgreSQL的位置,上面的问题过了(放在LD_LIBRARY_PATH中也是不行的),遇到以下问题:
make[2]: Entering directory `/root/software/gearmand-0.10/tests'
  CC     test.o
  CC     test_gearmand.o
  CC     test_worker.o
  CC     client_test.o
  CCLD   client_test
  CC     worker_test.o
  CCLD   worker_test
  CXX    cpp_test.o
cc1plus: error: unrecognized command line option "-Wno-attributes"
make[2]: *** [cpp_test.o] 错误 1
make[2]: Leaving directory `/root/software/gearmand-0.10/tests'
make[1]: *** [all-recursive] 错误 1
make[1]: Leaving directory `/root/software/gearmand-0.10'
make: *** [all] 错误 2


检查在test目录中的Makefile文件中有一个属性:-Wno-attributes,编译器不认识,去掉,总共2个。
在进行:
make clean --- 发觉有的时候修改了,已经存在的错误还是有,先全部clean后再make就没有问题了
make

可以了

看网上有些人说,运行ldconfig,把本地库更新一下就可以了,自己试了一下,还是不行。

-----------------------------------------
【2009-11-12】
在:https://launchpad.net/gearmand 的开头的地方,就有这么一句:
You should run several servers (at least two) for both load balancing and high availability.
意味着:gearmand可以同时运行多台,以满足负载平衡以及高可用性。
如何做到?

对于gearmand,现在有3点要解决的:
1。 持久化存储
2.   如何进行多台并行运行
3.   对gearmand的一些执行情况要有了解:
      如:后台有多个worker,gearmand给他们只发一次?
            有多个gearmand,是其中一个gearmand给worker发送?
            如果只有一个worker,而且通过publish/subscribe方式进行注册的,如果客户端发送很快,gearmand是发送一个等worker完成了以后,再发下一个?

持久化:在gearmand文档中有说明:http://gearman.org/index.php?id=manual:job_server
字段要求:
  • unique_key VARCHAR(64) PRIMARY KEY
  • function_name VARCHAR(255)
  • priority INT
  • data LONGBLOB
用MySQL的持久化方式:
在数据库中建立了DB: gearmand, 新建用户:gearmand/gearmand,
建表:savejob,格式就是上述的几个字段,unique_key设置为主键。

安装libdrizzle: https://launchpad.net/libdrizzle/trunk/0.5
安装libdrizzle,要重新安装gearmand,
在gearmand的configure中,要配置: --with-libdrizzle-prefix参数

./configure --prefix=要安装的目录 \
                 --with-libdrizzle-prefix=libdrizzle安装的目录  \
                 --with-lib-prefix=PostgreSQL安装的目录
                 --with-libevent-prefix=libevent安装的目录
(在make的时候,一样遇到-Wno-attribute问题,在tests目录中的Makefile文件中, 据网上说,到RHEL5.0就没有这个问题了)

运行:
gearmand -q libdrizzle --libdrizzle-host=10.0.0.1 --libdrizzle-user=gearman  --libdrizzle-password=secret --libdrizzle-db=some_db --libdrizzle-table=gearman_queue --libdrizzle-mysql
遇到以下问题:
FATAL _libdrizzle_query:drizzle_query:drizzle_state_handshake_result_read:old insecure authentication mechanism not supported
证实了,和MySQL版本无关(用了MySQL4.1.20和5.1.39都有这个问题,应该是libdrizzle什么地方不对)

在网上找到了一篇对应的资料: http://toys.lerdorf.com/archives/51-Playing-with-Gearman.html
说是MySQL4.1开始,采用了新的密码验证机制,

查了一些资料(http://hi.baidu.com/cherishtime/blog/item/6136e410652e88f8c3ce799a.html),发现本机上/etc/my.cnf中,有:
[mysqld]
old_password=1
把这一句改成:
old_password=0

启动可以了
(中间犯了很多错误:
1. gearmand@localhost不能登陆MySQL
2. 在处理old-password过程中,修改了密码,后来mysql中密码恢复了,但是gearmand启动中的密码没有修改,结果连接没有报:old insecure authentication,报的是: Access denied for user 'gearmand'@'localhost' (using password: YES)
3. mysql启动有多种方式,如:mysql,mysqld_safe, service mysql start,不同的方式需要读取/etc/my.cnf中的socket配置,配置了不一样造成连接不上mysql


进行测试(原始资料在: gearman-java-0.03-src.tar.gz 中的 README 文档):
client:
java -cp gearman-java-0.03.jar org.gearman.example.ReverseClient -hGearmanServerIP -pPort   随意的字符串
注意:
ReadMe中说,用JDK 5 or  greater,但是实际使用java 1.5.0_10版本执行的时候有问题,用1.5.0_17也不行,最后用的是1.6.0版本的Java

Worker:
java -cp gearman-java-0.03.jar org.gearman.example.WorkerRunner  -hGearmanServerIP -pPort  org.gearman.example.ReverseFunction


用这个例子进行测试:
client运行一次,很快的就返回,查MySQL的表,没有发现有任何记录。
以为是很快的处理完成后,在MySQL中的记录删除了。
把Worker停止,这个应该gearmand会把接收到的任务缓存在MySQL中了吧,
再运行client,client僵住了,等到返回(job.get),
检查MySQL对应的表,还是没有任何数据。

困惑了好久,从Gearmand的JobServer文档上讲:-f参数,通过gearmand -h显示出来的help,-f参数根本就不是那么一回事。
耽搁了很长的一段时间,想到客户端是否有问题:
客户端发送的任务,分为2种情况:
1.需要持久化的, 2.不需要持久化

看ReverseClient 的代码:
代码里发送一个任务用: GearmanJobImpl.createJob
在GearmanJobImpl中,还是有:createBackgroundJob的函数,这个和gearmand的thread说的有点想象:持久化记录的是通过background thread进行记录的。把代码改成createBackgroundJob,运行,在MySQL中对应的表看到了记录(Worker没有开);

用createBackgroundJob和createJob的区别:
createJob的job,用get会堵住的;
createBackgroundJob的job:用get立即返回,即使任务没有进行处理;
2种方式的JobId都是由客户端指定的;(可以用:java.util.UUID.randomUUID().toString()生成一个)

【2009-11-16】
Gearman的high-avaliable:

在文档上的介绍如下:

Now you're probably asking what if the job server dies? You are able torun multiple job servers and have the clients and workers connect tothe first available job server they are configured with. This way ifone job server dies, clients and workers automatically fail over toanother job server. You probably don't want to run too many jobservers, but having two or three is a good idea for redundancy. Thediagram to the left shows how a simple Gearman cluster may look.

From here, you can scale out your clients and workers as needed. Thejob servers can easily handle having hundreds of clients and workersconnected at once. You can draw your own physical (or virtual) machinelines where capacity allows, potentially distributing load to anynumber of machines. For more details on specific uses andinstallations, see the section on use cases.

在多个gearmand服务器之间并不通讯,而是运行多个gearmand服务器,通过client、worker连接多个服务器,如果遇到正在连接的那个故障,由client、worker切换到好用的gearmand服务器,这样来完成high-avliable。

自己试验过了,在50、51上安装了2台gearmand(其实可以一台机器上启动多个进程),在客户端把这2个gearmand都加到GearmanClient中,通过addJobServer的方式。

正常的,GearmanClient会连接第一个JobServer,把job发送过去。
把第一个kill掉,log中报:

警告:received IOException while attempting to initialize sesion GearmanNIOJobServerConnection....
然后自动的采用第二个JobServer,任务发送到第二个JobServer上了。
但是这个只有在首次连接的时候,会进行连接的检查。

如果一个连接已经存在,要重复这个连接的使用,在发送Job的时候,不断的报错,不会自动切换到另一个好的JobServer上。
这个在GearmanClientImpl.submit的时候就会报错
GearmanClientImpl.submit --- > driveRequestTillStae ---> driveClientIO ----> GearmanJobServerSession.driveSessionIO ---->sun.nio.ch.SocketChannelImpl.read 错误
要实现在客户端或者worker端的自动切换,要自己实现,或者修改gearman提供的Java源码。

而且在Gearman网站上提供的图(http://gearman.org/images/gearman_cluster.png),在Client一端,也只有连接一个JobServer,而Worker这一端,连接了2个JobServer,同时给2个JobServer提供服务。

我们要解决的,也就是client ---> JobServer这一端的fail over

【2009-11-17】
对background_job的处理情况的新思考:

在那篇文档上看到的忘了,至少在ClientImpl中有几个方法: 有几个Listen接口,好像是说当background_job处理完成后,JobServer会通知client,就是通过这些Listen接口进行通知的,是不是这样,还需要验证一下。