配置 JAX-RPC Web Service 客户机高速缓存

JAX-RPC Web Service 客户机高速缓存作为应用程序服务器上的 Java™ API for XML-Based Remote Procedure Call (JAX-RPC) 处理程序提供。 JAX-RPC Web Service 客户机高速缓存是动态高速缓存服务的组成部分,用于通过对远程 Web Service 的响应进行高速缓存来提高 Web Service 客户机的性能。 如果配置 JAX-RPC Web Service 客户机高速缓存,那么可以将来自远程 Web Service 的响应高速缓存达到指定的时间量,从而提高应用程序服务器的性能。

准备工作

缺省情况下,动态高速缓存服务处于启用状态。 您可以使用管理控制台来配置缺省高速缓存实例。 请参阅 使用动态高速缓存服务 以获取更多信息。 在尝试配置 Web Service 客户机高速缓存之前,了解如何创建基本高速缓存策略。 请参阅 使用 cachespec.xml 文件配置可高速缓存对象 以获取更多信息。

有关此任务

启用 Web Service 客户机高速缓存是一个选项,可让您通过使用动态高速缓存服务,将来自远程 Web Service 的响应保存达到指定的时间量,从而提高系统的性能。 对于 WebSphere Application Server Version 6.1,通过仅启用动态高速缓存服务来启用 Web Service 高速缓存。 通过启用动态高速缓存服务和 servlet 高速缓存来启用 Web Service 高速缓存。 当响应从远程 Web Service 返回之后,将该响应保存在应用程序服务器上的客户机高速缓存中。 然后,在指定时段内从高速缓存响应对同一远程 Web Service 发出的任何相同的请求进行响应。 因为目标 Web Service 可能在您的企业网络之外,并且未察觉到客户机高速缓存,所以 Web Service 客户机高速缓存主要依赖于基于时间的无效。 因此,您可以指定高速缓存中的时间量以及在您的客户机应用程序中构建高速缓存的高速缓存条目标识的规则。

Web Service 客户机高速缓存作为 Java API for XML-Based Remote Procedure Call (JAX-RPC) 处理程序在应用程序服务器上提供。 此 JAX-RPC 高速缓存处理程序拦截了从应用程序客户机流经它的 SOAP 请求。 然后,它识别基于目标 Web Service 的高速缓存策略。 在找到策略后,将逐一评估所有高速缓存标识规则,直到检测到有效的规则。

过程

  1. 为远程服务定位 Web Service 描述语言 (WSDL) 文件。 WSDL 文件的一些部分包含您将用来编写高速缓存策略的信息。
    有关 WSDL 文件的更多信息,请参阅 WSDL
    以下是 WSDL 文件的一些部分的示例,该文件包含用于演示的值。
    <definitions targetNamespace="http://TradeSample.com/"
    		xmlns:tns="http://TradeSample.com/"
    		xmlns="http://schemas.xmlsoap.org/wsdl/"
    		xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    		xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    	<message name="getQuoteRequest">
    		<part name="symbol" type="xsd:string"/>
    	</message>
    .....
    .....
    <binding name="SoapBinding" type="tns:GetQuote">
    	<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
    		<operation name="getQuote">
    			<soap:operation soapAction=""/>
    			<input name="getQuoteRequest">
    				<soap:body namespace="http://TradeSample.com/" 
    				use="encoded"
    			encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    			</input>
    			......
    			</operation>
    </binding>
    <service name="GetQuoteService">
    	<port binding="tns:SoapBinding" name="SoapPort">
    		<soap:address location="http://TradeSample.com:9080/service/getquote"/>
    	</port>
    </service>
    </definitions>
    突出显示的文本表明编写高速缓存策略时使用的值。
  2. 选择您计划为 Web Service 客户机高速缓存生成高速缓存标识的方式。
    您可以通过使用四个选项中的一个选项来构建高速缓存标识规则:
    • 通过计算 SOAPEnvelope 散列
    • 通过使用 SOAPHeader 项
    • 通过使用操作和部件参数
    • 通过使用定制 Java 代码从输入 SOAP 消息内容构建高速缓存标识
    如果您能包含构建高速缓存键作为 SOAP 标题的一部分的信息,那么使用 SOAPHeader 项是最佳选择。 可以很容易创建此方法来阅读高速缓存键,并且无需解析 SOAP 主体即能构建它。 使用定制 Java 代码根据 SOAP 消息生成特定高速缓存标识。 如果不能包括头信息,那么可以计算 SOAPEnvelope 的散列以提高性能或对用户友好的高速缓存键的 SOAP 主体进行语法分析。
  3. 开发高速缓存策略。

    所有的 Web Service 客户机高速缓存策略必须有 JAXRPCClient。 在每个高速缓存条目中的 name 元素是在 WSDL 文件中定义的目标端点位置。 您可以在 WSDL 文件中找到此地址,方法是查找<soap:address location=".."/>port 元素中的标记。 在此样本的 WSDL 文件中,地址为http://TradeSample.com:9080/service/getquote. 使用下列其中一个选项来开发其余高速缓存策略:

    • 计算 SOAPEnvelope 的散列以识别请求
      <cache>
      	<cache-entry>
      		<class>JAXRPCClient</class>
      		<name>http://TradeSample.com:9080/service/getquote</name>
      		<cache-id>
      			<component id="hash" type="SOAPEnvelope"/>
      			<timeout>60</timeout>
      		</cache-id>
      	</cache-entry>
      </cache>

      标记组件属性以创建基于 SOAPEnvelope 的散列计算的高速缓存标识。 此样本的高速缓存标识生成为http://TradeSample.com:9080/service/getquote:Hash=xxxHashSoapEnvelope.

    • 使用 SoapHeader 以识别请求
      <cache>
      	<cache-entry>
      		<class>JAXRPCClient</class>
      		<name>http://TradeSample.com:9080/service/getquote</name>
      		<cache-id>
      			<component id="urn:stock:getQuote" type="SOAPHeaderEntry"/>
      		</cache-id>
      	</cache-entry>
      </cache>

      通过使用 SOAP 标题中特殊的信息构建该高速缓存标识以识别高速缓存中条目的请求。 将 type 指定为SOAPHeaderEntryid 作为operation名称位于 WSDL 文件的 binding 元素中。 此样本的高速缓存标识生成为http://TradeSample.com:9080/service/getquote:urn:stock:getQuote=IBM.

      通过使用 SOAP 标题,客户机生成的 SOAP 请求的示例:

      请注意, soapenv: actor 属性必须包含com.ibm.websphere.cache.
      POST /wsgwsoap1/soaprpcrouther HTTP/1.1
      SOAPAction: ""
      Context-Type: text/xml; charset=utf-8
      User-Agent: Java/1.4.1
      Host: localhost
      Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
      Connection: keep-alive
      Content-Length: 645
      
      <?xml version="1.0" encoding="UTF-8"?>
      <soapenv:Envelope 
      xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
      	xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
      	xmlns:xsd="http://www.w3.org/2001/XMLSchema"
      	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <soapenv:Header>
      	<getQuote soapenv:actor="com.ibm.websphere.cache" xmlns="urn:stock">IBM</getQuote>
      </soapenv:Header>
      <soapenv:Body
      soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding">
      	<getQuote xmlns="urn:ibmwsgw#GetQuoteSample">
      		<symbol xsi:type="xsd:string">IBM</symbol>
      	</getQuote>
      </soapenv:Body>
      </soapenv:Envelope>
    • 使用操作和部件以识别请求
      <cache>
      	<cache-entry>
      		<class>JAXRPCClient</class>
      		<name>http://TradeSample.com:9080/service/getquote</name>
      		<cache-id>
      			<component id="" type="operation">
      				<value>http://TradeSample.com/:getQuote</value>
      			</component>
      			<component id="symbol" type="part"/>
      		</cache-id>
      	</cache-entry>
      </cache>

      此示例使用操作和请求参数。 该operation可以是位于 binding 元素中的 WSDL 文件中的方法名称,也可以是文档/字面值调用 (DII) 中的方法名称。 如果定义了操作的名称空间,那么值将格式化为namespaceOfOperation:nameOfOperation.part类型可以在 WSDL 文件的 message 元素中定义为请求参数或 DII 调用的请求参数。 ITSid属性是部件或参数名称,并且value是部件或参数值。 使用操作和请求参数生成的高速缓存标识为http://TradeSample.com:9080/service/getquote:operation=http://TradeSample.com/:getQuote/symbol=IBM.

      通过使用操作和部件,客户机生成的 SOAP 请求的示例:

      POST /wsgwsoap1/soaprpcrouter HTTP/1.1
      SOAPAction:""
      Content-Type: text/xml/charset=utf-8
      User-Agent: Java/1.4.1
      Host: localhost
      Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
      Connection: keep-alive
      Current-Length: 645
      
      <?xml version="1.0" encoding="UTF-8"?>
      <soapenv:Envelope
      xmlns: soapenv="http://schemas.xmlsoap.org/soap/envelope/"
      	xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
      	xmlns:xsd="http://www.w3.org/2001/XMLSchema"
      	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <soapenv:Body
      	soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
      	<getQuote xmlns="urn:ibmwsgw#GetQuoteSample">
      		<symbol xsi:type="xsd:string">IBM</symbol>
      	</getQuote>
      </soapenv:Body>
      </soapenv:Envelope>
    • 使用定制 Java 代码从输入 SOAP 消息内容构建高速缓存标识

      如果使用定制 Java 代码来构建高速缓存标识,请创建用于实现 com.ibm.websphere.cache.webservices.IdGenerator 包中定义的 IdGenerator 接口的标识生成器 Java 类,并使用 idgenerator 标记添加对您在 cachespec.xml 文件中创建的类的引用。

      您也可以通过使用 metadatagenerator 标记实现 com.ibm.websphere.cache.webservices.MetaDataGenerator 包以将高速缓存元数据(如超时、优先级和依赖项标识)指定到高速缓存条目中。

      实现 com.ibm.websphere.cache.webservices.InvalidationGenerator 接口,以及使用 cachespec.xml 文件中的 invalidationgenerator 标记以生成高速缓存标识并使高速缓存中的条目失效。 无效生成器生成的标识可以是高速缓存标识或依赖项标识。

      例如,如果您开发名为 SampleIdGeneratorImpl 的标识生成器类、名为 SampleMetaDataGeneratorImpl 的元数据生成器类和名为 SampleInvalidationGeneratorImpl 的无效生成器类,那么 cachespec.xml 文件可包含以下内容:

      <cache-entry>
      	<class>JAXRPCClient</class>
      	<name>http://TradeSample.com:9080/service/getquote</name>
      	<cache-id>
      		<idgenerator>com.mycompany.SampleIdGeneratorImpl</idgenerator>
      		<metadatagenerator>
             com.mycompany.SampleMetaDataAndInvalidationGeneratorImpl
          </metadatagenerator>
      		<timeout>60</timeout>
      	</cache-id>
      	<invalidation>http://TradeSample.com:9080/service/GetQuote
      		<invalidationgenerator>
             com.mycompany.SampleMetaDataAndInvalidationGeneratorImpl
          </invalidationgenerator>
      	</invalidation>
      </cache-entry>
      SampleIdGeneratorImpl 类是一个自定义 Java 类,它实现了com.websphere.cache.webservices.IdGenerator接口。 SampleIdGeneratorImpl 类包含 getID 方法:
      String getId(javax.xml.rpc.handler.soap.SOAPMessageContext messageContext)

      以下是 SampleIdGeneratorImpl.java 类的示例。

      public class SampleIdGeneratorImpl implements IdGenerator {
      //The SampleIdGenerator class builds cache keys using SOAP header entries
          public String getId(javax.xml.rpc.handler.soap.SOAPMessageContext 
      			messageContext) {
      			....
      			// retrieve SOAP header entries from SOAPMessage
      			SOAPHeader sh = soapEnvelope.getHeader();
      	   	if (sh != null) {
      				Iterator it = sh.examineHeaderElements("com.mycompany.actor");
      				while (it.hasNext()) {
      		   		SOAPHeaderElement element =
      			              (SOAPHeaderElement)it.next();
      					Name name = element.getElementName();
      					String headerEntryName = name.getLocalName();
      					if (headerEntryName.equals("getQuote")){
      						String sNamespace = element.getNamespaceURI("");
      						if (sNamespace != null && !sNamespace.equals("")) {
      		    				headerEntryName = sNamespace + ":" + headerEntryName;
      							String quotes = element.getValue();
      						}
      						...
      						...
      						// create a method "parseAndSort" to parse and sort quotes
      						// By parsing and sorting quotes, you avoid duplicate cache 
      						// entries.
      						// quotes e.g. IBM,CSCO,MSFT,INTC
      						// to return a cache key "urn:stock:getQuote=CSCO,IBM,INTC,MSFT"
      						String sortQuotes = parseAndSort(quotes); 
      						cacheKey = headerEntryName + "=" + sortQuotes;
      	   			}
      				}
      		return cacheKey;
      		}
      	}
      

      此样本的高速缓存标识生成为http://TradeSample.com:9080/service/getquote:urn:stock:symbol=CSCO,IBM,INTC,MSFT.

      SampleMetaDataAndInvalidationGeneratorImpl 类是一个自定义 Java 类,它实现了com.websphere.cache.webservices.MetaDataGenerator接口和com.websphere.cache.webservices.InvalidationGenerator接口。 SampleMetaDataAndInvalidationGeneratorImpl 类包含 setMetaData 方法和 getInvalidationIds 方法。 您也可以设置两个更小的类来代替这个大的类。 例如,为元数据生成器创建一个类,以及为无效生成器创建一个不同的类。 以下是 setMetaData 方法和 getInvalidationIds 方法的方法原型:

      void setMetaData (javax.xml.rpc.handler.soap.SOAPMessageContext messageContext, 
      	com.ibm.websphere.cache.webservices.JAXRPCEntryInfo entryInfo)
      String[] getInvalidationIds (javax.xml.rpc.handler.soap.SOAPMessageContext messageContext)

      SampleMetaDataAndInvalidationGeneratorImpl.java 类的示例如下:

      public class SampleMetaDataAndInvalidationGeneratorImpl implements 
        MetaDataGenerator, InvalidationGenerator {
          //assigns time limit, and priority metadata
          public void setMetadata(javax.xml.rpc.handler.soap.SOAPMessageContext messageContext, 
        com.ibm.websphere.cache.webservices.JAXRPCEntryInfo entryInfo) {
      			....
                      
      		// retrieve SOAP header entries from SOAPMessage
      			SOAPHeader sh = soapEnvelope.getHeader();
      	   	if (sh != null) {
      				Iterator it = sh.examineHeaderElements("com.mycompany.actor");
      				while (it.hasNext()) {
      		   		SOAPHeaderElement element =
      			              (SOAPHeaderElement)it.next();
      					Name name = element.getElementName();
      					String headerEntryName = name.getLocalName();
      	                                if (headerEntryName.equals("metadata")) {
      					// retrieve each metadata element and set metadata 
      	                entryInfo.setTimeLimit(timeLimit);
                      entryInfo.setPriority(priority);
                  }
              }
          }
      
          //builds invalidation ids using SOAP header. 
          public String[] getInvalidationIds(javax.xml.rpc.handler.soap.SOAPMessageContext 
            messageContext) {			....
      			// retrieve SOAP header entries from SOAPMessage
                      String[] invalidationIds = new String[1];
      			SOAPHeader sh = soapEnvelope.getHeader();
      	   	if (sh != null) {
      				Iterator it = sh.examineHeaderElements("com.mycompany.actor");
      				while (it.hasNext()) {
      		   		SOAPHeaderElement element =
      			              (SOAPHeaderElement)it.next();
      					Name name = element.getElementName();
      					String headerEntryName = name.getLocalName();
      	                                if (headerEntryName.equals("invalidation")) {
      					String sNamespace = element.getNamespaceURI("");
      					if (sNamespace != null && !sNamespace.equals("")) {
      		    			headerEntryName = sNamespace + ":symbol";
      						String quotes = element.getValue();
      					}
      					...
      					...
      					// create a method "parseAndSort" to parse and sort quotes
      					// By parsing and sorting quotes, you avoid duplicate cache 
      					// entries.
      					// quotes e.g. SUNW,NT
      					// to return a cache key "urn:stock:symbol=NT,SUNW"
      					String sortQuotes = parseAndSort(quotes); 
      					invalidationIds[0] = headerEntryName + "=" sortQuotes;
                   }
      	   	}
      		return invalidationIds;
          }
      }
      
      
      此样本的无效标识生成为:
      http://TradeSample.com:9080/service/getquote:urn:stock:symbol=NT,SUNW

      下面是客户机在使用定制 Java 代码时生成的 SOAP 请求的示例:

      POST /wsgwsoap1/soaprpcrouter HTTP/1.1
      SOAPAction: ""
      Context-type: text/xml, charset=utf-8
      User-Agent: Java/1.4.1
      Host: localhost
      Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
      Connection: keep-alive
      Content-Length:645
      
      <?xml version="1.0" encoding="UTF-8"?>
      <soapenv:Envelope
      xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
      		xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
      		xmlns:xsd="http://www.w3.org/2001/XMLSchema"
      		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <soapenv:Header>
      	<getQuote soapenv:actor="com.mycompany.actor"
      			xmlns="urn:stock">IBM,CSCO,MSFT,INTC</getQuote>
      		<metaData soapenv:actor="com.mycompany.actor" xmlns="urn:stock">
      			<priority>10</priority>
      			<timeLimit>30000</timeLimit>
      		</metaData>
      		<invalidation soapenv:actor="com.mycompany.actor" 
      			xmlns="urn:stock">SUNW, NT</invalidation>
      </soapenv:Header>
      <soapenv:Body
      soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding">
      <getQuote xmlns="urn:ibmwsgw#GetQuoteSample">
      	<symbol xsi:type="xsd:string">IBM,CSCO,MSFT,INTC</symbol>
      </getQuote>
      </soapenv:Body>
      </soapenv:Envelope>
  4. 将高速缓存策略保存到适当的目录中。
    • 如果您正在 SOAP 通道 1 上使用 Web Service 网关,那么目录为:<app_server_root>\installedApps\wsgwsoap1.servername.nodename.ear/wsgwsoap.war/WEB-INF
    • 如果您正在应用程序中使用简单的 JAX-RPC 客户机以调用远程 Web Service,那么在 JAX-RPC 应用程序的 Web 模块 WEB-INF 中保存高速缓存策略。

结果

您可以使用动态高速缓存监视器来监视 Web Service 客户机高速缓存策略的结果。 请参阅 显示高速缓存信息 以获取更多信息。