mina framework uses reentrant lock to realize message retransmission

Some time ago, when using mina, session.getConfig().setUseReadOperation(true) was used at the beginning; the return value of the client was synchronously read in combination with readFutrue.read(); the message was waiting to be returned when sending the message, but this method is not good. session.getConfig().setUseReadOperation(true) will not be truly synchronized.
Here's how to synchronously read the returned data

//Set to read data
session.getConfig().setUseReadOperation(true);
WriteFuture future = session.write(protocolMsgVO);
//Wait for data transmission to complete
future.awaitUninterruptibly();
if(future.isWritten()) {
//Waiting to read data
ReadFuture readFuture = session.read();     
BaseProtocolMsgVO msgReceive = null;
// Wait for data reading to complete20s If you don't return, turn off the connection           
if(readFuture.awaitUninterruptibly(20, TimeUnit.SECONDS)) {             
msgReceive = (BaseProtocolMsgVO) readFuture.getMessage();
} else {                

log.info("Resend times:" + 1);          
session.write(protocolMsgVO);           
if(readFuture.awaitUninterruptibly(20, TimeUnit.SECONDS)) {             
msgReceive = (BaseProtocolMsgVO) readFuture.getMessage();
} else {                    

log.info("Resend times:" + 2);                  
session.write(protocolMsgVO);                   
if(readFuture.awaitUninterruptibly(20, TimeUnit.SECONDS)) {                 
msgReceive = (BaseProtocolMsgVO) readFuture.getMessage();               
} else {                    
log.info("Resend more than three times,Disconnect");                    
session.getConfig().setUseReadOperation(false); // Set to no need to read data                   
// Turn off connection                 
session.closeNow();                 
throw new BusiException("Read device response data timeout");                  }
}}}

BaseProtocolMsgVO is a custom message entity class. At present, a good way is to use ReenLock and Condition to wait for notification.
1. Declare an entity class to store a reentrant lock, Condition and return message

public class ReenLockVO {

    private ReentrantLock lock;
    private Condition condition;
    private BaseProtocolMsgVO baseProtocolMsgVO;

    public ReenLockVO() {
        this.lock = new ReentrantLock();
        this.condition = lock.newCondition();
    }
    }

Load the re-entry lock and condition when instantiating;
2. When sending a message,

ReenLockVO lockVOs = new ReenLockVO();
lockVO.put(deviceCode + protocolMsgVO.getMsgNo(), lockVOs);
lockVOs.getLock().lock();
session.write(protocolMsgVO);
try {
    if(lockVOs.getCondition().await(20, TimeUnit.SECONDS)) {
        rBaseProtocolMsgVO = lockVOs.getBaseProtocolMsgVO();
    } else {
        log.info("Resend times:" + 1 + "Resend message:" + protocolMsgVO.toByteString());
        session.write(protocolMsgVO);
        if(lockVOs.getCondition().await(20, TimeUnit.SECONDS)) {
            rBaseProtocolMsgVO = lockVOs.getBaseProtocolMsgVO();
        } else {
            log.info("Resend times:" + 2 + "Resend message:" + protocolMsgVO.toByteString());
            session.write(protocolMsgVO);
            if(lockVOs.getCondition().await(20, TimeUnit.SECONDS)) {
                rBaseProtocolMsgVO = lockVOs.getBaseProtocolMsgVO();
            } else {
                log.info("Resend more than three times, disconnect!");
                session.closeNow();
            }
        }
    }
} catch(InterruptedException e) {
    e.printStackTrace();
} finally {
    if(lockVO.contains(deviceCode + protocolMsgVO.getMsgNo())) {
        lockVO.remove(deviceCode + protocolMsgVO.getMsgNo());
    }
    lockVOs.getLock().unlock();
}

lockVO is concurrenthashmap. Key stores the client number and message number, and value stores the VO that can be re entered
private static ConcurrentHashMap

lockVO.get(responseMsg.getDeviceCode() + msgVO.getMsgNo()).setBaseProtocolMsgVO(msgVO);
lockVO.get(responseMsg.getDeviceCode() + msgVO.getMsgNo()).getLock().lock();
try {
    lockVO.get(responseMsg.getDeviceCode() + msgVO.getMsgNo()).getCondition().signal();
} catch(Exception e) {
    log.error(e.getStackTrace());
} finally {
    lockVO.get(responseMsg.getDeviceCode() + msgVO.getMsgNo()).getLock().unlock();
}

When a message is received, it sets a message to the VO of the re-entry lock and notifies the reader, so as to realize the mechanism of synchronously reading the message and re sending the message.
The combination of reentrant lock and Condition is widely used in message queue, which is also the notification waiting implemented in the same way as message queue.

If you have any questions in this way, please give me some advice ~!!

Tags: Session

Posted on Sun, 03 May 2020 12:08:36 -0400 by robin01