我有一个处理程序,它被添加到管道行中以及传递给处理程序的散列轮式计时器,为来自client.Timer的每个新连接创建处理程序在管道工厂中创建。我需要的是如果客户端在指定的时间内没有进行任何活动,则计时器应关闭该通道。并且在处理程序中我有close方法,当关闭事件被触发时,它会被提供。所以是否需要在close方法上进行同步...因为当调用close时,将调用所有回调处理程序...它是否会导致死锁....
请建议
答案 0 :(得分:0)
答案取决于很多事情 - 因此要求查看您的代码。
HashedWheelTimer始终在使用默认Java线程工厂或提供的线程工厂创建的后台线程上触发超时事件。除非您正在采取特定操作来控制它,否则如果您的TimerTask由HashedWheelTimer直接执行,则很可能是在一个单独的线程上,您应该执行任何必要的同步。
如果您使用的是Netty的ReadTimeoutHandler或IdleStateHandler,则行为取决于您使用的Netty版本。在Netty 3.5之前,在HashedWheelTimer线程上触发了超时,并且可能需要进行同步。
由于Netty 3.5(包括Netty 4.0),超时处理程序将超时事件排队到分配了通道的I / O工作线程。这意味着事件将与所有其他频道事件一起串行引发。不需要同步。
如果您使用的是Netty 3.5或更高版本,我建议您考虑使用提供的超时处理程序,因为它们非常易于使用。如果使用其中一个提供的处理程序不是一个选项,您可以自己将事件排队到I / O工作程序。你如何实现这一点取决于Netty版本,所以我建议查看ReadTimeoutHandler的源代码,看看它是如何完成的。
请注意,上面假设您没有向管道添加执行程序但不保留通道事件的顺序(例如,Netty 3.x中的MemoryAwareThreadPoolExecutor)。
答案 1 :(得分:0)
class DataStreamHandler extends IdleStateAwareChannelUpstreamHandler {
private final Timer timer;
private final Timer idleTimer;`enter code here`
private Channel channel;
private SslHandler sslhandler;
private String serverId;
private boolean certClientId = false;
public enum State {
Open{
protected boolean handle (DataStreamHandler dh, Message event) {
//some logic to proceed to Established state handler
//other wise closed state handler
handler.write(event.getMessage(),),
State, null, true);
// write methods sets the state specified
}
},
Established{ protected boolean handle (DataStreamHandler dh, Message event) {
//some logic some logic to proceed to Bind state handler
handler.write(event.getMessage(),),
State, null, true);
// write methods sets the state specified other wise closed state handler
} },
Bind { protected boolean handle (DataStreamHandler dh, Message event) {
// some logic values below are configurable
channelPipeline.replace(idlestatehandler, new IdleStateHandler(this.idletimer, 10000,0,10000, milliseconds));
handler.write(event.getMessage(),), State, null, true);// write methods sets the state specified
}
}
},
Closed{ protected boolean handle (DataStreamHandler dh, Message event) {
//logic to set handler to fire closed event
} }
};
@Override
public void channelConnected(final ChannelHandlerContext ctx, final ChannelStateEvent e) {
synchronized(this) {
this.channel = ctx.getChannel();
this.sslHandler= ctx.getPipeline().get(SslHandler.class);
//set enum state to Established
}
super.channelConnected(ctx, e);
}
@Override
public void messageReceived(final ChannelHandlerContext ctx, final MessageEvent e) {
synchronized(this) {
if (!this.setCertClientId && !setCertClientId()) {
return;
}
//before processing the message ssl handler is used
}
}
private boolean setCertClientId() {
synchronized(this) {
this.setCertClientId = true;
if (this.sslHandler == null) {
return true;
}
//the ssl handler is added for every channel in getpipeline.
final SSLEngine sslEngine = sslHandler.getEngine();
//ssl related checks done other wise channel close is called
}
}
@Override
public void channelClosed(final ChannelHandlerContext ctx,
final ChannelStateEvent e)throws Exception { //NOSONAR, throw exception is from netty
synchronized(this) {
//set enum state to CLOSED
}
super.channelClosed(ctx, e);
}
private void closeChannel() {
final SslHandler theSslHandler;
synchronized(this) {
this.closePending = true;
theSslHandler = this.sslHandler;
if (sslHandler == null) {
future = getChannel().close();
} else {
future = theSslHandler.close();
}
monitorCloseChannel(future); // this methd has a listener to future
if(theSslHandler != null) {
// the CloseTask is a static class which impelemets the timer task to close the stream or the channel depending upon boolean value supplied
this.timer.newTimeout(new CloseTask(this, true), this.closeTimeoutMs, TimeUnit.MILLISECONDS);
}
}
super.channelClosed(ctx, e);
}
@Override
public void channelIdle(final ChannelHandlerContext ctx,
final IdleStateEvent e) throws Exception { //NOSONAR, throw exception is from netty
synchronized(this) {
switch (e.getState()) {
case ALL_IDLE:
if (this.closePending) {
// close the channel directly
} else {
this.closePending = true;
//call the CloseTask class to close the channel or stream
}
break;
case READER_IDLE:
if (getState() == State.ESTABLISHED) {
//some logic
}
break;
case WRITER_IDLE:
break;
}
}
super.channelIdle(ctx, e);
}
@Override
public void exceptionCaught(final ChannelHandlerContext ctx,
final ExceptionEvent e)
throws Exception {
if (!this.closePending) {
if (//checked for various exceptions) {
//call
closeChannel();
} else {
// call the CloseTask timertask class to close the channel or stream
}
} else {
log.debug("Received exception while closing", e.getCause());
}
}
}
protected abstract boolean handle (DataStreamHandler dh, Message event);
public DataStreamHandler () {
this.timer = timer;
this.idleTimer= idleTimer;
this.channel= channel;
this.sslhandler=sslhandler;
this.serverId=serverId;
}
}