上一節說到用到這個來創建服務,其實到最後就是new NettyServer(url, listener)
Transporters.bind(url, new DecodeHandler(new HeaderExchangeHandler(handler))
服務端
protected void doOpen() throws Throwable {
NettyHelper.setNettyLoggerFactory();
//創建boss線程池
ExecutorService boss = Executors.newCachedThreadPool(
new NamedThreadFactory("NettyServerBoss", true));
//創建worker線程池
ExecutorService worker = Executors.newCachedThreadPool(new
NamedThreadFactory("NettyServerWorker", true));
ChannelFactory channelFactory = new NioServerSocketChannelFactory(boss,
worker, getUrl().getPositiveParameter("iothreads",
Runtime.getRuntime().availableProcessors() + 1));
bootstrap = new ServerBootstrap(channelFactory);
//處理handler
final NettyHandler nettyHandler = new NettyHandler(getUrl(), this);
//將所有的channel保存下來
channels = nettyHandler.getChannels();
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec()
,getUrl(), NettyServer.this);
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("decoder", adapter.getDecoder());
pipeline.addLast("encoder", adapter.getEncoder());
pipeline.addLast("handler", nettyHandler);
return pipeline;
}
});
// bind
channel = bootstrap.bind(getBindAddress());
}
//關閉服務
protected void doClose() throws Throwable {
if (channel != null)
channel.close();
//目前客戶端連接的channel全部斷開
Collection<Channel> channels = getChannels();
if (channels != null && channels.size() > 0) {
for (com.alibaba.dubbo.remoting.Channel channel : channels) {
channel.close();
}
}
if (bootstrap != null)
bootstrap.releaseExternalResources();
if (channels != null)
channels.clear();
}
客戶端
//創建
protected void doOpen() throws Throwable {
NettyHelper.setNettyLoggerFactory();
bootstrap = new ClientBootstrap(channelFactory);
bootstrap.setOption("keepAlive", true);
bootstrap.setOption("tcpNoDelay", true);
bootstrap.setOption("connectTimeoutMillis", getTimeout());
final NettyHandler nettyHandler = new NettyHandler(getUrl(), this);
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(),
getUrl(), NettyClient.this);
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("decoder", adapter.getDecoder());
pipeline.addLast("encoder", adapter.getEncoder());
pipeline.addLast("handler", nettyHandler);
return pipeline;
}
});
}
//連接服務端
protected void doConnect() throws Throwable {
long start = System.currentTimeMillis();
ChannelFuture future = bootstrap.connect(getConnectAddress());
try{
boolean ret = future.awaitUninterruptibly(getConnectTimeout(),
TimeUnit.MILLISECONDS);
if (ret && future.isSuccess()) {
Channel newChannel = future.getChannel();
newChannel.setInterestOps(Channel.OP_READ_WRITE);
try {
// 關閉舊的連接
Channel oldChannel = NettyClient.this.channel;
if (oldChannel != null) {
try {
oldChannel.close();
} finally {
NettyChannel.removeChannelIfDisconnected(oldChannel);
}
}
} finally {
if (NettyClient.this.isClosed()) {
try {
newChannel.close();
} finally {
NettyClient.this.channel = null;
NettyChannel.removeChannelIfDisconnected(newChannel);
}
} else {
NettyClient.this.channel = newChannel;
}
}
}
}finally{
if (! isConnected()) {
future.cancel();
}
}
}
handler
用來處理netty中的請求。(客戶端連接、客戶端關閉、接收消息、發送消息以及出現異常)
而在duubo中使用的handler是採用了裝飾者模式
- NettyHandler
主要是將當前客戶端連接的channel保存到map中,供NettyServer使用,而他的構造器傳進來的ChannelHandler 就是NettyServer(它實現了ChannelHandler)
NettyHandler nettyHandler = new NettyHandler(getUrl(), this);
public class NettyHandler extends SimpleChannelHandler {
//在客戶端連接服務端,或者斷開連接。保存channel
private final Map<String, Channel> channels =
new ConcurrentHashMap<String, Channel>();
private final URL url;
private final ChannelHandler handler;
public NettyHandler(URL url, ChannelHandler handler){
this.url = url;
this.handler = handler;
}
public Map<String, Channel> getChannels() {
return channels;
}
//客戶端連接
public void channelConnected(ChannelHandlerContext ctx,
ChannelStateEvent e) throws Exception {
NettyChannel channel = NettyChannel.getOrAddChannel(ctx.getChannel(),
url, handler);
try {
if (channel != null) {
channels.put(NetUtils.toAddressString((InetSocketAddress)
ctx.getChannel().getRemoteAddress()), channel);
}
handler.connected(channel);
} finally {
NettyChannel.removeChannelIfDisconnected(ctx.getChannel());
}
}
//客戶端斷開
public void channelDisconnected(ChannelHandlerContext ctx,
ChannelStateEvent e)
throws Exception {
NettyChannel channel = NettyChannel.getOrAddChannel(ctx.getChannel(),
url, handler);
try {
channels.remove(NetUtils.toAddressString((InetSocketAddress)
ctx.getChannel().getRemoteAddress()));
handler.disconnected(channel);
} finally {
NettyChannel.removeChannelIfDisconnected(ctx.getChannel());
}
}
//接收客戶端的請求,向客戶端發送消息,異常處理都是交給handler處理
}
-
AbstractPeer
這裏全部交給下一級的handler處理 -
MultiMessageHandler
在接收消息時,如果message是MultiMessage類型,那麼就循環遍歷
public void received(Channel channel, Object message) {
if (message instanceof MultiMessage) {
MultiMessage list = (MultiMessage)message;
for(Object obj : list) {
handler.received(channel, obj);
}
} else {
handler.received(channel, message);
}
}
- HeartbeatHandler
主要是記錄讀寫時間,以及在接收消息時,如果是心跳請求,那麼就發送消息給對方
//初始化讀寫時間
public void connected(Channel channel) {
hannel.setAttribute("READ_TIMESTAMP", System.currentTimeMillis());
channel.setAttribute("WRITE_TIMESTAMP", System.currentTimeMillis());
handler.connected(channel);
}
//清除讀寫時間
public void disconnected(Channel channel) {
channel.removeAttribute("READ_TIMESTAMP");
channel.removeAttribute("WRITE_TIMESTAMP");
handler.disconnected(channel);
}
//重設寫時間
public void sent(Channel channel, Object message) {
channel.setAttribute("WRITE_TIMESTAMP", System.currentTimeMillis());
handler.sent(channel, message);
}
//重設讀時間,如果是心跳請求,那麼就發送消息
public void received(Channel channel, Object message) {
hannel.setAttribute("READ_TIMESTAMP", System.currentTimeMillis());
//如果消息是心跳請求,那麼就發送消息
if (isHeartbeatRequest(message)) {
Request req = (Request) message;
if (req.isTwoWay()) {
Response res = new Response(req.getId(), req.getVersion());
res.setEvent(Response.HEARTBEAT_EVENT);
channel.send(res);
}
return;
}
//接收消息
handler.received(channel, message);
}
- AllChannelHandler
在線程池中處理這些事件。
public void connected(Channel channel) {
ExecutorService cexecutor = getExecutorService();
cexecutor.execute(new ChannelEventRunnable(channel, handler ,
ChannelState.CONNECTED));
}
public void disconnected(Channel channel) throws RemotingException {
ExecutorService cexecutor = getExecutorService();
cexecutor.execute(new ChannelEventRunnable(channel, handler ,
ChannelState.DISCONNECTED));
}
public void received(Channel channel, Object message) {
ExecutorService cexecutor = getExecutorService();
cexecutor.execute(new ChannelEventRunnable(channel, handler,
ChannelState.RECEIVED, message));
}
public void caught(Channel channel, Throwable exception) {
ExecutorService cexecutor = getExecutorService();
cexecutor.execute(new ChannelEventRunnable(channel, handler ,
ChannelState.CAUGHT, exception));
}
//創建線程池
public Executor getExecutor(URL url) {
String name = url.getParameter(Constants.THREAD_NAME_KEY, "Dubbo");
int threads = url.getParameter(Constants.THREADS_KEY, 200);
int queues = url.getParameter(Constants.QUEUES_KEY, 0);
return new ThreadPoolExecutor(threads, threads, 0,
TimeUnit.MILLISECONDS,
queues == 0 ? new SynchronousQueue<Runnable>() :
(queues < 0 ? new LinkedBlockingQueue<Runnable>()
: new LinkedBlockingQueue<Runnable>(queues)),
new NamedThreadFactory(name, true), new
AbortPolicyWithReport(name, url));
}
- DecodeHandler
在接收消息時,對message進行解碼
待後續。。
public void received(Channel channel, Object message) {
if (message instanceof Decodeable)
decode(message);
if (message instanceof Request)
decode(((Request)message).getData());
if (message instanceof Response)
decode( ((Response)message).getResult());
handler.received(channel, message);
}
private void decode(Object message) {
if (message != null && message instanceof Decodeable)
((Decodeable)message).decode();
}
-
HeaderExchangeHandler
主要對頭部做一些處理 -
ExchangeHandler
private ExchangeHandler requestHandler = new ExchangeHandlerAdapter() {
//連接
public void connected(Channel channel) throws RemotingException {
invoke(channel, "onconnect");
}
//關閉連接
public void disconnected(Channel channel) throws RemotingException {
invoke(channel, "ondisconnect");
}
//接收消息
public void received(Channel channel, Object message) t {
if (message instanceof Invocation) {
reply((ExchangeChannel) channel, message);
} else {
super.received(channel, message);
}
}
//執行
private void invoke(Channel channel, String methodKey) {
Invocation invocation = createInvocation(channel, channel.getUrl(),
methodKey);
if (invocation != null)
received(channel, invocation);
}
//專門處理Invocation的消息
public Object reply(ExchangeChannel channel, Object message) {
if (message instanceof Invocation) {
Invocation inv = (Invocation) message;
Invoker<?> invoker = getInvoker(channel, inv);
//如果是callback 需要檢查當前的方法是否在url中的methods中...
RpcContext.getContext().setRemoteAddress(
channel.getRemoteAddress());
//直接調用
return invoker.invoke(inv);
}
throw new RemotingException(".....");
}
//創建Invocation
private Invocation createInvocation(Channel channel,
URL url, String methodKey) {
String method = url.getParameter(methodKey);
if (method == null || method.length() == 0) {
return null;
}
RpcInvocation invocation =
new RpcInvocation(method, new Class<?>[0], new Object[0]);
// ..
return invocation;
}
}
//從緩存中獲取Invoker
Invoker<?> getInvoker(Channel channel, Invocation inv) {
boolean isCallBackServiceInvoke = false;
boolean isStubServiceInvoke = false;
int port = channel.getLocalAddress().getPort();
String path = inv.getAttachments().get(Constants.PATH_KEY);
//如果是客戶端的回調服務.
isStubServiceInvoke = Boolean.TRUE.toString().equals(
inv.getAttachments().get(Constants.STUB_EVENT_KEY));
if (isStubServiceInvoke){
port = channel.getRemoteAddress().getPort();
}
//拼接key
String serviceKey = serviceKey(port, path,
inv.getAttachments().get(Constants.VERSION_KEY),
inv.getAttachments().get(Constants.GROUP_KEY));
//從緩存中獲取Exporter,在export中創建並exporterMap
DubboExporter<?> exporter = (DubboExporter<?>)
exporterMap.get(serviceKey);
return exporter.getInvoker();
}
NettyChannel
這裏對客戶端傳過來的channel進行了封裝
final class NettyChannel extends AbstractChannel {
private NettyChannel(org.jboss.netty.channel.Channel channel,
URL url, ChannelHandler handler){
super(url, handler);
this.channel = channel;
}
//對原有的channel進行封裝
static NettyChannel getOrAddChannel(org.jboss.netty.channel.Channel ch,
URL url, ChannelHandler handler) {
//new NettyChannel然後放進map
return ret;
}
//發送消息
public void send(Object message, boolean sent)
throws RemotingException {
super.send(message, sent);
boolean success = true;
int timeout = 0;
ChannelFuture future = channel.write(message);
//是否等待
if (sent) {
timeout = getUrl().getPositiveParameter("timeout",1000);
success = future.await(timeout);
}
Throwable cause = future.getCause();
if (cause != null) {
throw cause;
}
if(! success) {
throw new RemotingException("");
}
}
//...
}