rabbitmq突破单个队列的瓶颈

本文探讨了RabbitMQ在高QPS下因单个队列导致的性能问题,指出消息大小和队列进程限制了推送速度。通过实例介绍了如何使用多个队列进行消息分流,以提高系统性能。并提供了相关的代码实现和流程图。
摘要由CSDN通过智能技术生成

前言

我们通常谈qps只谈消息数量, 而忽略了每一条消息的大小, 我们知道每一个队列也是一个erlang的进程, 向一个队列里推送消息时, 往往会在队列进程中产生性能瓶颈. 在向一个队列快速发送消息的时候, connection和channel都会处于flow状态, 而队列处于running状态, 在一台CPU主频为2.6hz, 4内核, 8g的内存虚拟机中测试, 发送非持久化大小为10b左右的消息, 发送的qps平均为18k. 如果开启了publisher confirm机制, 持久化消息及增大payload都会降低这个qps的数值.

引入

这里就有了相应的处理办法, 利用多个队列来分流, 画一个流程图:
在这里插入图片描述

代码

基础mq工具类:

@Configuration
@EnableApolloConfig
public class MqUtil {
   

    private final List<Connection> connections = new ArrayList<>();
    private final int maxConnection = 20;

    @Value("${mq.calltopay.rabbit.host}")
    private String host;

    @Value("${mq.calltopay.rabbit.port}")
    private int port;

    @Value("${mq.calltopay.rabbit.username}")
    private String username;

    @Value("${mq.calltopay.rabbit.password}")
    private String password;

    @Autowired
    @Qualifier("mqConnectionFactory")
    public ConnectionFactory factory;

    @Bean(name = "mqConnectionFactory")
    public ConnectionFactory getRabbitMqConnection() {
   
        return getFactory();
    }

    public ConnectionFactory getFactory() {
   
        initFactory();
        return factory;
    }

    private void initFactory() {
   
        try {
   
            if (factory == null) {
   
                factory = new ConnectionFactory();
                factory.setHost(host);
                factory.setPort(port);
                factory.setUsername(username);
                factory.setPassword(password);
            }
        } catch (Exception e) {
   
            e.printStackTrace();
        }
    }

    public void sendMsg(String message, String queue) throws Exception {
   
        Connection connection = getConnection();
        Channel channel = connection.createChannel();
        channel.basicPublish("", queue, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes("utf-8"));
        channel.close();
        setConnection(connection);
    }

    public void sendMsg(String message, String exchange, String route) throws Exception {
   
        Connection connection = getConnection();
        Channel channel = connection.createChannel();
        channel.basicPublish(exchange, route, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes("utf-8"));
        channel.close();
        setConnection(connection);
    }

    public GetResponse basicGet(String queue, boolean autoAck) throws Exception {
   
        GetResponse getResponse = null;
        Connection connection = getConnection();
        Channel channel = connection.createChannel();
        getResponse = channel.basicGet(queue, autoAck);
        channel.close();
        setConnection(connection);
        return getResponse;
    }

    public Connection getConnection() throws Exception {
   
        return getAndSetConnection(true, null);
    }

    public void setConnection(Connection connection) throws Exception {
   
        getAndSetConnection(false, connection);
    }

    private synchronized Connection getAndSetConnection(boolean isGet, Connection connection) throws Exception {
   
        if (isGet) {
   
            if (connections.isEmpty()) {
   
                return factory.newConnection();
            }
            Connection newConnection = connections.get(0);
            connections.remove(0);
            if (newConnection.isOpen()) {
   
                return newConnection;
            } else {
   
                return factory.newConnection();
            }
        } else {
   
            if (connections.size() < maxConnection) {
   
                connections.add(connection);
            }
            return null;
        }
    }
}

bean:

public class Message implements Serializable {
   

    private static final long serialVersionUID = 1L;
    private Long msgSeq;
    private String msgBody;
    private Long deliveryTag;

    public Message() {
   
    }

    public Message(Long msgSeq, String msgBody, long deliveryTag) {
   
        this.msgSeq = msgSeq;
        this.msgBody = msgBody;
        this.deliveryTag = deliveryTag;
    }

    public static long getSerialVersionUID() {
   
        return serialVersionUID;
    }

    public Long getMsgSeq() {
   
        return msgSeq;
    }

    public void setMsgSeq(Long msgSeq) {
   
        this.msgSeq = msgSeq;
    }

    public String getMsgBody() {
   
        return msgBody;
    }

    public void setMsgBody(String msgBody) {
   
        this.msgBody 
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值