package com.hqyg.disjob.rpc.client.proxy;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import java.net.InetSocketAddress;
import java.util.concurrent.ExecutionException;
import com.hqyg.disjob.common.exception.TransportException;
import com.hqyg.disjob.common.util.LoggerUtil;
import com.hqyg.disjob.rpc.client.ChannelState;
import com.hqyg.disjob.rpc.client.HURL;
import com.hqyg.disjob.rpc.codec.Response;
import com.hqyg.disjob.rpc.codec.RpcRequest;
import com.hqyg.disjob.rpc.codec.RpcResponse;
/**
*
* @author Disjob
*
*/
public class NettyChannel implements Channel{
private volatile ChannelState state = ChannelState.UNINIT;
private RpcClient rpcClient;
private io.netty.channel.Channel channel = null;
private InetSocketAddress remoteAddress = null;
private InetSocketAddress localAddress = null;
private String channelId ;
@Override
public io.netty.channel.Channel getChannel() {
return channel;
}
public String getChannelId() {
return channelId;
}
public void setChannelId(String channelId) {
this.channelId = channelId;
}
public NettyChannel(RpcClient rpcClient) {
this.rpcClient = rpcClient;
this.remoteAddress = new InetSocketAddress(rpcClient.getHurl().getHost(), rpcClient.getHurl().getPort());
}
/**
*
*/
public Response request(final RpcRequest request) throws TransportException {
final RpcResponse response = new RpcResponse();
final String requestId = request.getData().getRequestId();
response.setRequestId(requestId);
LoggerUtil.debug("begin write: " + request.getData().getRequestId());
//1、
LoggerUtil.debug(request.getData().getRequestId()+ " , "+ (rpcClient.getHurl().getHost() + " channelId:" + this.channelId));
ChannelFuture writeFuture = this.channel.writeAndFlush(request);
LoggerUtil.debug("after" + rpcClient.getHurl().getHost() + "-"+ rpcClient.getHurl().getPort() + " request "+ request.getData().getRequestId());
//2、
writeFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future)
throws Exception {
if (future.isSuccess()) {
LoggerUtil.info("request success:" + requestId);
} else {
response.setException(requestId + " request failed:"+ future.cause().getMessage());
LoggerUtil.error(" request failed, requestId:" + requestId+ " rerequest", future.cause());
RpcClientCache.get(rpcClient.getHurl()).request(request);
}
}
});
try {
writeFuture.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
//3、
return response;
}
@Override
public synchronized io.netty.channel.Channel connect(int failReConCount) throws InterruptedException {
if (isAvailable()) {
LoggerUtil.warn("the channel already open, local: " + localAddress + " remote: " + remoteAddress + " url: "+ rpcClient.getHurl().getUri());
return channel;
}
//1、连接
long start = System.currentTimeMillis();
this.channel = rpcClient.connect(failReConCount);
if(this.channel == null){
return null;
}
LoggerUtil.info(this.getClass().getName()+"; connect to server [ "+ServerLinkedService.getRemoterAddress(channel)+" ] has take time :"+(System.currentTimeMillis()-start)/1000 +" s");
//2、设置状态
boolean success = this.channel.isActive();
if(success){
this.state = ChannelState.ALIVE ;
if (channel.localAddress() != null && channel.localAddress() instanceof InetSocketAddress) {
localAddress = (InetSocketAddress) channel.localAddress();
}
}
return this.channel ;
}
@Override
public void close() {
close(0);
}
@Override
public void close(int timeout) {
try {
state = ChannelState.CLOSE;
channel.close().addListener(ChannelFutureListener.CLOSE);
} catch (Exception e) {
LoggerUtil.error("NettyChannel close Error: " + rpcClient.getHurl().getUri() + " local=" + localAddress, e);
}
}
@Override
public boolean isAvailable() {
return state.isAliveState();
}
@Override
public InetSocketAddress getLocalAddress() {
return localAddress;
}
@Override
public InetSocketAddress getRemoteAddress() {
return remoteAddress;
}
@Override
public boolean isClosed() {
return state.isCloseState();
}
@Override
public HURL getHurl() {
return rpcClient.getHurl();
}
}