I'm trying to implement RabbitMQ RPC pattern (Request/Response).
It's totally new technology to me. So I am having a hard time.
It's a web app, built in spring boot.
Structure:
A user fills a form with some information and submits form, that invokes processing controller eg @{/processUser}
Object with that information from the form is sent to RabbitMQ queue
Response part is happening in other spring project service, that gets request, build response and sends it back.
Building response should do another User on that other spring project in given time frame, if not, generic response is sent back.
So I assumed that code for response, because it needs to wait on one thread whole time for request and I need main thread for spring boot application to run, should be on separated thread in background. Because I need it to be asynchronous.
This code works "asynchronously" as I want, but I have feeling that there is much better way that I just don't know. I don't know how this anonymous thread will behave with multiple users using web app. It doesn't need to be perfect, but acceptable:)
Code below is not finished and NOT doing the whole thing (sending object, making a response dynamically...) It's just test phase.
Code for Request:
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;
And this method is called in that processing 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();
}
Code for response:
@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();
}
I am not really sure what you are trying to achieve here, but given the code you provided it seems that you are trying to re-invent the wheel. Since you are using spring-boot
, there is no need to create a whole infrastructure capable of running async to consume messages.
This is already offered by Spring as part of the spring-amqp-starter
out of the box. For example in that case you won't have to manually poll the queue in order to get back response, since this action is handled by a declated RabbitListener
.
I suggest you do through the documentation as well as the various examples in order to get a better feel on how to use Rabbit. You can check those here and here .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.