资讯动态

我用ChatGPT,给RabbitMQ加了个连接池

发布时间:2026/9/4 7:35:40 来源:尧图企业网站定制
上次我把 RabbitMQ 集成到项目中但是每次使用 RabbitMQ 时都去 New 一个连接导致并发起不来所以这次我们就给 RabbitMQ 加一个连接池。为了偷个懒我直接用 ChatGPT 教我加。01 ChatGPT 生成的代码我输入的关键字如下rabbitmq 实现一个连接池 java下面是 GhatGPT 4.0 给我的回复以下是在Java中使用连接池创建RabbitMQ连接的示例 首先需要添加pika客户端依赖项例如 dependency groupIdcom.rabbitmq/groupId artifactIdamqp-client/artifactId version5.9.0/version /dependency 创建一个RabbitMQ连接类 import com.rabbitmq.client.Connection; public class RabbitMQConnection { private Connection connection; public RabbitMQConnection(String host, int port, String username, String password) { ConnectionFactory factory new ConnectionFactory(); factory.setHost(host); factory.setPort(port); factory.setUsername(username); factory.setPassword(password); try { connection factory.newConnection(); } catch (IOException | TimeoutException e) { e.printStackTrace(); } } public Connection getConnection() { return connection; } public void close() { try { connection.close(); } catch (IOException e) { e.printStackTrace(); } } } 创建一个RabbitMQ连接池类 import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class RabbitMQConnectionPool { private final BlockingQueueRabbitMQConnection pool; public RabbitMQConnectionPool(String host, int port, String username, String password, int poolSize) { pool new LinkedBlockingQueue(poolSize); for (int i 0; i poolSize; i) { pool.add(new RabbitMQConnection(host, port, username, password)); } } public RabbitMQConnection getConnection() throws InterruptedException { return pool.take(); } public void returnConnection(RabbitMQConnection connection) { pool.add(connection); } public void close() { pool.forEach(RabbitMQConnection::close); } } 创建一个消费者类 import com.rabbitmq.client.*; public class RabbitMQConsumer implements Runnable { private final RabbitMQConnectionPool connectionPool; private final String queueName; public RabbitMQConsumer(RabbitMQConnectionPool connectionPool, String queueName) { this.connectionPool connectionPool; this.queueName queueName; } Override public void run() { try { Connection connection connectionPool.getConnection().getConnection(); Channel channel connection.createChannel(); channel.queueDeclare(queueName, false, false, false, null); channel.basicConsume(queueName, true, (consumerTag, delivery) - { String message new String(delivery.getBody(), UTF-8); System.out.println(Received message: message); }, consumerTag - {}); } catch (InterruptedException | IOException e) { e.printStackTrace(); } } } 创建一个生产者类 import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.MessageProperties; public class RabbitMQProducer { private final RabbitMQConnectionPool connectionPool; private final String queueName; public RabbitMQProducer(RabbitMQConnectionPool connectionPool, String queueName) { this.connectionPool connectionPool; this.queueName queueName; } public void send(String message) { try { Connection connection connectionPool.getConnection().getConnection(); Channel channel connection.createChannel(); channel.queueDeclare(queueName, false, false, false, null); channel.basicPublish(, queueName, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes()); System.out.println(Sent message: message); channel.close(); connection.close(); } catch (InterruptedException|IOException e) { e.printStackTrace(); } } } 创建一个RabbitMQ连接池和多个消费者来消费队列 public class Main { public static void main(String[] args) throws InterruptedException { RabbitMQConnectionPool connectionPool new RabbitMQConnectionPool(localhost, 5672, guest, guest, 10); RabbitMQProducer producer new RabbitMQProducer(connectionPool, hello); producer.send(Hello, world!); RabbitMQConsumer consumer1 new RabbitMQConsumer(connectionPool, hello); Thread thread1 new Thread(consumer1); thread1.start(); RabbitMQConsumer consumer2 new RabbitMQConsumer(connectionPool, hello); Thread thread2 new Thread(consumer2); thread2.start(); thread1.join(); thread2.join(); connectionPool.close(); } } 该示例代码创建了大小为10的连接池并创建了两个消费者线程来消费队列并使用一个生产者向队列发送消息。每个消费者从连接池获取连接并消费队列中的消息当完成任务后将连接还回连接池。在实际部署中您需要根据您的应用程序需求选择合适大小的池并调整代码以使用正确的参数。我靠这代码写的真牛逼我需要做的事情就是把里面连接池的部分集成到我的项目中。02 给 RabbitMQ 加连接池2.1 加入连接池之前我们给 ConnectionFactory 加了个单例工厂具体可以参考我上一篇文章由于我们有连接池所以这个单例工厂就直接废弃了。/** * author Louzai * date 2023/5/10 */ public class RabbitmqConnection { private Connection connection; public RabbitmqConnection(String host, int port, String userName, String password, String virtualhost) { ConnectionFactory connectionFactory new ConnectionFactory(); connectionFactory.setHost(host); connectionFactory.setPort(port); connectionFactory.setUsername(userName); connectionFactory.setPassword(password); connectionFactory.setVirtualHost(virtualhost); try { connection connectionFactory.newConnection(); } catch (IOException | TimeoutException e) { e.printStackTrace(); } } /** * 获取链接 * * return */ public Connection getConnection() { return connection; } /** * 关闭链接 * */ public void close() { try { connection.close(); } catch (IOException e) { e.printStackTrace(); } } }这个代码就是 ChatGPT 给我写的我是直接 Copy 过来然后稍微改动了一下。public class RabbitmqConnectionPool { private static BlockingQueueRabbitmqConnection pool; public static void initRabbitmqConnectionPool(String host, int port, String userName, String password, String virtualhost, Integer poolSize) { pool new LinkedBlockingQueue(poolSize); for (int i 0; i poolSize; i) { pool.add(new RabbitmqConnection(host, port, userName, password, virtualhost)); } } public static RabbitmqConnection getConnection() throws InterruptedException { return pool.take(); } public static void returnConnection(RabbitmqConnection connection) { pool.add(connection); } public static void close() { pool.forEach(RabbitmqConnection::close); } }2.2 RabbitMQ 发送消费消息RabbitMQ 发送消息从连接池拿到连接 - 创建通道 - 声明交换机 - 发送消息 - 将连接归还连接池。这里的逻辑基本和之前的一样只是之前是 New 一个连接现在是直接从连接池拿到连接然后最后多了一步归还连接的操作。Override public void publishMsg(String exchange, BuiltinExchangeType exchangeType, String toutingKey, String message) { try { //创建连接 RabbitmqConnection rabbitmqConnection RabbitmqConnectionPool.getConnection(); Connection connection rabbitmqConnection.getConnection(); //创建消息通道 Channel channel connection.createChannel(); // 声明exchange中的消息为可持久化不自动删除 channel.exchangeDeclare(exchange, exchangeType, true, false, null); // 发布消息 channel.basicPublish(exchange, toutingKey, null, message.getBytes()); System.out.println(Publish msg: message); channel.close(); RabbitmqConnectionPool.returnConnection(rabbitmqConnection); } catch (InterruptedException | IOException | TimeoutException e) { e.printStackTrace(); } }RabbitMQ 消费消息从连接池拿到连接 - 创建通道 - 确定消息队列 - 绑定队列到交换机 - 接受并消费消息 - 将连接归还连接池。同上这里的逻辑基本和之前的一样只是多了一个拿连接和归还连接的过程。Override public void consumerMsg(String exchange, String queueName, String routingKey) { try { //创建连接 RabbitmqConnection rabbitmqConnection RabbitmqConnectionPool.getConnection(); Connection connection rabbitmqConnection.getConnection(); //创建消息信道 final Channel channel connection.createChannel(); //消息队列 channel.queueDeclare(queueName, true, false, false, null); //绑定队列到交换机 channel.queueBind(queueName, exchange, routingKey); Consumer consumer new DefaultConsumer(channel) { Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { String message new String(body, UTF-8); System.out.println(Consumer msg: message); // 获取Rabbitmq消息并保存到DB // 说明这里仅作为示例如果有多种类型的消息可以根据消息判定简单的用 if...else 处理复杂的用工厂 策略模式 notifyService.saveArticleNotify(JsonUtil.toObj(message, UserFootDO.class), NotifyTypeEnum.PRAISE); channel.basicAck(envelope.getDeliveryTag(), false); } }; // 取消自动ack channel.basicConsume(queueName, false, consumer); RabbitmqConnectionPool.returnConnection(rabbitmqConnection); } catch (InterruptedException | IOException e) { e.printStackTrace(); } }这个代码其实 ChatGPT 写的有问题你再回过头去看 ChatGPT 写的代码发现连接取出但是没有归还那会出现什么问题呢这里给大家分析一下由于我们的连接池用的是 BlockingQueue连接池大小是 5如果连接全部取出并都不归还当第 6 个请求过来后请求就卡住了导致界面操作会被阻塞请求完全没有反应。不要问我怎么知道因为我是踩坑过来的。2.3 代码仓库为了方便大家学习功能演变的过程每个模块都会单独开个分支连接池的分支和仓库如下代码仓库https://github.com/itwanger/paicoding代码分支feature/rabbitmq_connection_pool_20230511如果需要运行 RabbitMQ下面的配置需要改成 true因为代码默认是 false。3 实际效果我们是把技术派的“点赞”功能消息通过 RabbitMQ 方式处理我们多次点击“点赞”按钮触发 RammitMQ 消息发送。可以通过日志也可以看到发送和消费过的消息。最后就是大家关心的连接池个数打开 RabbitMQ 后台发现永远只有 5 个连接和我们的连接池大小一致符合预期。再看看打开的 Channel由于每次都关闭所以也没有了也符合预期。这里抛个疑问每次新开一个 Channel用完后关闭是不是也很耗时是否需要给 Channel 也搞一个连接池呢可以评论区告诉我哈~~4 后记如果用 ChatGPT 3.5给的结果就不一样需要加入更多关键字如果需要达到 GhatGPT 4.0 给的结果你需要给 ChatGPT 3.5 以下关键字。rabbitmq 用BlockingQueue实现一个连接池 java再回到 RabbitMQ 本身上一篇文章只是告诉大家 RabbitMQ 的基本原理以及如何集成 RabbitMQ这篇文章主要教大家加连接池其实这个示例里面可以加的东西还很多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价