在Ice有两种异步使用的方式,AMI和AMD。AMI是异步方法调用,AMD是异步方法调度(分派)。前者用在代理端,后者用在饲服实现端。
AMI其实就是在代理端,使用Future机制进行异步调用,而不阻塞等待响应结果。
AMD只是提供一种回调机制,让你可以选择返回响应的时机,不必在Skeleton调度(分派)你的方法调用最后返回响应,这样你可以制造一个barrier让一组响应同时返回。或者在你的方法实现中要依赖代理远程调用时,组合这个代理AMI方式,让你的响应操作在AMI完成事件回调处执行,这点是在饲服实现端进行AMI代理调用的必要前提。AMD方式让你的调用分派是否并发没有关系,因为是对象适配器使用线程池在并发分派你的调用。
我们先来看看一次Ice远程调用在不使用异步方式编程的活动流
在ActiveObject模式下,调用和调用调度执行分别在两条不同的控制流中进行。并且在调用执行之外的增加了不少开销,其中调用红色的活动是可能发生长时间等待,或消耗长时间处理,发而阻塞住活动所在的控制流。在调用方的控制流可能因为等待响应结果而阻塞,而远端调用调度执行的控制流也可能因为调用执行本身会等待事件或进行长时间任务而阻塞。所在不论在调用方的控制流抑或远端调用调度执行的控制流都需要应用异步编程的方法来避免阻塞。在调用方控制流使用异步编程的方法叫做AMI,远端调用调度执行的控制流使用异步编程的方法叫做AMD。一般地异步编程方法将一个任务分开两部分,分别在不同的控制流中执行,任务调度给别的控制流后将转入其它任务的执行上下文。
由于等待事件而阻塞控制流,则将等待事件和后续任务调度给其它控制流,然后离开当前任务的控制流。
由于任务中包含了长时间的子任务,则将长时间的子任务调度给别的控制流,然后离开当前任务的控制流。
因为在调用方(即使用代理方)的控制流上同步等待响应结果的话,就可能需要长时间阻塞当前控制流,所以在调用方等待响应结果的任务使用回调调度到其它控制流的编程方法就是AMI(Asynchronous Method Invoke)。
而在远端调用调度执行方,为了不阻塞调度(Dispatch)的控制流,使用异步编程方法就是AMD(Asynchronous Method Dispatch)。由于远端调用执行在调度的控制流上,至使因为一个长时间执行或需要等待的调用会阻塞调度控制流,从而不能调度其它请求的调用,降低调度请求的吞吐。将调用的响应任务做成可回调,就可以使调用执行从调度控制流中分离出来,不至阻塞住调度控制流。这就是AMD相关的框架设施为我们提供的服务。
下面是使用AMD方式的三种情况:
长时间执行的调用从调度流分离
在调用执行中依赖其它远程调用,要使用AMI,就必须依赖AMD,即在Servant端组合AMI到AMD使用。换句话说,当你看到一个接口的方法声明为["amd"]时,可能意味着这个方法的执行中依赖另外的代理(远程调用)。
第三种是用AMD来同步(Sync Barrier)响应输出。Barrier绝对不能做在调度控制流上,所以Barrier依赖AMD。有这么一种情况,调用在调度控制流的线程池中并发执行,响应的次序不能确保,而你需要确保响应有序,那么就必须设立一个Barrier,然后在Barrier处将响应重建次序。