-
Notifications
You must be signed in to change notification settings - Fork 577
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Thread.interrupt() cause message loss and hang for ChannelRpcTimeout(default 10mins) or forever #718
Comments
So what is the suggested change to make this method more interrupt-safe? |
I don't remember off the top of my head why the Since the current contact is currently to ignore interruption, I don't really see why breaking it, especially if the code has a configurable timeout and so a foreseeable behavior. |
Hi, michaelklishin and acogoluegnes. Thanks for your replies. Excuse me, my English is poor. May not be well @@described. In my case, what I want say is that if we discard a message we can tell k.getReply(..) there is no respone to wait,because we don't send the rpc request to the rabbitmq server. So if a message was be discarded, I think that wake up k.getReply(..) immediately and let k.getReply(..) throw a special exception may be better for users. Or,notify the user that the message was discarded, throught a Listener I think ChannelContinuationTimeoutException has at least tow kinds of meaning. |
The semantics here are debatable, but we could try to do an effort if we know the response won't come. The problem is to know that the request has been dropped, and this is more complicated than it sounds. Could you please provide a test case that reproduces the problem you face? @michaelklishin Do you know why |
@acogoluegnes @Test
public void publish() throws IOException, TimeoutException, InterruptedException {
ConnectionFactory factory = createFactory();
final Connection connection = factory.newConnection();
boolean isTx = true;
int msgCount = 1;
BasicProperties properties = new BasicProperties();
AtomicInteger succCount = new AtomicInteger();
AtomicInteger failCount = new AtomicInteger();
int threadCount = 1;
Thread thread = null;
for(int n=0;n<threadCount;n++) {
thread = new Thread(()->{
try {
if(isTx) {
withTx(connection, msgCount, properties, succCount, failCount);
}else {
withNonTx(connection, msgCount, properties, succCount, failCount);
}
} catch (IOException e) {
}
});
thread.start();
}
try(Scanner scanner = new Scanner(System.in);){
while(!"q".equals(scanner.nextLine())) {
thread.interrupt();
}
}
System.out.println(String.format("success count %s ; fail count%s", succCount.get(), failCount.get()));
}
private void withTx(final Connection connection, int msgCount, BasicProperties properties, AtomicInteger succCount, AtomicInteger failCount)
throws IOException {
Channel channel = connection.createChannel();
channel.txSelect();
byte[] bytes = "".getBytes();
long beginTime = System.currentTimeMillis();
for(int i=0;i<msgCount;i++) {
try {
channel.basicPublish("", "LzyTest", properties, bytes);
channel.txCommit();//① set a breakpoint at here
succCount.incrementAndGet();
} catch (IOException e) {
failCount.incrementAndGet();
e.printStackTrace();
}
}
long times = System.currentTimeMillis() - beginTime;
System.out.println(String.format("cost: %s ms avg: %s ms", times, times*1.0 / msgCount));
}
private void withNonTx(final Connection connection, int msgCount, BasicProperties properties, AtomicInteger succCount, AtomicInteger failCount)
throws IOException {
Channel channel = connection.openChannel().get();
byte[] bytes = "".getBytes();
long beginTime = System.currentTimeMillis();
for(int i=0;i<msgCount;i++) {
try {
channel.basicPublish("", "LzyTest", properties, bytes);
succCount.incrementAndGet();
} catch (IOException e) {
failCount.incrementAndGet();
}
}
long times = System.currentTimeMillis() - beginTime;
System.out.println(String.format("cost: %s ms avg: %s ms", times, times*1.0 / msgCount));
}
private ConnectionFactory createFactory() {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("ip");
factory.setPort(5672);
factory.setUsername("username");
factory.setPassword("password");
factory.setConnectionTimeout(100000);
factory.setAutomaticRecoveryEnabled(true);
factory.setNetworkRecoveryInterval(10 * 60 * 1000);
factory.setChannelRpcTimeout(30_000);
factory.useNio();
factory.setNioParams(new NioParams().setNbIoThreads(4));
return factory;
} |
To avoid thread execution for too long, we interrupt the thread after the time limit is reached. Recently, We find that occasionally messages get lost. We use TX mode , and txCommit() got an ChannelContinuationTimeoutException. I found the following problem according to the warning log.
if thread interrupted before rpc(m,k) then rpc will not be sent to the server. And k.getReply(..) will hang for _rpcTimeout or forever.
client version is 5.8.0
The text was updated successfully, but these errors were encountered: