<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)

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲色大成网站www久久九| 国产精品亚洲综合专区片高清久久久| 亚洲国产精品无码专区在线观看| 人人公开免费超级碰碰碰视频| 国产男女猛烈无遮挡免费网站| 亚洲国产精品自在自线观看| 麻豆国产入口在线观看免费| 亚洲6080yy久久无码产自国产| 成人永久福利免费观看| 国产亚洲精品2021自在线| 免费少妇a级毛片| ww在线观视频免费观看w| 亚洲精品无码国产| 黄色网址在线免费| 亚洲黄色网址大全| 成人毛片免费观看视频大全| 国产成人高清亚洲一区久久 | 免费看美女让人桶尿口| 亚洲人成网站在线播放2019| 成人免费淫片在线费观看| 国产AV无码专区亚洲AV蜜芽 | 亚洲日本VA午夜在线影院| 四虎永久在线精品视频免费观看| 日本永久免费a∨在线视频 | 亚洲第一永久在线观看| 67194成是人免费无码| 老司机午夜精品视频在线观看免费 | 亚洲婷婷天堂在线综合| 免费看片免费播放| 高清免费久久午夜精品 | 久久亚洲国产中v天仙www | 久久er国产精品免费观看8| 久久久国产精品亚洲一区| 成年在线观看免费人视频草莓| 全黄A免费一级毛片| 精品日韩亚洲AV无码| 在线免费不卡视频| 伊人免费在线观看高清版| 国产精品亚洲综合五月天| 亚洲精品一级无码中文字幕| 免费成人福利视频|