一:傳統socket分析數據庫
1.tomcat
Server.accept();傳統socket是會阻塞等待客戶端請求的,讀取時也是會阻塞的。安全
InputStream.read(bytes)(讀取阻塞)服務器
問題是,原始的寫法並非多線程併發的,在處理某個正被阻塞的請求時是不會再去處理新進入的請求的。那如何解決多線程併發的問題呢?用ExecutorService線程池的方式是一種方法。多線程
那麼問題又來啦,一個請求就分配一個服務生,這樣的資源消耗若是作長鏈接的服務仍是有些頭疼吧。只不過從歷史引進方面,短鏈接仍是能處理的,好比之前的tomcat就採用了一問一答的形式,基本不多出現獨佔的狀況,一個線程是能夠處理多個任務的。併發
總結:單線程時只有一個客戶端,線程池時可有多個客戶端,只是很消耗資源,不適合作長鏈接的服務器,短鏈接的應答模式如tomcat仍是能用一下的。框架
2.NIOsocket
initServer(serversocket 綁定端口)oop
而後listen(selector是阻塞的,得到key,將處理selector key,會註冊一個socket事件,selector將不會不斷阻塞)源碼分析
ServerSocketChannel ServerSocket(餐廳)
SocketChannel Socket(客戶)
Selector是核心(服務生)
NIO能夠實現單線程爲多個客戶服務,傳統IO是不適應的。傳統IO是一個客人對應一個服務員。
NIO能夠用餐廳服務生點菜的方式理解,一個服務生能夠被多個客戶共享。只要一個服務生不斷的等待被調用,接待客人或想用客人點菜。NIO是netty的基礎,不然netty是很差看懂的。明白的是思想,而不是別的。
SimpleChannelHandler處理消息的接收和發放,檢測消息是不是惡意頻繁訪問,下線異常處理和數據清理等業務連接控制,上圖的boss,worker一個是監聽端口,一個是控制選擇器的。
Netty整個線程工做的原理:
Netty客戶端寫法,和服務端寫法類似,客戶端,編碼解碼器,沒有鏈接的話是不能disconnected的,會直接close.連的話,並不僅是連一次。
分析下netty的原碼,netty的工做原理,要知其然和因此然。
原始IO,一個線程服務一個socket客戶。NIO能夠一個線程服務多個客戶端,selector能夠選擇多個客戶端,只要selector打開相應的channel。我以爲就是把單線程的長鏈接佔用別讓它空閒,充分的利用它來監聽多個可能的請求,選擇合適的,而後進行業務處理。而不像IO那樣是one2one綁定佔用式的服務。
NIO,1個線程+selector服務多個客人
NIO問題,說一個IO是否阻塞,不是看執行是否停在那裏了,而是是否會馬上返回數據,selector.wakeup()能夠喚醒,因此基本是沒有阻塞的狀況。Selector容許關注某些事情,事情關注了纔會去響應。(好比SelectorKey.Write).
Netty,hadoop,dubbo,akka用在什麼地方,底層RPC通訊基本都是基於netty。部分遊戲服務器已經開始使用netty.netty是個線程消息數據得到等很好的框架。開始咱們NIO並非多線程的。咱們建立個線程池,處理時扔到線程池裏面。對IO的操做方式弄個線程池就能夠了。ExecutorService es = Executors.newCachedThreadPool(); es.execute(new Runnable(){ public void run(){ handler(socket);}});可是多線程時倒是報錯的。一個NIO有多個selector, 並且一個selector能夠註冊多個服務。若是餐廳擴大,一個服務生能夠按片來監督和管理本身的負責的區域,一個餐廳能夠被分紅多個區域。一個併發很好的思想是不會直接主動的調用任務而是往任務隊列中壓入任務。Netty的工做原理,基本是本身的對象執行本身的任務,放入隊列任務,從隊列中取出對應的任務,註冊,wakeup後執行。
Netty源碼分析:
1. 看代碼直接引入了項目,而後打印些東西進行跟蹤。處理些任務隊列,處理,分配原理。
2. 學到了棧頂的執行,學到了斷點設置屬性。先調用的在棧底。
3. 先把基礎的弄懂。
Netty回顧,客戶端鏈接服務端時,若是鏈接成功會有disconnected,而後closed。若是沒有鏈接成功直接就closed。
線程池:內部是有多個隊列放線程的,執行時是併發執行的
1個htread+隊列=一個單線程線程池=》線程安全,任務是線性串行執行的。
單客戶端,多鏈接如何維護呢?
A. 對象池
B. 對象組
對象池用在什麼地方呢?當單個對象線程不安全,或多線程併發產生阻塞效應的時候能夠嘗試用對象池的設計。好比數據庫鏈接池,不是線程安全,或併發會產生阻塞效應。
還有一種設計叫對象組設計方式,這種方式並不移除對象,因此就有多個線程訪問同個對象的可能,因此要求這個對象要有併發的能力。那麼客戶端用channel寫數據時是否線程安全呢,SingleThreadEventExecutor是單線程+線程池,是串行執行的,不會有併發問題。
使用ip,可能出現斷網重連的可能。
Netty心跳
1.用戶長時沒讀寫,須要斷掉會話,這個時候檢測狀態,學習idleStateHandler