<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 56,  comments - 12,  trackbacks - 0

    本文可看成是對Doug Lea Scalable IO in Java一文的翻譯。

    當前分布式計算 Web Services盛行天下,這些網絡服務的底層都離不開對socket的操作。他們都有一個共同的結構:
    1. Read request
    2. Decode request
    3. Process service
    4. Encode reply
    5. Send reply

    經典的網絡服務的設計如下圖,在每個線程中完成對數據的處理:

    但這種模式在用戶負載增加時,性能將下降非常的快。我們需要重新尋找一個新的方案,保持數據處理的流暢,很顯然,事件觸發機制是最好的解決辦法,當有事件發生時,會觸動handler,然后開始數據的處理。

    Reactor模式類似于AWT中的Event處理:

    Reactor模式參與者

    1.Reactor 負責響應IO事件,一旦發生,廣播發送給相應的Handler去處理,這類似于AWT的thread
    2.Handler 是負責非堵塞行為,類似于AWT ActionListeners;同時負責將handlers與event事件綁定,類似于AWT addActionListener

    如圖:

    Java的NIO為reactor模式提供了實現的基礎機制,它的Selector當發現某個channel有數據時,會通過SlectorKey來告知我們,在此我們實現事件和handler的綁定。

    我們來看看Reactor模式代碼:


    public class Reactor implements Runnable{

      final Selector selector;
    final ServerSocketChannel serverSocket;

      Reactor(int port) throws IOException {
    selector = Selector.open();
    serverSocket = ServerSocketChannel.open();
    InetSocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(),port);
    serverSocket.socket().bind(address);

    serverSocket.configureBlocking(false);
    //向selector注冊該channel
    Selecti sk =serverSocket.register(selector,Selecti.OP_ACCEPT);

    logger.debug("-->Start serverSocket.register!");

    //利用sk的attache功能綁定Acceptor 如果有事情,觸發Acceptor
    sk.attach(new Acceptor());
    logger.debug("-->attach(new Acceptor()!");
    }


    public void run() { // normally in a new Thread
    try {
    while (!Thread.interrupted())
    {
    selector.select();
    Set selected = selector.selectedKeys();
    Iterator it = selected.iterator();
    //Selector如果發現channel有OP_ACCEPT或READ事件發生,下列遍歷就會進行。
    while (it.hasNext())
    //來一個事件 第一次觸發一個accepter線程
    //以后觸發SocketReadHandler
    dispatch((Selecti)(it.next()));
    selected.clear();
    }
    }catch (IOException ex) {
    logger.debug("reactor stop!"+ex);
    }
    }

      //運行Acceptor或SocketReadHandler
    void dispatch(Selecti k) {
    Runnable r = (Runnable)(k.attachment());
    if (r != null){
    // r.run();

        }
    }

      class Acceptor implements Runnable { // inner
    public void run() {
    try {
    logger.debug("-->ready for accept!");
    SocketChannel c = serverSocket.accept();
    if (c != null)
    //調用Handler來處理channel
    new SocketReadHandler(selector, c);
    }
    catch(IOException ex) {
    logger.debug("accept stop!"+ex);
    }
    }
    }
    }

    以上代碼中巧妙使用了SocketChannel的attach功能,將Hanlder和可能會發生事件的channel鏈接在一起,當發生事件時,可以立即觸發相應鏈接的Handler。

    再看看Handler代碼:

    public class SocketReadHandler implements Runnable {

      public static Logger logger = Logger.getLogger(SocketReadHandler.class);

      private Test test=new Test();

      final SocketChannel socket;
    final Selecti sk;

    static final int READING = 0, SENDING = 1;
    int state = READING;

      public SocketReadHandler(Selector sel, SocketChannel c)
    throws IOException {

        socket = c;

        socket.configureBlocking(false);
    sk = socket.register(sel, 0);

        //將Selecti綁定為本Handler 下一步有事件觸發時,將調用本類的run方法。
    //參看dispatch(Selecti k)
    sk.attach(this);

    //同時將Selecti標記為可讀,以便讀取。
    sk.interestOps(Selecti.OP_READ);
    sel.wakeup();
    }

      public void run() {
    try{
    // test.read(socket,input);
    readRequest() ;
    }catch(Exception ex){
    logger.debug("readRequest error"+ex);
    }
    }


    /**
    * 處理讀取data
    * @param key
    * @throws Exception
    */
    private void readRequest() throws Exception {

      ByteBuffer input = ByteBuffer.allocate(1024);
    input.clear();
    try{

        int bytesRead = socket.read(input);

        ......

        //激活線程池 處理這些request
    requestHandle(new Request(socket,btt));

        .....


    }catch(Exception e) {
    }

    }

    注意在Handler里面又執行了一次attach,這樣,覆蓋前面的Acceptor,下次該Handler又有READ事件發生時,將直接觸發Handler.從而開始了數據的讀 處理 寫 發出等流程處理。

    將數據讀出后,可以將這些數據處理線程做成一個線程池,這樣,數據讀出后,立即扔到線程池中,這樣加速處理速度:

    更進一步,我們可以使用多個Selector分別處理連接和讀事件。

    一個高性能的Java網絡服務機制就要形成,激動人心的集群并行計算即將實現。

    posted on 2007-01-18 23:59 苦笑枯 閱讀(325) 評論(0)  編輯  收藏 所屬分類: Java
    收藏來自互聯網,僅供學習。若有侵權,請與我聯系!

    <2007年1月>
    31123456
    78910111213
    14151617181920
    21222324252627
    28293031123
    45678910

    常用鏈接

    留言簿(2)

    隨筆分類(56)

    隨筆檔案(56)

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 台湾一级毛片永久免费| 无码av免费一区二区三区| 永久免费看mv网站入口| 亚洲免费闲人蜜桃| 国产在线a免费观看| 亚洲一区中文字幕在线观看| 最近高清中文字幕无吗免费看| 亚洲精品自拍视频| 久久WWW色情成人免费观看| 亚洲一区二区无码偷拍| 永久免费bbbbbb视频| 国产偷国产偷亚洲高清在线| 亚洲国产精品日韩| a毛片久久免费观看| 亚洲精品福利网站| 成人免费看黄20分钟| 免费无码国产V片在线观看| 永久亚洲成a人片777777| 久久久久久久99精品免费 | 亚洲第一香蕉视频| 男男AV纯肉无码免费播放无码| 亚洲爆乳无码专区www| 亚洲av无码乱码在线观看野外| a级毛片在线免费看| 亚洲午夜久久久精品电影院| 在线免费一区二区| 中文字幕免费观看视频| 亚洲黄色在线视频| 国产美女a做受大片免费| 99在线免费视频| 中文有码亚洲制服av片| 亚洲精品国产自在久久| 99久久免费精品视频| 亚洲精品无码人妻无码| 337p日本欧洲亚洲大胆裸体艺术| 少妇人妻偷人精品免费视频 | 亚洲一卡一卡二新区无人区| 亚洲成A∨人片天堂网无码| 日韩人妻一区二区三区免费| 亚洲精品无码一区二区| 亚洲视频在线视频|