Tars-Java網絡編程源碼分析(上)

                  上一篇 / 下一篇  2023-03-17 16:30:22

                    一、Tars框架基本介紹
                    Tars是騰訊開源的支持多語言的高性能RPC框架,起源于騰訊內部2008年至今一直使用的統一應用框架TAF(Total Application Framework),目前支持C++、Java、PHP、Nodejs、Go語言。
                    該框架為用戶提供了涉及到開發、運維、以及測試的一整套解決方案,幫助一個產品或者服務快速開發、部署、測試、上線。它集可擴展協議編解碼、高性能RPC通信框架、名字路由與發現、發布監控、日志統計、配置管理等于一體,通過它可以快速用微服務的方式構建自己的穩定可靠的分布式應用,并實現完整有效的服務治理。
                    vivo推送平臺也深度使用了該框架,部署服務節點超過一千個,經過線上每日一百多億消息推送量的考驗。
                    Tars-java 最新穩定版1.7.2以及之前的版本都使用Java NIO進行網絡編程;本文將分別詳細介紹java NIO的原理和Tars 使用NIO進行網絡編程的細節。
                    二、Java NIO原理介紹
                    從1.4版本開始,Java提供了一種新的IO處理方式:NIO (New IO 或 Non-blocking IO)  是一個可以替代標準Java IO 的API,它是面向緩沖區而不是字節流,它是非阻塞的,支持IO多路復用。
                    2.1 Channels (通道) and Buffers (緩沖區)
                    標準的IO基于字節流進行操作的,而NIO是基于通道(Channel)和緩沖區(Buffer)進行操作。數據總是從通道讀取到緩沖區中,或者從緩沖區寫入到通道中,下圖是一個完整流程。
                    Channel類型:
                    1. 支持文件讀寫數據的FileChannel
                    2. 能通過UDP讀寫網絡中的數據的DatagramChannel 
                    3. 能通過TCP讀寫網絡數據的SocketChannel
                    4. 可以監聽新進來的TCP連接,對每一個新進來的連接都會創建一個SocketChannel的ServerSocketChannel 。
                    SocketChannel:
                    ·打開 SocketChannel:SocketChannel socketChannel = SocketChannel.open();
                    · 關閉 SocketChannel:socketChannel.close();
                    · 從Channel中讀取的數據放到Buffer: int bytesRead = inChannel.read(buf);
                    · 將Buffer中的數據寫到Channel: int bytesWritten = inChannel.write(buf);
                    ServerSocketChannel:
                    通過 ServerSocketChannel.accept() 方法監聽新進來的連接,當accept()方法返回的時候,它返回一個包含新進來的連接的SocketChannel,因此accept()方法會一直阻塞到有新連接到達。
                    通常不會僅僅只監聽一個連接,在while循環中調用 accept()方法. 如下面的例子:
                    代碼1:
                    while(true){
                        SocketChannel socketChannel = serverSocketChannel.accept();
                         //do something with socketChannel...
                    }
                    ServerSocketChannel可以設置成非阻塞模式。在非阻塞模式下,accept() 方法會立刻返回,如果還沒有新進來的連接,返回的將是null。因此,需要檢查返回的SocketChannel是否是null。
                    代碼2:
                    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
                    serverSocketChannel.socket().bind(new InetSocketAddress(8888));
                    serverSocketChannel.configureBlocking(false);
                    while(true){
                        SocketChannel socketChannel = serverSocketChannel.accept();
                        if(socketChannel != null){
                            //do something with socketChannel...
                        }
                    }
                    Buffer類型:
                    ·ByteBuffer
                    · CharBuffer
                    · DoubleBuffer
                    · FloatBuffer
                    · IntBuffer
                    · LongBuffer
                    · ShortBuffer
                    Buffer的分配:
                    ByteBuffer buf = ByteBuffer.allocate(2048);
                    Buffer的讀寫:
                    一般是以下四個步驟:
                    1. 寫入數據到Buffer,最大寫入量是capacity,寫模式下limit值即為capacity值,position即為寫到的位置。
                    2. 調用flip()方法將Buffer從寫模式切換到讀模式,此時position移動到開始位置0,limit移動到position的位置。
                    3. 從Buffer中讀取數據,在讀模式下可以讀取之前寫入到buffer的所有數據,即為limit位置。
                    4. 調用clear()方法或者compact()方法。clear()方法將position設為0,limit被設置成capacity的值。compact()方法將所有未讀的數據拷貝到Buffer起始處,然后將position設到最后一個未讀元素后面。
                    mark() 與 reset()方法
                    通過調用Buffer.mark()方法,可以標記Buffer中的一個特定position,之后可以通過調用Buffer.reset()方法恢復到這個position。
                    duplicate()
                    此方法返回承載先前字節緩沖區內容的新字節緩沖區。
                    remaining()
                    limit 減去 position的值。
                    2.2 Selector(選擇器)
                    Java NIO引入了選擇器的概念,選擇器用于監聽多個通道的事件。單個的線程可以監聽多個數據通道。要使用Selector,得向Selector注冊Channel,然后調用它的select()方法。這個方法會一直阻塞到某個注冊的通道有事件就緒。一旦這個方法返回,線程就可以處理這些事件。
                  線程使用一個selector處理多個channel
                    代碼3:
                    channel.configureBlocking(false);
                    SelectionKey key = channel.register(selector,Selectionkey.OP_READ);
                    注意register()方法的第二個參數,這是一個監聽的集合,即在通過Selector監聽Channel時關注什么事件集合。
                    SelectionKey包含:
                    1) interest集合:selectionKey.interestOps()  可以監聽四種不同類型的事件:OP_ACCEPT、OP_CONNECT、OP_WRITE、OP_READ
                    2) ready集合:selectionKey.readyOps();  ready 集合是通道已經準備就緒的操作的集合,提供4個方便的方法:
                    ·selectionKey.isAcceptable();
                    · selectionKey.isConnectable();
                    · selectionKey.isReadable();
                    · selectionKey.isWritable();
                    3) Channel:selectionKey.channel();
                    4) Selector:selectionKey.selector();
                    5) 可選的附加對象:
                    selectionKey.attachment();  可以將一個對象或者更多信息附著到SelectionKey上,這樣就能方便的識別特定的通道。
                    提示:
                    OP_ACCEPT和OP_CONNECT的區別:簡單來說,客戶端建立連接是connect,服務器準備接收連接是accept。一個典型的客戶端服務器網絡交互流程如下圖:
                    selectedKeys() 
                    一旦調用了select()方法,并且返回值表明有一個或更多個通道就緒了,然后可以通過調用selector的selectedKeys()方法,訪問已選擇鍵集(selected key set)中的就緒通道。
                    wakeUp()
                    某個線程調用select()方法后阻塞了,即使沒有通道已經就緒,也有辦法讓其從select()方法返回。只要讓其它線程在阻塞線程調用select()方法的對象上調用Selector.wakeup()方法即可。阻塞在select()方法上的線程會立馬返回。如果有其它線程調用了wakeup()方法,但當前沒有線程阻塞在select()方法上,下個調用select()方法的線程會立即wake up。
                    close()
                    用完Selector后調用其close()方法會關閉該Selector,且使注冊到該Selector上的所有SelectionKey實例無效。通道本身并不會關閉。
                    通過Selector選擇通道:
                    · int select() 阻塞直到至少有一個通道在你注冊的事件上就緒了
                    · int select(long timeout) 增加最長阻塞毫秒數
                    · int selectNow() 不會阻塞,不管什么通道就緒都立刻返回

                  TAG: 軟件開發 Java java

                   

                  評分:0

                  我來說兩句

                  日歷

                  « 2023-04-10  
                        1
                  2345678
                  9101112131415
                  16171819202122
                  23242526272829
                  30      

                  數據統計

                  • 訪問量: 116285
                  • 日志數: 549
                  • 建立時間: 2020-08-11
                  • 更新時間: 2023-04-04

                  RSS訂閱

                  Open Toolbar
                  亚洲欧洲自拍图片专区123_久久久精品人妻无码专区不卡_青青精品视频国产色天使_A免看的日黄亚洲