Netty3源码原理

来源:互联网 发布:淘宝卖虚拟物品流程 编辑:程序博客网 时间:2024/06/06 13:16

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

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;i<count;i++){           bosses[i]= new NioBossSelector(boss, "boss thread"+i, this);       }   }   public void initWorker(Executor worker,int count){       workers = new Worker[count];       for(int i=0;i<count;i++){           workers[i] = new 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<Runnable> tasksQueue = new ConcurrentLinkedQueue<Runnable>();    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<SelectionKey> 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<SelectionKey> 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("服务已启动!");   }}
0 0
原创粉丝点击