Netty3源码原理

Netty3主要有 Worker,Boss,AbstractNioSelector,NioSelectorRunnablePool,NioBossSelector ,NioWorkerSelector,ServerBootstrap 等类组成,如果把Netty3比作是一个餐厅的话,Boss相当于在门前欢迎客户的股东(老板,有多个),Worker相当于服务生(多个),负责客人点餐,老板在门口等到客人后把客人交给服务生,老板和服务生都是监听者(AbstractNioSelector),只是职能不同,NioSelectorRunnablePool是线程管理者,即可以管理老板和服务生。当然,Netty中远没有这么简单,这只是一个简单的类比。能力有限,如果类比有误,欢迎指正。
他们的关系如下:
Netty3源码原理_第1张图片

1、AbstractNioSelector

 老板和服务生都是一个selector,需要抽象出来,定义为类AbstractNioSelector,为一个虚类,是一个线程,老板服务类和服务生服务类都继承此类,此类需要定义

A、有执行任务的线程池Executor
B、选择器Selector
C、选择器状态标记,标记选择器是睡眠状态还是运行状态 AtomicBoolean
D、任务队列,要有任务执行才有意义,ConcurrentLinkedQueue
E、当前线程线程名 String threadName
F、线程管理对象,NioSelectorRunnablePool,后面会讲到。
方法需要定义
A、构造方法,初始化线程池、线程名、线程管理对象,并获取selector和启动线程
B、注册一个任务并且并激活selector,相当于在任务队列中加入一个任务,并且唤醒selector,表示可以执行任务了,因为没有任务的时候selector会设置为睡眠,定义为registerTask(Rannable task)
C、执行任务队列里的任务,定义为processTaskQueue();
D、选择选择器,定义为select(Selector selector);
E、处理业务逻辑,定义为process(Selector selector);老板服务类处理的业务逻辑为,接收到新连接的客户端,相当于在餐厅门口接到了客人,然后把客人交给服务生,然后老板就不管了,把客人交给服务生的时候需要用的线程管理对象获得一个服务生。然后服务生注册此客人。服务生服务类负责处理读写数据,相当于负责点餐。
F、最后定义run方法,因为是线程处理,循环执行 把唤醒标志设置为false,选择选择器,执行任务,处理业务逻辑。

2、NioSelectorRunnablePool

   线程管理者,相当于一个线程池,用于管理老板和服务生,定义类为NioSelectorRunnablePool,需要定义

A、boss线程数组和boss计数器
B、worker线程组合worker计数器
方法需要定义
A、初始化boss线程,定义为initBoss(Executor boss,int count);创建count个Boss,并且把线程池给boss
B、初始化worker线程,定义为initWorker(Executor worker,int count);创建count个Worker,并且把线程池给Worker
C、获取下一个worker,定义为nextWorker();就是计数器对应的worker
D、获取下一个boss,定位为nextBoss();就是计数器对应的boss。

3、Worker

主要负责读写客户端消息, 只需定义一个方法,就是注册到通道任务中,定义为registerNewChannelTask(SocketChannel channel);

4、Boss

  只需定义一个方法,就是加入一个新的ServerSocket,定义为registerAcceptChannelTask(ServerSocketChannel serverChannel);

5、NioBossSelector

负责监听客户端的连接处理,并把客户端交个worker处理读写。

6、NioWorkerSelector

负责处理客户端的读写数据等处理。

7、ServerBootstrap

绑定端口

模拟代码如下:

package com.sf.simba.netty.imitate.pool;

import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;

import com.sf.simba.netty.imitate.NioBossSelector;
import com.sf.simba.netty.imitate.NioWorkerSelector;
/**
 * 
 * @author 734621
 *
 */
public class NioSelectorRunnablePool {
   private Boss[] bosses;
   private AtomicInteger bossCount = new AtomicInteger();

   private Worker[] workers;
   private AtomicInteger workersCount = new AtomicInteger();

   public NioSelectorRunnablePool(Executor boss, Executor worker, int bossCount, int workerCount){
       initBoss( boss, bossCount);
       initWorker(worker,workerCount);
   }

   public void initBoss(Executor boss,int count){
       bosses = new Boss[count];
       for(int i=0;inew NioBossSelector(boss, "boss thread"+i, this);
       }
   }

   public void initWorker(Executor worker,int count){
       workers = new Worker[count];
       for(int i=0;inew NioWorkerSelector(worker,"worker thread"+i,this);
       }
   }

   /**
    * 获得一个worker
    * @return
    */
   public Worker nextWorker(){
       return workers[Math.abs(workersCount.getAndIncrement()%workers.length)];
   }
   /**
    * 获得一个boss
    * @return
    */
   public Boss nextBoss(){
       return bosses[Math.abs(bossCount.getAndIncrement()%bosses.length)];
   }
}
package com.sf.simba.netty.imitate.pool;

import java.io.IOException;
import java.nio.channels.ServerSocketChannel;

public interface Boss {
    /**
     * 注册新来的客户端
     * 即相当于老板在门口迎接了新的客人,之后会交给服务生
     * @param channel
     * @throws IOException 
     */
   public void registerAcceptChannelTask(ServerSocketChannel channel) throws IOException;
}
package com.sf.simba.netty.imitate.pool;

import java.nio.channels.SocketChannel;

public interface Worker {

    public void registerNewChannelTask(SocketChannel channel);


}
package com.sf.simba.netty.imitate;

import java.io.IOException;
import java.nio.channels.Selector;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;

import com.sf.simba.netty.imitate.pool.NioSelectorRunnablePool;
/**
 * bossSelector 和  workerSelector的抽象类
 * @author 734621
 *
 */
public abstract class AbstractNioSelector implements Runnable{
    //线程池
    private final Executor executor;
    //选择器
    protected Selector selector;
    //selector唤醒标志
    private final AtomicBoolean wakeup = new AtomicBoolean();
    //任务队列
    private final Queue tasksQueue = new ConcurrentLinkedQueue();

    private String threadName;
    /**
     * 线程管理器,管理boss和worker
     */
    private NioSelectorRunnablePool selectPool;

    public AbstractNioSelector(Executor executor,String threadName,NioSelectorRunnablePool selectPool){
        this.executor = executor;
        this.threadName = threadName;
        this.selectPool = selectPool;
        openSelector();
    }
    /**
     * 获取selector并启用线程
     */
    private void openSelector(){
        try {
            selector = Selector.open();
        } catch (IOException e) {
            e.printStackTrace();
        }
        executor.execute(this);
    }
    /**
     * 注册任务 相当于告诉boss或者worker有新的客人,需要开始工作了
     * @param task
     */
    public final void registerTask(Runnable task){
        tasksQueue.add(task);
        Selector selector = this.selector;

        if(selector != null){
            if(wakeup.compareAndSet(false, true)){
                selector.wakeup();
            }
        }else{
            tasksQueue.remove(task);
        }

    }

    public void run(){
        Thread.currentThread().setName(threadName);

        while(true){
            wakeup.set(false);
            try {
            //选择选择器
            select(selector);
            //处理任务
            processTaskQueue();
            //处理逻辑

                process(selector);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    /**
     * 处理任务队列
     */
    protected final void processTaskQueue(){
        while(true){
            final Runnable task = tasksQueue.poll();
            //如果没有任务了就直接退出循环
            if(task == null) break;
            task.run();
        }
    }


    protected abstract  void select(Selector selector) throws IOException;


    protected abstract void  process(Selector selector) throws IOException;

    public NioSelectorRunnablePool getSelectPool() {
        return selectPool;
    }




}
package com.sf.simba.netty.imitate;

import java.io.IOException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Set;
import java.util.concurrent.Executor;

import com.sf.simba.netty.imitate.pool.Boss;
import com.sf.simba.netty.imitate.pool.NioSelectorRunnablePool;
import com.sf.simba.netty.imitate.pool.Worker;

public class NioBossSelector extends AbstractNioSelector implements Boss {

    public NioBossSelector(Executor executor, String threadName,
            NioSelectorRunnablePool selectPool) {
        super(executor, threadName, selectPool);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void registerAcceptChannelTask(final ServerSocketChannel channel) throws IOException {
        final Selector selector = this.selector;
        registerTask(new Runnable(){

            @Override
            public void run() {
                try {
                    channel.register(selector, SelectionKey.OP_ACCEPT);//把boss注册为接受,即在门口迎接客人
                } catch (ClosedChannelException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }

        });

    }


    @Override
    public void select(Selector selector) throws IOException {
            selector.select();

    }

    /**
     * 处理业务逻辑,boss的业务逻辑主要是在门口迎接客人并且把客人交给worker,worker接待后准备为客人点餐
     * @throws IOException 
     */
    @Override
    public void process(Selector selector) throws IOException {
         Set selectionKeys = selector.selectedKeys();
          if(selectionKeys.isEmpty()){
              return;
          }

          for(SelectionKey key:selectionKeys){
              ServerSocketChannel channel = (ServerSocketChannel)key.channel();
                SocketChannel accept = channel.accept();//接收此客人
                accept.configureBlocking(false);
                //把此客人交给一个服务生worker
                Worker nextworker = super.getSelectPool().nextWorker();
                nextworker.registerNewChannelTask(accept);
               System.out.println("一个新的客户端连接了进来!");
          }

    }

}
package com.sf.simba.netty.imitate;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Set;
import java.util.concurrent.Executor;

import com.sf.simba.netty.imitate.pool.NioSelectorRunnablePool;
import com.sf.simba.netty.imitate.pool.Worker;

public class NioWorkerSelector extends AbstractNioSelector implements Worker {

    public NioWorkerSelector(Executor executor, String threadName,
            NioSelectorRunnablePool selectPool) {
        super(executor, threadName, selectPool);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void select(Selector selector) throws IOException {
        selector.select(200);

    }

    @Override
    public void process(Selector selector) throws IOException {
        Set selectedKeys = selector.selectedKeys();
         if(selectedKeys.isEmpty())
             return;

        for(SelectionKey key : selectedKeys){
            selectedKeys.remove(key);//移除,防止重复加载
            SocketChannel channel = (SocketChannel) key.channel();
            channel.configureBlocking(false);

            //开始读取数据
            int messageCount = 0;
            boolean failture = true;
            ByteBuffer buffer = ByteBuffer.allocate(100);

            messageCount = channel.read(buffer);
            failture = false;
            //判断是否已经断开
            if(messageCount <0 || failture){
                key.cancel();
                System.out.println("客户端已经断开连接!");
            }else{
                System.out.println("服务器收到数据:"+new String(buffer.array()));
                ByteBuffer outbuffer = ByteBuffer.wrap("服务器已经收到数据\n".getBytes());
                channel.write(outbuffer);
            }
        }

    }

    /**
     * worker注册为
     */
    @Override
    public void registerNewChannelTask(final SocketChannel channel) {
        final Selector selector = this.selector;
        registerTask(new Runnable(){
            public void run(){
                try {
                    channel.register(selector, SelectionKey.OP_READ);
                } catch (ClosedChannelException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }   
            }
        });
    }

}
package com.sf.simba.netty.imitate;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.ServerSocketChannel;

import com.sf.simba.netty.imitate.pool.Boss;
import com.sf.simba.netty.imitate.pool.NioSelectorRunnablePool;

public class ServerBootstrap {
    private NioSelectorRunnablePool selectorPool;

    public ServerBootstrap(NioSelectorRunnablePool selectorPool){
        this.selectorPool = selectorPool;
    }

    /**
     * 绑定端口并获得一个boss
     * @param address
     * @throws IOException 
     */
    public void bind(final InetSocketAddress address) {
        try{
            ServerSocketChannel channel = ServerSocketChannel.open(); 
            channel.configureBlocking(false);
            channel.socket().bind(address);

            Boss boss = selectorPool.nextBoss();
            boss.registerAcceptChannelTask(channel);
        }catch(IOException e){
            e.printStackTrace();
        }

    }
}
package com.sf.simba.netty.imitate;

import java.net.InetSocketAddress;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import com.sf.simba.netty.imitate.pool.NioSelectorRunnablePool;

public class Netty3Main {
    /**
     * 测试
     * @param args
     */
   public static void main(String [] args){

       Executor boss = Executors.newCachedThreadPool();
       Executor worker = Executors.newCachedThreadPool();



       NioSelectorRunnablePool nsrp = new NioSelectorRunnablePool(boss,worker,1,Runtime.getRuntime().availableProcessors()*2);

       ServerBootstrap boot = new ServerBootstrap(nsrp);
       boot.bind(new InetSocketAddress(8000));

       System.out.println("服务已启动!");

   }
}

你可能感兴趣的:(Netty)