使用NIO可以完成鏈接複用以及對調用者的同步調用的支持,其調用方式,除了同步調用外,還有以下的幾種調用方式。java
原理:單向(Oneway)發送特色爲只負責發送消息,不等待服務器迴應且沒有回調函數觸發,即只管發送請求而不關心結果。此方式發送消息的過程耗時很是短,通常在微秒級別。在NIO下使用oneway的話,會比同步調用簡單不少,以下圖所示:服務器
把發送的數據放入數據隊列中就能夠繼續後面的任務了。IO線程也只用從數據隊列中讀出數據而後經過Socket發送出去就行了,Oneway不關心對方是否接收到了數據,也不關心對方收到數據以後最什麼或則有什麼返回。屬於不保證可靠送達的通知。異步
應用場景:適用於某些耗時很是短,但對可靠性要求並不高的場景,例如日誌收集。ide
public void invokeOneway(String addr, RemotingCommand request, long timeoutMillis) throws InterruptedException, RemotingConnectException, RemotingTooMuchRequestException, RemotingTimeoutException, RemotingSendRequestException { Channel channel = this.getAndCreateChannel(addr); if (channel != null && channel.isActive()) { try { if (this.rpcHook != null) { this.rpcHook.doBeforeRequest(addr, request); } this.invokeOnewayImpl(channel, request, timeoutMillis); } catch (RemotingSendRequestException var7) { ······ } } else { ······ } }
上面的代碼是com.aliyun.openservices包中mq的onceway的實現,能夠看到invokeOnewayImpl()建立channel發送消息,其餘的就不關心了。函數
這種方式下請求發送方發送請求以後會繼續執行本身的操做,等對方有響應時進行一個回調。設計圖以下:學習
上圖分析:
(1)調用者首先設置了回調對象,而後將數據寫入數據隊列以後就能夠作本身的事了。網站
(2)後面的IO線程也是同樣,從數據隊列中取出數據,創建Socket而後發送給服務端。this
(3)當服務提供者返回以後,IO線程會通知回調對象,這時候就執行回調方法。spa
(4)若是須要支持超時,一樣經過定時任務來處理,若是超時服務提供者尚未返回,這時候也執行回調方法,通知超時沒有結果。線程
(5)這裏須要注意的是,回調函數的執行最好是在單獨的線程中,不要放在IO線程中執行,防止回調函數的執行時間長等問題影響了IO線程。
producer.sendAsync(msg, new SendCallback() { @Override public void onSuccess(SendResult sendResult) { // TODO } @Override public void onException(OnExceptionContext onExceptionContext) { // TODO } });
上面的代碼中sendAsync()方法採用就是Callback回調方式,不管msg是否發送成功,或者是否超時,都會調用SendCallback。
這種實現的結構以下圖:
一樣是在數據入隊前設置Future對象,接着就在線程中發送數據到服務提供者。等到獲取到服務提供者的響應以後,就經過Future來獲取通訊結果並直接控制超時。
可靠異步要保證異步請求可以在遠程被執行,通常經過消息中間件來完成這個保障。
上面四種異步通訊方式中:(1)Oneway是單向的通知;(2)Callback回調是一種被動的方式,Callback的執行不是在原請求線程中。(3)Future是一種可以主動控制超時、獲取結果的方式,而且它的執行仍然在原請求線程中。(4)可靠異步方式能保證異步請求在遠程被執行。