1.网络服务一般的结构:
读取请求--->解码请求--->处理服务--->编码响应--->发送响应
经典的服务设计是“每一个请求一个线程”,如下图
2.Reactor模式
Reactor响应I/O事件,分发到合适的Handler处理。
Handler执行非阻塞的动作。
基本的Reactor设计,单线程版本
示例代码:
- package com.zhang.nio;
- import java.io.IOException;
- import java.net.InetSocketAddress;
- import java.nio.channels.SelectionKey;
- import java.nio.channels.Selector;
- import java.nio.channels.ServerSocketChannel;
- import java.nio.channels.SocketChannel;
- import java.util.Set;
- public class Reactor implements Runnable {
- final Selector selector;
- final ServerSocketChannel serverSocketChannel;
- public Reactor(int port) throws IOException {
- selector = Selector.open();
- serverSocketChannel = ServerSocketChannel.open();
- serverSocketChannel.socket().bind(new InetSocketAddress(port));
- serverSocketChannel.configureBlocking(false);
- SelectionKey key = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
- key.attach(new Acceptor());
- }
- @Override
- public void run() {
- while (!Thread.interrupted()) {
- try {
- selector.select();
- Set<SelectionKey> selectionKeys = selector.selectedKeys();
- for(SelectionKey selectionKey : selectionKeys){
- dispatch(selectionKey);
- }
- selectionKeys.clear();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- private void dispatch(SelectionKey selectionKey) {
- Runnable run = (Runnable) selectionKey.attachment();
- if(run != null){
- run.run();
- }
- }
- class Acceptor implements Runnable{
- @Override
- public void run() {
- try {
- SocketChannel channel = serverSocketChannel.accept();
- if(channel != null){
- new Handler(selector,channel);
- }
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- }
- import java.io.IOException;
- import java.nio.ByteBuffer;
- import java.nio.channels.SelectionKey;
- import java.nio.channels.Selector;
- import java.nio.channels.SocketChannel;
- public class Handler implements Runnable {
- private final static int DEFAULT_SIZE = 8092;
- private final SocketChannel socketChannel;
- private final SelectionKey seletionKey;
- private static final int READING = 0;
- private static final int SENDING = 1;
- private int state = READING;
- ByteBuffer inputBuffer = ByteBuffer.allocate(DEFAULT_SIZE);
- ByteBuffer outputBuffer = ByteBuffer.allocate(DEFAULT_SIZE);
- public Handler(Selector selector, SocketChannel channel) throws IOException {
- this.socketChannel = channel;
- socketChannel.configureBlocking(false);
- this.seletionKey = socketChannel.register(selector, 0);
- seletionKey.attach(this);
- seletionKey.interestOps(SelectionKey.OP_READ);
- selector.wakeup();
- }
- @Override
- public void run() {
- if(state == READING){
- read();
- }else if(state == SENDING){
- write();
- }
- }
- class Sender implements Runnable {
- @Override
- public void run() {
- try {
- socketChannel.write(outputBuffer);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- if(outIsComplete()){
- seletionKey.cancel();
- }
- }
- }
- private void write() {
- try {
- socketChannel.write(outputBuffer);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- while(outIsComplete()){
- seletionKey.cancel();
- }
- }
- private void read() {
- try {
- socketChannel.read(inputBuffer);
- if(inputIsComplete()){
- process();
- seletionKey.attach(new Sender());
- seletionKey.interestOps(SelectionKey.OP_WRITE);
- seletionKey.selector().wakeup();
- }
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- public boolean inputIsComplete(){
- return false;
- }
- public boolean outIsComplete(){
- return false;
- }
- public void process(){
- }
- }
NIO支持的特性:
- Channels,连接到文件、socket等等,支持非阻塞读。
- Buffers,与数组相似的对象,能直接从Channels中读写。
- Selectors,辨识哪一个通道的集合有IO事件。(Tell which of a set of Channels have IO events)
- SelectionKeys,维护IO事件的状态和绑定。
多线程设计
- 添加线程增加可扩展性,主要应用在多核处理器中
- Worker 线程,Reactors要快速出发handlers。handlers的处理降低了Reactor的速度。将非I/O操作分离到其他线程中处理。
- Multiple Reactor Threads,多Reactor线程。Reactor线程可以使IO操作饱和,分布负载到其他的reactors,负载均衡来匹配CPU和IO之间的速度差异。
![](http://dl.iteye.com/upload/attachment/0073/5744/9a27651a-b2e9-355b-85b3-8f699e0a127b.jpg)
使用多个Reactors
![](http://dl.iteye.com/upload/attachment/0073/5746/fead5d70-d42e-3b1a-a51f-09f1100902e1.jpg)
文章转自:http://ryanflyer.iteye.com/blog/1672876