Axis2的session(会话)管理

来源:互联网 发布:淘宝mg店什么意思 编辑:程序博客网 时间:2024/05/18 16:14
本文是对《Axis2 Session Management》的翻译,所依据的英文在http://www.developer.com/services/article.php/3620661/Axis2-Session-Management.htm。以下是翻译内容。
    Web服务有着很大的需求,很多人进入了Web服务这一领域,其结果是人们需要Web服务具有更多的特性,以便使用Web服务可以完成任何事情。但Web服务从设计上来说是没有状态的。在Web服务世界起初的时候是没有管理会话的概念的,但是现在形势改变了:没有会话管理,开发者是无法开发出高级的应用程序的。一个很好的例子是银行系统,您登录进入系统,然后取钱,最后退出登录。
    如果我们把这一场景映射到Web服务:
  • 首先,用户登录进自己的账户(调用登录方法)
  • 用户取钱(在他的账户上调用一些操作)
  • 用户退出登录(完成事务)
    您可以很容易的看出上述3个操作是相互关联的,同一个用户进行3个调用操作。所以,这意味着需要有地方来跟踪用户,另外有地方在用户调用方法期间跟踪用户数据。这也就暗含了需要会话管理。
    当开发高级应用程序时,我们必须打破现有的规则;否则,没有人能够开发出真正的Web应用程序。虽然Web服务本质上是无状态的,但是需要在Web服务之上增加一层会话管理的功能。
    Axis2的无状态本质
    Axis2的优秀设计原则之一是保持逻辑和状态的分离,所以它没有组件需要维护会话,实际上也是这样做的。在Axis2的处理程序中,传输部分,甚至Aixs引擎部分都是无状态的。因此,对Axis2来说多个实例和一个实例是没有区别的。
    作为最佳实践,处理程序或传输部分不应该保持任何实例变量(如果可能会变化的话),因为那样会打破Axis2无状态的本质。所以,如果处理程序或传输部分需要有状态的方式,正确的做法是在需要的时候保存状态和Axis2的状态层次,而不是保持实例变量。
    Axis2的会话类型
    像上面提到的,企业级Web服务无法得到认可除非引在Web服务引擎中入了会话概念。换种说法,因为存在不需要维持会话的Web服务,让每种Web服务引擎都支持会话管理这样的说法是不对的。一个很好的例子是Google搜索服务和Google拼写检查服务。
    会话管理的直接影响是占用内存空间的上升和性能的降低,所以您需要一个折中:您的服务是否要支持会话并提供状态。Axis2是定位于企业级Web服务引擎的,所以它必须提供会话管理。
    有几种类型的会话,它们的生命周期是各不相同的。有些会话存在几秒钟,而有些会话的生命周期和系统一样长。Axis2设计为支持4种类型会话,它们存在很多差别,希望您能够使用以下4种会话类型开发出各种Web服务。
  • Request
  • SOAPSession
  • Application
  • Transport
    Axis2的上下文层次结构
    在深入讨论Axis2的会话之前,理解Axis2的各种上下文是很有帮助的。如上所述,Axis2保持逻辑和状态的分离,上下文是保存状态的地方。在Axis2中有5种类型的上下文:
  • ConfigurationContext:整个系统运行时的表述,为了启动Axis2系统需要有一个配置上下文。配置上下文与系统的生命周期是一样的,在这里保存一些状态(配置项)能够一直有效(直到系统关闭)。
  • ServiceGroupContext:在Axis2中,可以在一个服务组中部署多个服务。在运行时,有一个或多个服务组(依赖于组的会话范围)上下文在会话范围内保存组的状态。
  • ServiceContext:表述一个服务的运行时状态,其生命周期与会话的生命周期相同。依赖于所对应服务的会话范围,存在一个或多个服务上下文。
  • OperationContext:表述MEP(Message Exchange Patterns,消息交换格式)的生命周期。操作上下文的生命周期通常短于服务上下文的生命周期。
  • MessageContext:表述所输入消息的生命周期。如果给定执行链中的两个处理程序想共享数据,最好的方法是把他们存在消息上下文中。一个操作上下文可能有多个消息上下文。
    与会话范围无关,当会话开始和结束时,Axis2会通知服务的实现类,但是需要在服务的实现类中增加两个方法。
public void init(ServiceContext serviceContext) {
}

public void destroy(ServiceContext serviceContext) {
}
    除此之外,当服务接收到一个请求时,它会传入相应的操作上下文作为参数进行通知。如果服务想访问输入消息的上下文或输入的SOAP消息,可以在服务的实现类中加入以下方法来做到这一点,在真正的方法调用之前调用这一方法。
public void setOperationContext(OperationContext operationContext) {
}
    请求会话范围(Request Session Scope)
    请求会话是Axis2默认的会话类型,部署服务时没有指定会话管理的内容,服务会被部署为请求会话类型。这种会话的生命周期被限定在方法调用的生命周期之内,或者请求的处理时间内。所以,当部署服务为请求范围的服务时,是没法管理会话的;这与没有会话是一样的。
    一旦把服务部署为请求会话范围的服务时,每个服务的实现类就会准备建立服务实例。例如以请求范围的方式建立了一个名为“foo”的服务,如果客户端调用了10次,就会有这个服务实现类的10个实例。如果想显式的指定服务的会话范围,可以在services.xml中的service标签中增加一个scope属性,如下:
<service name="foo" scope="request">
</service>
    即使把服务部署为请求范围内的,在Axis2中也有一些方法管理会话。一种方法是在Axis2的全局运行时(配置上下文)中保存状态,在需要的时候获取它。
    SOAP会话范围(SOAP Session Scope)
    SOAP会话的生命周期比请求会话的稍长,以SOAP会话的方式部署服务需要修改services.xml。管理SOAP会话需要客户端和服务都能识别会话,换句话说,客户端访问相同会话需要传输会话相关的数据,服务需要以会话相关的数据来验证用户。
    管理SOAP会话,客户端需要在SOAP头中增加名为“serviceGroupId”的参数。SOAP会话不仅提供一个服务调用的会话,还提供一个服务组中多个服务的会话。只要在同一个SOAP会话中,可以在服务上下文中管理服务相关的数据;如果想在组中多个服务中共享数据,可以使用服务组上下文。
    以SOAP会话的方式部署了服务,当客户端第一次访问服务的时候,Axis2会产生“serviceGroupId”,并在wsa:ReplyTo中以引用参数的方式向客户端传输:
<wsa:ReplyTo>
  <wsa:Address>
  http://www.w3.org/2005/08/addressing/anonymous
  </wsa:Address>
  <wsa:ReferenceParameters>
    <axis2:ServiceGroupId xmlns:axis2=
      "http://ws.apache.org/namespaces/axis2">
        urn:uuid:65E9C56F702A398A8B11513011677354
    </axis2:ServiceGroupId>
  </wsa:ReferenceParameters>
</wsa:ReplyTo>
    如果客户端想保持在同一个会话内,它要复制那个引用参数,并在第二次调用服务的时候传回服务器。只要客户端传输了正确的“serviceGroupId”,它就会在同一个会话内,服务也可以维护会话相关的数据。与请求会话不同,SOAP有默认的失效期,如果客户端超过30秒没有连接服务,会话就会过期。如果客户端发送了过期的“serviceGroupId”,会得到Axis错误。
    管理SOAP会话需要衔接服务端和客户端的对应模块。部署服务为SOAP会话方式需要以如下方式修改services.xml:
<service name="foo" scope="soapsession">
</service>
    传输会话范围(Transport Session Scope)
    在传输会话方式下,Axis2以传输相关的会话管理技术来管理会话。例如,在HTTP协议下,以HTTP cookies的方式来管理会话。会话的生命周期是由传输来控制的,而不是Axis2;Axis2在传输会话内保存服务上下文和服务组上下文,所以在会话生命期内服务都可以访问这些上下文。
    传输会话的主要优势是在一个会话内与多个服务组交互。在SOAP会话中,无法在两个服务组间进行交互,而在传输会话中就可以。这种情况下,服务实例的数量取决于传输会话的数量。
    部署服务为传输会话方式需要以如下方式修改services.xml:
<service name="foo" scope="transportsession">
</service>
    如果打算使用Axis2,以传输会话方式部署服务需要对axis2.xml做些修改。这主要是为了提高内存的使用率;否则,无论是否以传输会话方式部署服务,Axis2都会在传输的级别建立会话对象;有了这些变化,Axis就不会创建无用的对象了。为了管理传输级别的会话,需要在axis2.xml中设置“manageTransportSession”参数为“true”:
<parameter name="manageTransportSession"
    locked="false">true</parameter>
    应用范围(Application Scope)
    应用范围的会话与其他会话方式相比具有最长的生命周期,应用会话的生命周期与系统的生命周期一样长。如果以应用范围会话的方式部署服务,只会有服务的一个实例,并且这个服务只有一个服务上下文。在Axis2中,如果考虑内存占用,并且不想管理会话,一个好的方法是把服务部署为应用范围的。
    当把服务部署为应用范围的会话方式时,客户端不需要传送额外的数据以使用同一个会话。部署服务为应用范围会话方式需要以如下方式修改services.xml:
<service name="foo" scope="application">
</service>
    服务客户端管理会话
    客户端管理会话需要做一些工作。如上所述,客户端如果想在SOAP会话和传输会话方式下保持在同一个会话中,需要传输一些会话相关的数据。对SOAP会话来说,需要复制所需的引用参数;对传输会话来说,需要访问传输以复制和发送cookies。
    为了简化开发,Axis2有内置的管理会话的功能,在客户端设置一个标志就可以了。这样,只要使用同一个客户端,就会往服务端发送会话相关的数据。所以,如果想保持在同一个会话内,最主要的一点就是使用同一个客户端调用服务。
    如果想保持在同一个会话内,可以用以下的方式创建服务客户端,并且重用客户端对象调用服务。
Options options = new Options();
options.setManageSession(true);
ServiceClient sender = new ServiceClient();
sender.setOptions(options);
    一旦按照如上方式创建了服务客户端,如果服务部署为SOAP会话方式,客户端会复制“serviceGroupId”并在第二次调用的时候上传服务端;如果服务器是发送的会话id,例如HTTP cookies,客户端就会复制服务上下文(在客户端)并在第二次调用的时候发送给服务器。
    总结
    无状态是Web服务的主要特性之一,但这对高级Web服务开发来说是一个限制。使用Web服务开发企业级的应用并不容易,除非有一个会话管理层。Axis2有4中会话类型以解决企业级服务开发的问题。
附英文原文:
Web services are in high demand and a large number of players have entered the web service arena. As a result of this, users are looking for more and more features, and they are trying to do everything by using Web services. By design, Web services are said to be stateless. There was no notion of managing sessions in the Web service world, but now this has changed and users cannot develop an advanced application without managing state. A good example would be banking applications where you log in into the system, withdraw money, and log, out.
If we try to map that into a Web service:
  • First, the user logs in into your account (invoking a login method)
  • The user withdraws money (invoking some operation on his account)
  • The user logs out (completing the transaction).
You easily can understand that the three operations stated above are interrelated, and the same user does all three invocations. So, it means that someone needs to keep track of the user, and another has to keep track of the user data throughout methods invocation. This implies the need for session management.
When it comes to advanced applications, we have to break the rules; otherwise, no one can implement real Web applications. As a result, even though Web services are stateless by nature, upi need to add a layer above it to provide session management.
The Stateless Nature of Axis2
One of the good design principles of Axis2 is that it keeps logic and states separately, so none of its components are needed to maintain session and they don't maintain sessions. In Axis2 handlers, transports and even AxisEngine are said to be stateless; therefore, there is no difference between having multiple instances or one instance of them.
As a best practice, a handler or transport should not keep any instance variable (if it is likely to be changed), because that breaks the stateless nature of Axis2. So, if the handler or transport wants to act in a stateful manner, the correct way is to store the state and Axis2 state hierarchy and use it whenever necessary, rather than keeping instance variable.
Types of sessions in Axis2
As mentioned above, an enterprise web service cannot sustain itself unless the session concept burns into Web service engines. In other words, it is wrong to say that each and every SOAP web service engine should maintain sessions because you can have services that do not require maintaining sessions. A good example could be a Google search service and a Google spell checker service.
Managing sessions directly causes an increase of the memory footprint and to slow down performance, but you need to have a compromise: whether or not you support the session and provide state full service development. Axis2 is meant to be an enterprise Web service engine, so it has to support session management.
When sessions are considered, there can be different types of sessions as well, and the lifetime of the session may vary from one to another. Some sessions last a few seconds whereas others last the system lifetime. Axis2 architecture has been designed to support four types of sessions. There are a few differences from one to another; hopefully you can develop any kind of Web service by using the following four types of session scope.
  • Request
  • SOAPSession
  • Application
  • Transport
Axis2 context hierarchy
It is useful to understand the types of contexts in Axis2 before discussing types of session in depth. As mentioned above, Axis2 keeps logic and states separately, so contextS are there to store the states. There are five types of contexts in Axis2:
  • ConfigurationContext:The runtime representation of THE whole system, to start Axis2 system you need to have A configuration context. The lifetime of configuration context will be the lifetime of the system, so if you store some state (a property) it will last forever (until system shutdown).
  • ServiceGroupContext:In Axis2, you can deploy multiple services together as a service group. At runtime, there will be one or more service group contexts (depending on the session scope of the group) to keep states of the group throughout the session.
  • ServiceContext:Will represent the runtime of one service; the context lifetime will be the lifetime of the session. There can be one or many service contexts in the system depending on the session scope of the corresponding service.
  • OperationContext:This context represents the lifetime of a MEP (Message Exchange Patterns). The lifetime of the operation context is usually less than the lifetime of the service context.
  • MessageContext:The lifetime of an incoming message is represented by the message context. If two handlers in a given execution chain want to share data, the best way is to store them in message context. One operation context may have many message contexts.
Irrespective of the session scope, when the session start up and when it finishes, Axis2 will notify the service implementation class, but you have to add two additional methods to your service implementation class.
public void init(ServiceContext serviceContext) {
}

public void destroy(ServiceContext serviceContext) {
}
In addition to that, whenever a service receives a request, it will notify by passing the corresponding OperationContext as an argument. So, if the service wants to access an incoming message's context or an incoming SOAPMessage, he can do that by just adding the following method to the service implementation class; this method will be called before the actual method is called.
public void setOperationContext(OperationContext operationContext) {
}
Request session scope
Request session scope is the default session in Axis2. When you deploy a service without knowing anything about session management, your service will be deployed in the requested session scope. The lifetime of this session is limited to the method invocation's lifetime, or the request processing time. So, when you deploy a service in request scope, you don't have a way to manage session; it is the same as though you don't have a session at all.
Once you deploy a service in request session scope for each and every invocation service, the implementation class will be created. Say you have deploy a service called "foo" in request scope; if a client invokes the service 10 times, there will be 10 instances of the service implementation class. If you want to specify the scope explicitly, you still can do that by adding a scope attribute to the service element in services.xml as follows:
<service name="foo" scope="request">
</service>
Even if you deploy a service in a request scope, there are many ways of managing sessions in Axis2. One way is to store the state in Axis2' global runtime (configuration context) and retrieve it whenever necessary.
SOAP Session Scope
SOAP session scope has a slightly longer lifetime than a request session, and deploying a service in a SOAP session is required to change services.xml. Managing a SOAP session requires both the client and service to aware of the sessions; in other words, the client has to send the session-related data if he wants to access the same session and the service has to validate the user by using session-related data.
To manage a SOAP session, a client has to send an addition reference parameter in the SOAP header; it is named the serviceGroupId parameter. The SOAP session provides a way to manage the session not only for a single service invocation but also for multiple services in a service group. As long as you are in the same SOAP session, you can manage service-related data in a service context; if you want to share data across other services in the group, you can use serviceGroupContext.
When you deploy a service in SOAP session and when a client tries to access the service in the first time, Axis2 will generate serviceGroupId and send that to the client as a reference parameter in wsa:ReplyTo, as shown below:
<wsa:ReplyTo>
  <wsa:Address>
  http://www.w3.org/2005/08/addressing/anonymous
  </wsa:Address>
  <wsa:ReferenceParameters>
    <axis2:ServiceGroupId xmlns:axis2=
      "http://ws.apache.org/namespaces/axis2">
        urn:uuid:65E9C56F702A398A8B11513011677354
    </axis2:ServiceGroupId>
  </wsa:ReferenceParameters>
</wsa:ReplyTo>
If the client wants to live in the same session, he has to copy that reference parameter and send it back to the server when he invokes the service the second time. As long as a client sends the valid serviceGroupId, he can use the same session, and the service can maintain the session-related data. Unlike a request session, a SOAP session has a default timeout period, so if the client does not touch the service for 30 seconds, the session will expire, and if the client sends the old serviceGroupId, he will get an AxisFault too.
Managing a SOAP session requires you to engage addressing modules on both the server side and client side. Deploying a service in a SOAP session requires you to change services.xml as follows:
<service name="foo" scope="soapsession">
</service>
Transport Session Scope
In the case of a Transport session, Axis2 uses transport-related session management techniques to manage session. As an example, in the case of HTTP, it uses HTTP cookies to manage the session. The lifetime of the session is controlled by the transport, not by Axis2; Axis2 stores the service context and serviceGroupContext in the transport session object so that the service can access those contexts as long as the session lives.
One of the key advantages of the Transport session over other sessions is that you can talk to multiple service groups within one transport session. In a SOAP session, you don't have a way to communicate between two service groups, but with the transport session you have that capability. In this case, the number of service instances created depends on the number of transport sessions created.
Deploying a service in a transport session requires you to change services.xml as follows:
<service name="foo" scope="transportsession">
</service>
If you are using Axis2 nightly builds or planning to use them the next version, deploying a service in a transport session requires additional changes to axis2.xml. That is mainly to improve the memory usage; otherwise, whether you deploy the service in a transport session or not Axis2 tries to create a session object at the transport level; with these changes, it will not create unnecessary objects. To manage the transport-level session, you need to set the manageTransportSession parameter value to true in axis2.xml:
<parameter name="manageTransportSession"
    locked="false">true</parameter>
Application Scope
Application scope has the longest lifetime compared to others; the lifetime of the application session is equal to the lifetime of the system. If you deploy a service in application scope, there will be only one instance of that service and obviously there will be only one service context for that service. In the Axis2 world, if you consider the memory footprint and if you don't want to manage the session, the good candidate is to deploy the service in application scope.
When you deploy a service in application scope, a client does not need to send any additional data to use the same session. To deploy a service in application scope, you need to change axis2.xml as shown below:
<service name="foo" scope="application">
</service>
Managing the session using the service client
Managing the session on the client side involves bit of a work. As mentioned above, both in a SOAP session and Transport session a client has to send the session-related data if he wants to live in the same session. Maybe he can do that for a SOAP session by coping with required reference parameters, but with a Transport session a user must get access to the transport to copy and send cookies.
To make life easier, Axis2 has the built-in capability of managing sessions in the client session by just setting a flag. Then, depending on the service side session, it will send the corresponding data as long as you use the same service client. So, the main requirement is to use the same service client to invoke the service if you want to live in the same session.
If you want to live in the same session, you can create service client as shown below and re-use the created serviceclient object to invoke the service.
Options options = new Options();
options.setManageSession(true);
ServiceClient sender = new ServiceClient();
sender.setOptions(options);
Once you create the service client as shown above, if the service deploys in a SOAP session it will copy the serviceGroupId and send that from the second invocation onwards. If the server sends the session id, such as HTTP cookies, it will copy that to the service context (on the client side) and send it back to the server when the client invokes the service for a second time.
Summary
The stateless nature is one of the main characteristics of Web services, but it is a limitation for advanced Web services developers. Developing an enterprise-level application using Web services is not easy unless you have a session management layer. Axis2 has four levels of sessions to address enterprises-level Web service development issues
原创粉丝点击