dubbo --netty創建服務端、客戶端以及handler

上一節說到用到這個來創建服務,其實到最後就是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("");
	    }
    }
    //...
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章