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

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲毛片αv无线播放一区| 亚洲免费观看视频| 亚洲精品中文字幕麻豆| 免费国产成人高清在线观看麻豆| 51精品视频免费国产专区| 一级毛片大全免费播放下载| 亚洲熟伦熟女专区hd高清| 亚洲国产日韩一区高清在线| 亚洲性日韩精品国产一区二区| 日韩成人免费视频播放| 91精品成人免费国产片| 国产拍拍拍无码视频免费| 中国一级特黄高清免费的大片中国一级黄色片 | 99久久综合国产精品免费| 久久国产精品2020免费m3u8| 国产精品免费视频观看拍拍| 在线观看亚洲免费| 亚洲精品无码一区二区| 33333在线亚洲| 久久精品国产亚洲av麻豆蜜芽| 亚洲毛片在线观看| 亚洲av中文无码乱人伦在线r▽| 国产偷国产偷亚洲高清日韩| 亚洲VA综合VA国产产VA中| 国产福利免费观看| 国产精品色午夜免费视频| 午夜两性色视频免费网站| 毛片在线看免费版| 99久久免费精品国产72精品九九 | 国产亚洲精品精品国产亚洲综合| 国产美女无遮挡免费视频| 日韩免费电影在线观看| 国产a级特黄的片子视频免费| 国产极品美女高潮抽搐免费网站| 四虎影视大全免费入口| 天天摸天天碰成人免费视频| 一个人看的www在线观看免费| 久久久www成人免费毛片| 最近中文字幕无免费视频| 免费看AV毛片一区二区三区| 免费看大美女大黄大色|