使用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)可靠异步方式能保证异步请求在远程被执行。