/*
* Copyright 2008-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.hasor.rsf.rpc.net;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import net.hasor.core.AppContext;
import net.hasor.core.future.BasicFuture;
import net.hasor.rsf.InterAddress;
import net.hasor.rsf.RsfEnvironment;
import net.hasor.rsf.RsfSettings;
import net.hasor.rsf.domain.ProtocolStatus;
import net.hasor.rsf.domain.RsfException;
import net.hasor.rsf.utils.NameThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;
/**
* RSF网络服务,并提供数据传出、传入,以及端口监听服务。
* tips:支持多协议
* @version : 2014年9月12日
* @author 赵永春(zyc@hasor.net)
*/
public class RsfNetManager {
protected Logger logger = LoggerFactory.getLogger(getClass());
private final RsfEnvironment rsfEnvironment; // RSF环境
private final LinkPool linkPool; // 网络连接池,负责管理所有网络连接
private final EventLoopGroup workLoopGroup; // I/O线程
private final NioEventLoopGroup listenLoopGroup; // 监听线程
private final RsfReceivedListener receivedListener; // 负责汇总所有来自底层网络的 RequestInfo、ResponseInfo消息
private final Map<String, Connector> bindListener; // 不同协议都有自己独立的‘RPC协议连接器’
//
public RsfNetManager(RsfEnvironment rsfEnvironment, RsfReceivedListener receivedListener) {
RsfSettings rsfSettings = rsfEnvironment.getSettings();
this.bindListener = new HashMap<String, Connector>();
this.linkPool = new LinkPool(rsfEnvironment);
//
int workerThread = rsfSettings.getNetworkWorker();
int listenerThread = rsfEnvironment.getSettings().getNetworkListener();
this.workLoopGroup = new NioEventLoopGroup(workerThread, new NameThreadFactory("RSF-Nio-%s", rsfEnvironment.getClassLoader()));
this.listenLoopGroup = new NioEventLoopGroup(listenerThread, new NameThreadFactory("RSF-Listen-%s", rsfEnvironment.getClassLoader()));
this.logger.info("nioEventLoopGroup, workerThread = {} , listenerThread = {}", workerThread, listenerThread);
//
this.rsfEnvironment = rsfEnvironment;
this.receivedListener = receivedListener;
}
//
//
/** 环境对象 */
public RsfEnvironment getRsfEnvironment() {
return this.rsfEnvironment;
}
/**获取运行着哪些协议*/
public Set<String> runProtocols() {
return Collections.unmodifiableSet(this.bindListener.keySet());
}
/** 查找RPC连接器。 */
public Connector findConnector(String protocol) {
return this.bindListener.get(protocol);
}
//
//
/** 启动RSF上配置的所有连接器。*/
public void start(AppContext appContext) {
//
this.linkPool.initPool();
RsfSettings settings = this.getRsfEnvironment().getSettings();
String defaultProtocol = settings.getDefaultProtocol();
Map<String, InterAddress> connectorSet = settings.getBindAddressSet();
Map<String, InterAddress> gatewaySet = settings.getGatewaySet();
//
for (Map.Entry<String, InterAddress> entry : connectorSet.entrySet()) {
String protocolKey = entry.getKey();
InterAddress local = entry.getValue();
InterAddress gateway = gatewaySet.get(protocolKey);
if (local.getPort() <= 0) {
throw new IllegalStateException("[" + protocolKey + "] the prot is zero.");
}
if (gateway != null && gateway.getPort() <= 0) {
throw new IllegalStateException("[" + protocolKey + "] the gateway prot is zero.");
}
//
try {
Connector connector = new Connector(appContext, protocolKey, local, gateway, this.receivedListener, this.linkPool, this.workLoopGroup);
connector.startListener(this.listenLoopGroup);//启动连接器
this.bindListener.put(protocolKey, connector);
} catch (Throwable e) {
this.logger.error("connector[{}] failed -> {}", protocolKey, e.getMessage(), e);
if (defaultProtocol.equals(protocolKey)) {
throw new IllegalStateException("default connector start failed.", e);//默认连接器启动失败
}
}
}
//
}
/** 销毁 */
public void shutdown() {
logger.info("rsfNetManager, shutdownGracefully.");
if (this.bindListener != null && !this.bindListener.isEmpty()) {
for (Connector listener : this.bindListener.values()) {
listener.shutdown();
}
this.bindListener.clear();
}
this.linkPool.destroyPool();
this.listenLoopGroup.shutdownGracefully();
this.workLoopGroup.shutdownGracefully();
}
//
/** 建立或获取和远程的连接(异步+回调) */
public Future<RsfChannel> getChannel(InterAddress target) throws InterruptedException {
// .查找连接,并确定已有连接是否有效
String hostPort = target.getHostPort();
BasicFuture<RsfChannel> channelFuture = this.linkPool.findChannel(hostPort);
if (channelFuture != null && channelFuture.isDone()) {
RsfChannel channel = null;
try {
channel = channelFuture.get();
if (channel != null && !channel.isActive()) {
this.linkPool.closeConnection(hostPort);// 连接已经失效,需要重新连接
channelFuture = null;
}
} catch (Exception e) {
this.linkPool.closeConnection(hostPort);// 连接失败
channelFuture = null;
}
}
if (channelFuture != null) {
return channelFuture;
}
//
// .异步新建连接
synchronized (this) {
channelFuture = this.linkPool.findChannel(hostPort);
if (channelFuture != null) {
return channelFuture;
}
channelFuture = this.linkPool.preConnection(hostPort);
String protocol = target.getSechma();
Connector connector = this.findConnector(protocol);// tips:例如:如果本地都不支持 rsf 协议,那么也没有必要连接远程的 rsf 协议。
if (connector == null) {
this.logger.error("connect to {} failed. ", hostPort);
channelFuture.failed(new RsfException(ProtocolStatus.ProtocolUndefined, "Connector Undefined for protocol " + protocol));
} else {
logger.info("connect to {} ...", hostPort);
connector.connectionTo(target, channelFuture);
}
}
return channelFuture;
}
}