Can I store time in RabbitMQ for call handler in this time? Does RabbitMQ support this?
Yes, it's supported, but only via extra plugin.
There is more dateiled about that
Simply saying you need to install rabbitmq-plugins enable rabbitmq_delayed_message_exchange plugin, and add new header to your message:
byte[] messageBodyBytes = "delayed payload".getBytes();
AMQP.BasicProperties.Builder props = new AMQP.BasicProperties.Builder();
headers = new HashMap<String, Object>();
headers.put("x-delay", 5000);
props.headers(headers);
channel.basicPublish("my-exchange", "", props.build(), messageBodyBytes);
So you need to put x-delay value with milliseconds after this message should be processed.
Related
What I'm using:
spring-data-redis.1.7.0.RELEASE
Lettuce.3.5.0.Final
I configured Spring beans related to Redis as follows:
#Bean
public LettucePool lettucePool() {
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMasIdle(10);
poolConfig.setMinIdle(8);
... // setting others..
return new DefaultLettucePool(host, port, poolConfig)
}
#Bean
public RedisConnectionFactory redisConnectionFactory() {
new LettuceConnectionFactory(lettucePool());
}
#Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<Stirng, Object> redisTemplate = new RedisTemplate<String, Object>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
redisTemplate.setEnableTransactionSupport(true);
... // setting serializers..
return redisTemplate;
}
And redisTemplate Bean is autowired and used for Redis opertions.
The connections look correctly established when I check using an 'info' command via redis-cli. The client count is exactly the same with the value set to the lettucePool Bean + 1. (redis-cli is also a client)
However, my application's log says it sends operation requests through always the one same port. So I checked client status using 'client list' command and it says there are the pooling number of clients and just port is sending requests.
What am I missing?
This is caused by Lettuce's specific feature, 'sharing native connection'.
LettuceConnectionFactory in spring-data-redis has a setter method named setShareNativeConnection(boolean), set to true by default. This means no matter how many connections are created and pooled, only one native connection is used as long as non-blocking and non-transactional operation called.
As you can see, I didn't manually set the value so it was set to the default, 'true' and I had no blocking or transactional operations.
Additionally, the reason why the default value is set to true is that Redis itself is single-threaded, which means even though clients send many operations simultaneously, Redis must execute them one by one, so settings this value to 'false' doesn't mean that it increases Redis' throughput.
We are migrating our Vertx code base from 3.6.3 to 3.8.1.
And I am not sure if the redis pub/sub and the event bus consumers still work together. I couldn't find any documentation in the new version either.
from the 3.5.1 documentation:
vertx.eventBus().<JsonObject>consumer("io.vertx.redis.channel1", received -> {
// do whatever you need to do with your message
JsonObject value = received.body().getJsonObject("value");
// the value is a JSON doc with the following properties
// channel - The channel to which this message was sent
// pattern - Pattern is present if you use psubscribe command and is the pattern that matched this message channel
// message - The message payload
});
RedisClient redis = RedisClient.create(vertx, new RedisOptions());
redis.subscribe("channel1", res -> {
if (res.succeeded()) {
// so something...
}
});
How does this work now with the new Redis client / RedisAPI?
The documentation is not very descriptive. (There s not a subscribe command.. nor a trace of channel1)
You should be able to register a handler for subscriptions io.vertx.redis.client.Redis#handler. Which will be called with an io.vertx.redis.client.Response reference (with corresponding information) for published messages.
I create a consumer base to retrieve each message from RabbitMq. I'm using easynetq to consume the messages in which the consumer is configured by advanced mode because the queue has some different configurations. Once recevied a message a call async method to process each message. However, the consume method in the advanced doesn't have a async consume method. Do I have to call async method using Task.Run or Task.Factory.StartNew methods?
Some process may last long time and erros may occurs during the process. In the error cases, I need to reject the message and let the message into the queue again. When the process is finally complete successfully, the message can accept and remove it from the queue.
That's an example of my code:
var queue = _bus.Advanced.QueueDeclare(_queueName, durable: true);
_consumerResult = _bus.Advanced.Consume(queue, (body, properties, info) =>
{
var message = Encoding.UTF8.GetString(body);
if (string.IsNullOrWhiteSpace(message))
return;
var deserializeObject = JsonConvert.DeserializeObject<IntegrationEvent<T>>(message, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Include,
TypeNameHandling = TypeNameHandling.Auto,
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple
});
deserializeObject.DeliveryTag = info.DeliverTag;
// I need to call a async method
ConsumeAsync(deserializeObject));
});
How I can accept and reject the message manually?
I am trying to create a RabbitMq consumer in Java Spring framework. Where I need to implement RabbitMq RPC model, so basically consumer shall receive some message from RabbitMq broker, process it, and send it back to the associated reply queue.
Can somebody please point me a neat sample code which implements this requirement in Spring ?
Thanks in advance.
Consider using the Spring AMQP Project.
See the documentation about async consumers. You just need to implement a POJO method and use a MessageListenerAdapter (which is inserted by default when using XML configuration) - if your POJO method returns a result, the framework will automatically send the reply to the replyTo in the inbound message, which can be a simple queue name, or exchange/routingKey.
<rabbit:listener-container connection-factory="rabbitConnectionFactory">
<rabbit:listener queues="some.queue" ref="somePojo" method="handle"/>
</rabbit:listener-container>
public class SomePojo {
public String handle(String in) {
return in.toUpperCase();
}
}
Or, you can use the annotation #RabbitListener in your POJO - again, see the documentation.
Thanks Gary, it worked for me. I used #RabbitListener annotation.
Strangely it only works when I provide queue alone, However specifying a binding of exchange, routing key and queue doesn't work. Not sure what the issue here.
Here is client code snippet in python.
#!/usr/bin/env python
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel()
channel.queue_declare(queue='myQueue',durable='true')
channel.basic_publish(exchange='myExchange',
routing_key='rpc_queue',
body='Hello World!')
print " [x] Sent 'Hello World!'"
connection.close()
Here is spring consumer code.
#RabbitListener(
bindings = #QueueBinding(
value = #Queue(value = "myQueue", durable = "true"),
exchange = #Exchange(value = "myExchange"),
key = "rpc_queue")
)
public void processOrder(Message message) {
String messageBody= new String(message.getBody());
System.out.println("Received : "+messageBody);
}
Not sure whats going wrong with this binding.
I am new to rabbitmq and I am trying to send a .sh file in rabbitmq. I have setup my queue and exchanges. I am using spring-amqp and I can send json messages with my listerner container
public SimpleMessageListenerContainer messageListenerContainer() {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
container.setQueues(topicQueue());
container.setAcknowledgeMode(AcknowledgeMode.AUTO);
container.setMessageListener(new MessageListenerAdapter(pageListener(), jsonMessageConverter()));
return container;
}
but I am not sure how to send a sh file and write it in my pagelistener. Any idea how to do it?
You need to read the file and send the content.
You can use a SimpleMessageConverter (the default) and if the content_type property is text/plain, you'll get a String; otherwise you'll get a byte[].
On the receiving side (presumably) you'd have to write it to a file and set the permissions.