深入剖析SCA异步调用模式(二)

日期: 2008-10-28 作者:Yu ZhangXiao Li Yu 来源:TechTarget中国 英文

  这里,您可以选择一些参数:异步调用类型和调用是否跨越模块边界。

  在调用JSP文件以后,JSP页面上选择的参数被传递给Caller组件的Java实现(请参见清单4)。该实现将根据参数发出特定的异步调用。

  清单4. Caller组件的实现
  public void makeAsyncCall(Boolean isCrossModuleInvocation,
      Integer asyncInvocationType) {
  
  System.out.println(“=========> into caller’s makeAsyncCall method,
   parameters are: isCrossModule:” +  isCrossModuleInvocation +
   ” asyncInvocationType:” + asyncInvocationType);
 
  Service callee = null;
  if (isCrossModuleInvocation) {
   //cross module invocation.
   callee = this.locateService_HelloSCAIntfPartner1();
  } else {
   callee =  this.locateService_HelloSCAIntfPartner();
  }
  
  switch(asyncInvocationType) {
   case  1:
    callee.invokeAsync(“oneWayCall”, “hello”);
    break;
   case 2:
    AsyncTicket ticket = (AsyncTicket)callee.invokeAsync(“twoWayCall”, “hello”);
    System.out.println(“===========>Invocation Type is two way deferred response,
      ticket:” + ticket.getId());
    try {
  Thread.currentThread().sleep(2*1000);
    } catch (InterruptedException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
    }
    
    DataObject result = (DataObject) callee.invokeResponse(ticket, Service.WAIT);
    System.out.println(result.get(“output”));
    
    break;
   case 3:
    ticket = (AsyncTicket)callee.invokeAsyncWithCallback(“twoWayCall”, “hello”);
    System.out.println(“===========> Invocation Type is two way call back, ticket:”
      + ticket.getId());
    
    break;
   default:
    System.out.println(“wrong type:” + asyncInvocationType);
     
  
     }
   }
 
  总共存在六种组合,接下来的几个部分将对此进行详细的介绍。

  单模块异步调用:单向

  ·在JSP页面上,确保选择SingleModuleInvocation和asyncOneWay,然后单击Submit按钮。

  ·在调用完成以后,打开SystemOut日志文件。您应该看到已生成了如清单5所示的信息。

  清单5. 单模块中的单向异步调用的SystemOut日志
  [6/2/08 13:37:02:093 CST] 00000067 SystemOut     O =====> destination name:
    sca/Caller/component/Callee
  [6/2/08 13:37:02:124 CST] 00000067 SystemOut     O =====> destination   name:sca/Caller
 
  可以看到,此调用中涉及到两个目的地:sca/Caller/component/Callee和sca/Caller。正如目的地名称所指示的,sca/Caller/component/Callee表示Callee组件,sca/Caller表示该模块本身。关键配置:在将消息路由到sca/Caller/component/Callee以后,消息会自动重新路由到sca/Caller目的地。这是通过在目的地sca/Caller/component/Callee上定义缺省转发路由路径来实现的,如图9所示。

  图9. 缺省转发路由路径
 
  基于SystemOut日志文件中生成的日志,您可以创建消息流序列关系图,如图10所示。Caller组件发出异步调用,然后请求将由SCA运行时进行处理。SCA运行时将请求和目标服务信息放入消息中,然后SCA运行时将消息放入sca/Caller/component/Callee目的地中。下一步,根据缺省转发路由路径,消息将路由到sca/Caller目的地。MDB被触发以处理该消息;它只是拾取该消息,从消息正文中获取请求数据,从消息标头中获取目标服务信息,然后将信息发送给SCA运行时。基于此信息,SCA运行时可以知道应该将请求路由到哪一个组件。

  图10. 单模块异步调用的消息流序列关系图:单向
 
  单模块异步调用:延迟响应

  第二种场景是异步延迟响应。在清单6中,您可以看到您首先发出了一个异步请求。在调用完成以后,您可以获取一个票据(ticket)对象。稍后您可以使用此票据来查询结果。

  清单6. 延迟响应调用
  AsyncTicket ticket = (AsyncTicket)callee.invokeAsync(“twoWayCall”, “hello”);
  //do something

  //query result    
  DataObject result = (DataObject) callee.invokeResponse(ticket, Service.WAIT);
 
  ·在JSP页面上,确保选择SingleModuleInvocation和asyncDeferredResponse,然后单击Submit按钮。

  ·在调用完成以后,打开SystemOut日志文件。您应该看到已生成了如清单7所示的信息。

  清单7. 单模块中的延迟响应异步调用的SystemOut日志
  [6/2/08 13:38:30:942 CST] 00000067 SystemOut     O =====>
    destination name:sca/Caller/component/Callee
  [6/2/08 13:38:30:942 CST] 00000067 SystemOut     O =====> destination   name:sca/Caller
  [6/2/08 13:38:31:036 CST] 00000067 SystemOut     O =====>
    destination name:sca/Caller/component/Callee
  [6/2/08 13:38:31:083 CST] 00000067 SystemOut     O =====> destination    name:sca/Caller
 
  在SystemOut日志中,您可以看到除了sca/Caller/component/Callee和sca/Caller以外,还使用了另一个目的地sca/Caller/component/Caller。SCA运行时使用此目的地来传送响应消息。其机制如下:在调用目标服务并生成响应以后,SCA运行时知道该消息是响应消息。然后SCA运行时将消息放入此目的地中(SCA运行时维护有每个调用的消息标头,因此它知道请求来自于何处,以及应该将响应发送到何处)。同样,sca/Caller/component/Caller中定义了缺省的转发路由路径,然后消息将路由到sca/Caller模块目的地。消息一直保留在此目的地中,直到您发出invokeResponse请求来使用它为止。

  图11. 单模块异步调用的消息流序列关系图:延迟响应
 
  单模块异步调用:回调

  此场景与延迟响应场景相同,只不过结果将由SCA运行时自动发回给调用者。幕后的“魔法”在于,caller类具有一个接收响应的方法。因此如清单8所示,当SCA运行时取回响应消息时,它将调用Caller的特定方法来将响应传递给Caller。

  清单8. 回调调用
  public void onTwoWayCallResponse(Ticket __ticket, String returnValue,
    Exception exception) {

  //proces response message.
  
   }
 
  清单9显示了在使用SingleModuleInvocation和asyncDeferredResponse参数提交请求之后,SystemOut日志文件中生成的日志信息。

  清单9. 单模块中的回调异步调用的SystemOut日志
  [6/2/08 13:39:59:385 CST] 00000067 SystemOut     O =====>
   destination name:sca/Caller/component/Callee
  [6/2/08 13:39:59:416 CST] 0000006f SystemOut     O =====> destination   name:sca/Caller
  [6/2/08 13:39:59:588 CST] 00000067 SystemOut     O =====>
   destination name:sca/Caller/component/Caller
  [6/2/08 13:39:59:603 CST] 0000006f SystemOut     O =====> destination   name:sca/Caller


 
  图12. 单模块异步调用的消息流序列关系图:回调
 
  跨模块异步调用:单向

  转向跨模块的场景时,情况变得稍微有点复杂,因为必须正确地将请求消息和响应消息传递到正确的目的地,而这些目的地位于不同的模块中。

  ·在JSP页面上,确保选择IsCrossModuleInvocation和asyncDeferredResponse。然后单击Submit按钮。

  ·在调用完成以后,打开SystemOut日志文件。您应该看到已生成了如清单10所示的信息。

  清单10. 跨模块单向异步调用的SystemOut日志
  [6/2/08 13:55:31:782 CST] 0000006f SystemOut     O =====>
   destination name:sca/Caller/importlink/CalleeImport
  [6/2/08 13:55:31:829 CST] 0000006f SystemOut     O =====>
   destination name:sca/Callee/exportlink/CalleeExport
  [6/2/08 13:55:31:876 CST] 0000006f SystemOut     O =====> destination   name:sca/Callee
 
  根据生成的日志,您可以绘制消息路由序列关系图(如图13所示)。

  图13. 跨模块异步调用的消息流序列关系图:单向
 
  这里的要点在于,在部署期间,将会在sca/Caller/importlink/CalleeImport上创建缺省转发路由路径。然后在消息到达此目的地时,消息将被自动转发到sca/Callee/exportlink/CalleeExport,后者驻留在Callee模块中。同样,sca/Callee/exportlink/CalleeExport上定义了缺省转发路由路径,因此在消息到达此目的地时,消息将被转发到sca/Callee目的地。正如前面所讨论的,生成的MDB将发挥作用以使用该请求消息。

  跨模块异步调用:延迟响应

  清单11显示了为延迟响应调用生成的日志。

  清单11. 跨模块延迟响应异步调用的SystemOut日志
  [6/2/08 13:57:08:491 CST] 0000006f SystemOut     O =====>
   destination name:sca/Caller/importlink/CalleeImport
  [6/2/08 13:57:08:506 CST] 0000006f SystemOut     O =====>
   destination name:sca/Callee/exportlink/CalleeExport
  [6/2/08 13:57:08:506 CST] 0000006f SystemOut     O =====> destination   name:sca/Callee
  [6/2/08 13:57:08:569 CST] 0000006f SystemOut     O =====>
   destination name:sca/Caller/import/CalleeImport
  [6/2/08 13:57:08:569 CST] 0000006f SystemOut     O =====> destination   name:sca/Caller
 
  在消息路由序列关系图中,可以看到在结果可用之后,SCA运行时可以直接将响应消息发回到Caller模块的目的地。其基本原理在于,当在Caller的模块中发出延迟响应调用时,SCA知道该调用是跨模块调用,并将响应目的地名称放入请求消息标头中。然后在目标端,当服务调用返回时,SCA运行时将向从请求消息标头中检索到的目的地发送响应。

  您可以使用清单12中的示例代码来从消息标头中获取响应目的地名称。消息路由序列关系图如图14所示。

  清单12. 用于获取响应目的地的示例代码
  SIMessageContext ctx =(SIMessageContext)context;
  String responseDestination = ctx.getSIMessage().getUserProperty  (“scaTargetDestination”));


 
  图14. 跨模块异步调用的消息流序列关系图:延迟响应
 
  跨模块异步调用:回调

  回调调用类似于延迟响应调用,只不过结果将自动传递给调用者。清单13显示了所生成的日志。

  清单13. 跨模块回调异步调用的SystemOut日志
  [6/2/08 14:01:07:143 CST] 0000006f SystemOut     O =====>
   destination name:sca/Caller/importlink/CalleeImport
  [6/2/08 14:01:07:159 CST] 0000006f SystemOut     O =====>
   destination name:sca/Callee/exportlink/CalleeExport
  [6/2/08 14:01:07:581 CST] 00000077 SystemOut     O =====> destination   name:sca/Callee
  [6/2/08 14:01:07:659 CST] 0000006f SystemOut     O =====>
   destination name:sca/Caller/component/Caller
  [6/2/08 14:01:07:690 CST] 00000077 SystemOut     O =====> destination   name:sca/Caller
 
  消息路由序列关系图如图15所示。

  图15. 跨模块异步调用的消息流序列关系图:回调
 
  结束语

  在本文中,您了解了SCA运行时如何处理异步调用,以及SCA运行时如何利用基础的消息系统(WebSphere Process Server)来实现异步调用。架构师可以使用此信息作为参考,从而设计大规模、基于消息的面向服务的体系结构(Service-Oriented Architecture,SOA)。

  作者简介

  Yu Zhang是IBM中国软件开发实验室的一名软件工程师,他在那里从事IBM WebSphere Process Server方面的工作已超过四年时间。他拥有系统验证测试和客户案例合作项目方面的丰富经验。现在他是负责产品交付的WebSphere Process Server组件技术负责人。
 
  Xiao Li Yu是IBM中国软件开发实验室的一名软件工程师,她在那里从事IBM WebSphere产品方面的工作已超过四年时间。她的工作重点是测试,包括功能验证测试、系统验证测试、压力测试和持久性测试。现在她是WebSphere Process Server的运行时工具测试负责人。

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐