繁体   English   中英

Spring 启动和异步 RabbitMQ RPC

[英]Spring boot and asynchronous RabbitMQ RPC

我正在尝试实施 RabbitMQ RPC 模式(请求/响应)。

这对我来说是全新的技术。 所以我很难过。

这是一个 web 应用程序,内置于 spring 启动。

结构:

  • 用户用一些信息填写表单并提交表单,调用处理 controller 例如@{/processUser}

  • Object 将表单中的信息发送到 RabbitMQ 队列

  • 响应部分发生在其他 spring 项目服务中,即获取请求、构建响应并将其发回。

  • 建筑响应应该在给定的时间范围内对另一个 spring 项目做另一个用户,如果没有,则发回通用响应。

所以我假设响应代码,因为它需要在一个线程上等待整个时间请求,我需要主线程运行 spring 启动应用程序,应该在后台的单独线程上。 因为我需要它是异步的。

这段代码按照我的意愿“异步”工作,但我觉得有更好的方法我只是不知道。 我不知道这个匿名线程将如何处理多个使用 web 应用程序的用户。 它不需要完美,但可以接受:)

下面的代码没有完成,也没有完成所有的事情(发送 object,动态做出响应......)这只是测试阶段。

请求代码:

public  String call(String message) throws Exception{
          final String corrID = UUID.randomUUID().toString();

        String replayQueueName = channel.queueDeclare().getQueue();
        AMQP.BasicProperties props = new AMQP.BasicProperties.Builder().correlationId(corrID).replyTo(replayQueueName).build();

        channel.basicPublish("", requestQueueName,props,message.getBytes());

        final BlockingQueue<String> response = new ArrayBlockingQueue<>(1);
        String ctag = channel.basicConsume(replayQueueName, true, (consumerTag, delivery) -> {
            if (delivery.getProperties().getCorrelationId().equals(corrID)) {
                response.offer(new String(delivery.getBody(), "UTF-8"));
            }
        }, consumerTag -> {
        });
        String result  = response.take();
        channel.basicCancel(ctag);
        return result;

并且在处理controller时调用了这个方法:

try(Connection connection = factory.newConnection()){
            channel = connection.createChannel();
            System.out.println("Sending request...");

            String response = call("Test_Message");
            System.out.println(response);

        }catch (Exception e){
            e.printStackTrace();
        }

响应代码:

@Bean
    public ConnectionFactory startFactory(){
        return new ConnectionFactory();
    }

    @Bean
    public Connection startCon(ConnectionFactory factory) throws Exception{
        return  factory.newConnection();
    }

    @Bean
    public void reciver(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{

                    Channel channel = connection.createChannel();
                    channel.queueDeclare(RPC_QUEUE_NAME,false,false,false,null);
                    channel.queuePurge(RPC_QUEUE_NAME);

                    channel.basicQos(1);

                    System.out.println("Awaiting rpc requests");

                    Object monitor = new Object();
                    DeliverCallback deliverCallback = (consumerTag, delivery) ->{
                        AMQP.BasicProperties replayProps = new AMQP.BasicProperties.Builder()
                                .correlationId(delivery.getProperties().getCorrelationId())
                                .build();
                        String response = "RESPONSE_TESTING";
                        String message = new String(delivery.getBody(),"UTF-8");
                        System.out.println(message);
                        channel.basicPublish("",delivery.getProperties().getReplyTo(), replayProps, response.getBytes());
                        channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
                        synchronized (monitor){
                            monitor.notify();
                        }

                    };
                    channel.basicConsume(RPC_QUEUE_NAME, false, deliverCallback, (consumerTag -> {}));
                    while(true){
                        synchronized (monitor){
                            try{
                                monitor.wait();
                            }catch (InterruptedException e){
                                e.printStackTrace();
                            }
                        }
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }

            }
        }).start();



    }

我不太确定您要在这里实现什么目标,但是鉴于您提供的代码,您似乎正在尝试重新发明轮子。 由于您使用的是spring-boot ,因此无需创建能够运行异步以使用消息的整个基础架构。

这已经由 Spring 作为开箱即用的spring-amqp-starter的一部分提供。 例如,在这种情况下,您不必手动轮询队列来获取响应,因为此操作由已声明的RabbitListener处理。

我建议您通读文档和各种示例,以便更好地了解如何使用 Rabbit。 您可以在此处此处查看

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM