10、Request Response 请求响应
EasyNetQ也支持Request/Response消息模式。这种模式很容易实现Client/Server应用,即客户端发送一个请求给服务器,服务器处理请求然后返回一个响应。和传统的RPC(远程过程调用,如WebService)机制不同,EasyNetQ request/response操作不需要有一个名字,仅仅需要简单的定义一对request/response消息类型。
另外,不同于传统的RPC机制包括众多的web service 工具集,EasyNetQ的request/response模式是基于消息传递,因此它是开箱即用的异步模式。
发送请求,处理响应
用EasyNet发送请求,即调用IBus的Request方法。
var myRequest = new MyRequest{Text ="hello Server"}; var response = bus.Request<MyRequest, MyResponse>(myRequest); Console.WriteLine(response.Text);
这里我们创建了一个MyRequest类型的请求(消息),和MyResponse类型的响应(消息)——简单起见,都定义一个Text自动属性,然后调用IBus的Request方法,并用这个请求消息作为它的参数。
执行Request方法时当前线程阻塞在此,直到收到一个MyResponse类型消息。当返回这个response响应时,消息的Text属性值输出到控制台。
异步请求
消息传递天生是异步的。你发送一个消息,然后允许你的程序继续执行其他任务。在之后的某一时刻,你收到响应。
使用上面所示的同步Request方法,你的线程将阻塞,直到返回响应。
通常来说,使用RequestAsync方法(异步方法)返回一个Task是比较好的选择。
var task = bus.RequestAsync<MyRequest, MyResponse>(request); task.ContinueWith(response => { Console.WriteLine("Got response: '{0}'", response.Result.Text); });
响应请求
如果要写一个用来响应请求的服务,可以简单调用IBus.Respond方法。如下:
bus.Respond<MyRequest,MyResponse>(request => new MyResponse{ Text ="Responding to " + request.Text});
Respond带有单个参数,即一个Func<TRequest, TResponse>响应委托,用来接收一个请求并返回响应。我在上节讲“订阅回调委托”时说的注意事项,也适用于此处的响应委托。即:不要进行耗时的IO操作阻塞了线程。假如你非要这么干,应该使用ResponseAsync异步方法,而不是Respond方法。
异步响应
EasynetQ提供了一个RespondAsync 方法,它带有一个Func<TRequest, Task<TResponse>>委托参数。
这允许你在不阻塞EasyNetQ订阅处理(即循环获取消息)的情况下执行耗时的IO操作。
1 static void Main(string[] args) 2 { 3 //创建一个工作者容器。 4 var workers = new BlockingCollection<MyWorkder>(); 5 for(int i = 0; i < 10; i++) 6 { 7 workers.Add(new MyWorker()); 8 } 9 //创建一个Bus 10 var bus = RabbitHutch.CreateBus("host=localhost"); 11 //响应请求。 12 bus.RespondAsync<RequestServerTime, ResponseServerTime>( 13 request => 14 Task.Factory.StartNew(() => 15 { 16 var worker = workers.Take(); 17 try 18 { 19 return worker.Execute(request); 20 } 21 finally 22 { 23 workers.Add(worker); 24 } 25 })); 26 Console.ReadLine(); 27 bus.Dispose(); 28 }
示例应用
EasynetQ展示Request Response和Autosubcriber,连上使用Windsor IOC的示例代码地址如下:
https://bitbucket.org/philipogorman/createrequestservice/src
英文地址:https://github.com/EasyNetQ/EasyNetQ/wiki/Request-Response