2014年7月11日星期五

RabbitMQ - Task Queue in Java

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
RabbitMQ - Task Queue in Java  阅读原文»

RabbitMQ - Task Queue in Java

这次我们试着实现这样一个小程序:

wKioL1O898eRR0jzAAA4OcHQx40945.jpg

嗯,就是任务队列(task queue)。

不是将任务集中在一堆并一直等到所有任务一并完成为止,而是将每一个任务封装为一个消息,并将其发送到队列,后台的workers就从队列中分担工作。

web应用尤其喜欢这种处理方式,比如面对一个请求时我们有一大堆复杂逻辑需要处理,而我们却不需要立即响应处理结果,那就放到后面慢慢弄。

(PS:另外也有直接对任务进行持久化,然后用scheduler什么的去定时处理。无论如何,没有银弹。)

对于复杂的任务,我们可以用Thread.sleep模拟一下。

比如provider每发一个"hello...",worker读到消息后开始数点,每读到一个"."就睡一会儿。

provider也简单模拟一下,一次塞个20个消息到队列:

publicstaticvoidmain(String[]argv)throwsjava.io.IOException{
ConnectionFactoryfactory=newConnectionFactory();
factory.setHost("localhost");
Connectionconnection=factory.newConnection();
Channelchannel=connection.createChannel();
channel.queueDeclare(TASK_QUEUE_NAME,true,false,false,null);
Stringmessage="Hello...";
for(inti=0;i<20;i++){
channel.basicPublish("",TASK_QUEUE_NAME,
MessageProperties.PERSISTENT_TEXT_PLAIN,message.concat(i+1+"").getBytes());
System.out.println("[x]Sent'"+message+(i+1)+"'"
+(i+1)+"times");
channel.close();
connection.close();

有一个需要注意的地方,就是consumer揽了活后没干完就死掉了。

我需要其他还活着的consumer替死者完成工作。

RabbitMQ支持消息应答,如果worder没有做出应答却死掉了,provider则会将消息重新发给其他活着的consumer。

但这个和timeout无关,只有在worker的connection断掉时才会重新发送。

如果调用了没有autoAck参数的basicConsume,消息应答默认是启用的,也就是autoAck=false。

booleanautoAck=false;
channel.basicConsume(TASK_QUEUE_NAME,autoAck,consumer);

当autoAck==false时需要我们显示调用channel.basicAck方法将接收的消息ack一下。

如果接收了消息却不显示调用应答方法,就不能再接收新的消息,这就造成了浪费。

另外,如果设置了autoAck就不要显示进行应答,否则会来一个com.rabbitmq.client.ShutdownSignalException。

consumer死了有其他人处理后事,那整个server死掉了怎么办?

为了让消息不丢失,我们需要将队列和消息标记为durable。

booleandurable=true;
channel.queueDeclare("hello",durable,false,false,null);

好了,这样即使重启RabbitMQ服务也不会丢失队列。

但这并不保证消息不会丢失,为了保证这一点,我们在provider发布消息时加了essageProperties.PERSISTENT_TEXT_PLAIN:

channel.basicPublish("",TASK_QUEUE_NAME,
MessageProperties.PERSISTENT_TEXT_PLAIN,message.concat(i+1+"").getBytes());

虽然这种方式并不完美,我们还需要做其他的一些工作,但暂时先到这里。

最后一个问题是,如何做到给consumer公平分配任务。

如果没有做这个处理,会出现这样一种情况。

举个例子:provider发送了20个消息,随即启动的consumer_1把这20个消息全都独占了。

在consumer_1工作期间又有consumer_2被启动,但此时consumer_2没有任何任务。

此时provider又发送了20个消息,这时consumer_2会得到10个任务。

我们可以使用channel.basicQos(int prefetchCount)方法限制预获取的数量,比如prefetchCount==1就是返回应答后可以再获得1个消息。

好了,consumer代码如下:

publicclassWorker{
GitLab安装篇-Ubuntu 14.04 LTS  阅读原文»

GitLab安装篇-Ubuntu 14.04 LTS

GitLab 是一个用于仓库管理系统的开源项目。使用Git作为代码管理工具,并在此基础上搭建起来的web服务。它提供Git版本控制、代码检查、Bug跟踪和Wiki,它可以通过LDAP或活动目录来进行安全认证和授权。单个GitLab可以支持25000个用户,同时它也可以通过设置多台服务器来实现其高可用性。GitLab并没有被收入到Ubuntu14.04软件库中,但安装GitLab却也十分方便,下面讲讲如何安装GitLab:

首先照着GitLab的官方文档,输入以下命令:

wget-chttps://downloads-packages.s3.amazonaws.com/ubuntu-14.04/gitlab_7.0.0-omnibus-1_amd64.deb
sudoapt-getinstallopenssh-server
sudoapt-getinstallpostfix
sudodpkg-igitlab_7.0.0-omnibus-1_amd64.deb

因为GitLab这个包的地址下载速度很慢,还经常出现断点,所以在wget后加上了-c这个参数。安装openssh-server这句其实可以去掉,因为我一般都是在安装服务器的时候就勾选安装了这个服务,毕竟需要远程登录服务器嘛!Postfix是邮件服务,如果不安装这个服务的话,也可以安装Sendmail或Exim等相似的邮件服务(如果有邮件服务器的话,这一步可以忽略,可以通过gitlab-ctl来重配置SMTP服务)。

接下来是设置GitLab的域名:

sudomkdir-p/etc/gitlab
sudotouch/etc/gitlab/gitlab.rb
sudochmod600/etc/gitlab/gitlab.rb
sudovi/etc/gitlab/gitlab.rb

然后添加一条域名配置:

external_url"www.hostname.com"
#如果没有安装Postfix或Sendmail这类邮件服务的话,那么就需要象邮件客户端那样根据SMTP服务器的参数来设置以下的内容了
gitlab_rails['smtp_enable']=true
gitlab_rails['smtp_address']="smtp.server"
gitlab_rails['smtp_port']=456
gitlab_rails['smtp_user_name']="smtpuser"
gitlab_rails['smtp_password']="smtppassword"
gitlab_rails['smtp_domain']="example.com"
gitlab_rails['smtp_authentication']="login"
gitlab_rails['smtp_enable_starttls_auto']=true

然后对GitLab进行重配置即可:

sudogitlab-ctlreconfigure

注意:正如GitLab大多数配置文件(如gitlab.yml或database.yml等)中所注释的那样:

#Thisfileismanagedbygitlab-ctl.Manualchangeswillbe
#erased!Tochangethecontentsbelow,edit/etc/gitlab/gitlab.rb
#andrun`sudogitlab-ctlreconfigure`.

在GitLab中的大部分关于配置方面的修改,现在都需要在/etc/gitlab/gitlab.rb中进行设置,然后再运行sudo gitlab-ctl reconfigure进行修改。

如果对如何配置gitlab.rb有兴趣的话,可以参见:https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md这个网址,基本上已经讲得很清楚了。

接下来就是检测是否安装成功了,可以输入下面的命令:

sudogitlab-ctlstatus
[sudo]passwordforfirehare:
run:nginx:(pid13334)16103s;run:log:(pid4244)22211s
run:postgresql:(pid4153)22280s;run:log:(pid4152)22280s
run:redis:(pid4070)22291s;run:log:(pid4069)22291s
run:sidekiq:(pid4234)22212s;run:log:(pid4233)22212s
run:unicorn:(pid4212)22218s;run:log:(pid4211)22218s

如果得到与上面相似的结果,那么说明你安装成功。

由于GitLab包自带了Ruby、Rails和PostgreSQL,所以也就不需要象以前那样考虑兼容性的问题了。最后只需要直接登录GitLab所在的服务器,并使用帐号root,密码5iveL!fe来登录GitLab。首次登录GitLab会强行让你重置密码,然后就可以进入GitLab了。

本文出自 "野火兔的窝" 博客,请务必保留此出处http://firehare.blog.51cto.com/809276/

阅读更多内容

没有评论:

发表评论