Consumer的高级特性
独有消费者:
Consumer消息的异步分发:
Consumer的优先级:
管理持久化消息:
持久化发送端:
持久化接收端:
运行程序,从界面上查看订阅者,20秒之后再刷新界面就可以看到这个不活跃的订阅者就会消失:
消息分组:
前面讲了使用queue消息的时候,如果消息队列中有1,2,3,共3个消息,此时如果是并发的线程来拿消息进行消费,会出现消息顺序不一致的情况,为了防止这种情况使用独有消费者,但是会有性能上的问题,所以考虑使用消息分组。
发送端:
接收端:
运行接收端和发送端,从运行结果中可以看的出来,虽然有两个接收端,但是因为设置了分组,所以发送的所有消息只会给一个消费者。现在修改一下发送端,我们让发送端发给不同的组,那这些消息就会根据组的不同被不同的消费者消费,看运行的结果:
所以使用消息分组,一个组的消息就会给一个消费者,这一个组的消息不会被分发给不同的消费者。不同的组的消息会发给不同的消费者。
实际上这个组用完就关闭了,所以这里的关闭实际上是没有什么用的。
消息选择器(消息过滤):
使用上一节讲的消息分组的发送端和接收端。修改发送端:
修改接收端:
因为使用了过滤条件,所以运行程序之后可以看的出来是没有信息的。虽然消费者不接受不满足自己条件的消息,但是消息还是在Activemq队列中的,如果现在修改一下接收端,直接只运行接收端,就可以接收到(原来的消息还在队列中):
重新传递消息策略:
现在来测试一下默认的重传次数,用以前写过的一个发送端:
先把接收端的session.commit注释掉。然后运行程序,通过测试可以发现,我们运行一次发送端,运行n次接收端,因为把接收端的session.commit注释了,所以开启了很多次的接收端还是可以接收到消息,这是因为接收端的session.commit注释了,所以即使消费端消费了消息,在消息队列中还是不会清除掉已经消费的消息,还是会存在,所以可以一直接收到消息:
但是消费端一直消费到第7次以后的时候就不能再接受了,因为默认的重传次数是6,超过7就不能接受了:
从web界面中可以看到那个DLQ队列:
现在来测试使用消息重传策略。修改消费端,设置的重传次数是3:
现在重新来测试,启动消费端,启动生产端,消费者一共接受了4次消息,再次启动消费者的时候就接受不到了,因为已经达到重传次数了。观察web界面中的死消息的队列的时候就可以看到多的消息了:
可以自动删除过期消息:
当然也可以为每一个topic或者queue的目的地设置重传策略:
慢消费者处理:
在配置文件中可以看到默认是1000:
监控和管理Broker
第一种方式:这种方式就是我们常说的web界面:
第二种方式:这是ActiveMQ5.9以后可以使用的:
这里有很多可以查询或者使用的功能:
集成ActiveMQ和Tomcat
就是说把ActiveMQ嵌入到Tomcat中去跑,而不是作为一个单独的程序应用运行。其实一般的情况下是不希望两者结合使用的,因为单独用ActiveMQ可以很方便的做修改和扩展,但是如果有要使用ActiveMQ和tomcat结合的需求的时候可以用。结合之后就希望ActiveMQ是尽量不要经常变化的了。现在来操作一下,修改里面的web.xml内容:
在tomcat中加入spring和xbean的包。下面的除了default包以外的spring和xbean的包都是需要加入到Linux上的tomcat中的,所以这些包在windows上指定一个位置处放好:
通过下面的命令将windows上的spring和xbean的包传入到linux的tomcat上(选中的是里面的jar包):
ActiveMQ的使用场景
- 异步:提高速度和性能的
- 一对多,消费者那一端不用管他是否在线这些
- 不同系统之间的通信,即使这两个系统是在不同的机器上,即使这两个系统用不同的语言开发的都没有关系,通过远程的ActiveMQ就可以实现通信。
4.作为RPC的替代:就是远程过程的调用。
如果A,B在同一个虚拟机中那么他们可以随便的通信,但是如果不在同一个机器上,就要通过RPC框架。ActiveMQ就相当于RPC。比如A要调用B的方法,那么A就给ActiveMQ发一个消息,B就会执行相应的方法,然后A给ActiveMQ发消息说要得到返回结果,然后B就把结果告诉A。
ActiveMQ的优化
ActiveMQ结合业务
一般就是适合于高并发量的,插入修改等复杂业务逻辑的时候使用,如果是高并发的访问适合用memcache这些。上面的例子:如果生成订单,如果同时有很大的并发量要求生成订单,一个服务器压力是很大的,那么每个客户那边反应就会很慢,所以使用ActiveMQ,将客户的生成订单的请求放在队列中,可以很快的放进去,然后如果并发量很大的时候可以有多个消费者从队列中拿请求做处理。所以这个时候对于客户来说反应是很快的,真正处理业务逻辑的就是一个个的消费者了。
那ActiveMQ如何我们的应用进行结合呢?
- 第一种方式是将ActiveMQ内嵌进Eclipse中,然后在Tomcat中一起启动
- 第二种方式是将ActiveMQ作为一个中间件独立的去使用
一般我们使用这种异步的组件的时候还是用第二种方式,方便以后扩展或其他的使用。第二种方式就是单独的启动ActiveMQ。就是将service中的一堆的处理逻辑作为Consumer。然后还要考虑用queueu还是用topic,这里我们用的是queue。当然我们一个service中有很多的业务处理逻辑,所以可以搞多个消费者的线程一起处理。
现在有一个业务,接收消费者的Id,下订单:
现在使用ActiveMQ的消息:
service的方法就可以直接使用ActiveMQ消息了:
现在来写消费端。这里面就是当时具体的service中的业务逻辑,因为下面具体的业务逻辑中需要的uuid是从发送端发送过来的,所以接收端要首先接受一下:
消费者的一端可以用多线程的方式,如果有需要共享的资源就要加上锁,注意加锁是为哪个加锁,不能随便使用this。
所以为了想在web应用启动的时候接收端就创建好,有两种方式,第一种是把接收端做成Lister(就是和配置Spring的监听器类似,在web.xml中把service配置好),另一种方式是让web容器启动的时候就把spring相关的service都创建好,这样就把接收端也创建好了。
现在我们来试试第二种方式,让我们的接收端实现监听器,并且加上注解,让web容器创建的时候spring就把这个接收端创建,好:
修改接收端,去掉session的关闭:
不关闭连接这样服务器就是一直开着的,只要有消息就会进行接受。我们这里就是把接收端做成一个服务了,是为了方便起见,当然也可以根据实际的业务需要做修改。
第一种方式:将接收端作为监听器
实现监听器接口,就要实现初始化和销毁的方法,初始化做的就是让接收端打开连接:
然后在web应用的web.xml中把监听器配置上,名字要对应,注意:我们的接收端的Listener要放在spring的监听器的后面,因为只有spring创建成功了,才能创建它管理的接收端和service:
现在分析一下。我们一共有3个部分,业务的service,发送端和接收端,我们把接收端做成了监听器,不用我们手动启动了。
因为我们的接收端做成监听器了,每次启动web容器的时候都会启动监听器,所以接收端就是一直运行的,如果我们把接收端的监听器先去掉,先不让她启动,看一下业务的速度:
这样我们就只管发消息,这样速度明显就快了。根据具体的业务具体处理。