簡體   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