一 RibbitMQ
RabbitMQ 是一个开源的 AMQP(高级消息队列协议) 实现,服务器端用Erlang语言编写.
相关概念
持久化
RabbitMQ的持久化是在消费确认前的持久,在消费确认后还是会删除。
虚拟主机
一个虚拟主机持有一组交换机、队列和绑定。为什么需要多个虚拟主机呢?很简单, RabbitMQ 当中,用户只能在虚拟主机的粒度进行权限控制。 因此,如果需要禁止A组访问B组的交换机/队列/绑定,必须为A和B分别创建一个虚拟主机。每一个 RabbitMQ 服务器都有一个默认的虚拟主机“/”。
交换机
Exchange 用于转发消息,但是它不会做存储 ,如果没有 Queue bind 到 Exchange 的话,它会直接丢弃掉 Producer 发送过来的消息。
这里有一个比较重要的概念:路由键 。消息到交换机的时候,交互机会转发到对应的队列中,那么究竟转发到哪个队列,就要根据该路由键。
- Direct:(默认)“先匹配, 再投送”. 即在绑定时设定一个 routing_key, 消息的routing_key 匹配时, 才会被交换器投送到绑定的队列中去.可以多个队列绑定同一个交换机,但是在同一时间只有一个队列能拿到消息。
- Topic:按规则转发消息(最灵活)。根据通配符来转发,其他和direct类似。*可以匹配句点之间的字符,#可以匹配任意字符,包括句点。
- Headers:设置 header attribute 参数类型的交换机,根据消息中的headers属性和队列与交换机绑定时候设定的键值对规则匹配,x-match参数可以有any和all,any是只要有一组键值对匹配上就会发送消息到相应队列,all则需所有键值对都匹配上才可以。
- Fanout:转发消息到所有绑定队列,不管所有规则,只要绑定了就会发送。
注
headers表越大性能越差
绑定
也就是交换机需要和队列相绑定,是多对多的关系。
Default Exchange
rabbitTemplate.convertAndSend(“hello rabbit”);这种没有路由健的消息会丢失,不会给到任何queue --> mandatory
rabbitTemplate.convertAndSend(“simpleQueue”, “hello simple”); 指定了routing key 发送给指定的queue
rabbitTemplate.convertAndSend(“testQueue”, “hello testQueue”); 如果同一个queue有多个消费者 会按prefetch均匀分配
properties属性
消息发布的性能权衡
- 平衡投递速度和可靠投递
- 使用mandatory设置,正确投递不会有相应,错误投递会抛异常。(待确认)
- 发布者确认,不与事务一起工作,是事务的轻量化代替方案
- 备用交换器,错误的消息会被你设置的路由到死信队列(dead-letter)如果此时设置了mandatory标志也不会给发布者返回信息,而是被认为正确投递。exhange的alternate-exchange
- HA队列(集群模式)来避免单点故障
- delivery-mode=2来持久化消息,性能影响比较大;可以增加RAM,以便将磁盘页面保留在内核磁盘缓存中。
- TCP背压和连接阻塞,阻止单点发布者的恶意请求或者异常(太多)请求
消息接收的性能权衡
- 尽量不使用主动拉取,而是使用监听
- 使用no-ack会提高性能,却会丢失消息,权衡点:prefetch的大小
- QoS,服务质量,调整预取值到合适
- 一次确认多条消息性能比单条提升1.5倍(在预取量达到1000及以上)
- 事务,不适用于金庸确认的消费者,影响性能不过在不设置qos时,使用事务批量确认消息时性能有略微提升
- reject-拒绝单条消息可以设置redelivered重新投递或者丢弃,Nack批量不确认
- 死信交换器,过期或者被拒绝的消息,当作queue的x-dead-letter-exchange参数传入即可
- 自动删除队列auto-delete=true,单消费者队列exclusivetrue,自动过期队列x-expires=毫秒
队列的参数设置
消费顺序
为了保证消费顺序,rabbitmq可以使用queue和consumer一一对应的关联,虽然queue多了一点但是利用了queue的队列达到了消息的顺序行,在consumer内部也可以维护一个队列来保证顺序。–这样影响了性能
RocketMQ通过轮询所有队列的方式来确定消息被发送到哪一个队列(负载均衡策略)。比如下面的示例中,订单号相同的消息会被先后发送到同一个队列中:
// RocketMQ通过MessageQueueSelector中实现的算法来确定消息发送到哪一个队列上
// RocketMQ默认提供了两种MessageQ