Java Web服务性能优化实践(3)

来源:互联网 发布:软件乱码 编辑:程序博客网 时间:2024/06/05 11:11

本文介绍如何提升 Java Web 服务性能,主要介绍了三种方法:一是采用 Web 服务的异步调用,二是引入 Web 服务批处理模式,三是压缩 SOAP 消息。重点介绍在编程过程中如何使用异步 Web 服务以及异步调用和同步调用的差异点。本文还示范了如何在项目中使用以上三种方法,以及各种方法所适合的应用场景。

压缩SOAP

当 Web Service SOAP 消息体比较大的时候,我们可以通过压缩 soap 来提高网络传输性能。通过 GZIP 压缩 SOAP 消息,得到二进制数据,然后把二进制数据作为附件传输。以前常规方法是把二进制数据 Base64 编码,但是 Base64 编码后的大小是二进制数据的 1.33 倍。辛苦压缩的,被 Base64 给抵消差不多了。是否可以直接传输二进制数据呢? JAX-WS 的 MTOM 是可以的,通过 HTTP 的 MIME 规范, SOAP message 可以字符,二进制混合。我们在 client 和 server 端各注册一个 handler 来处理压缩和解压。 由于压缩后的 SOAP 消息附件与消息体中的部分不是基于 MTOM 自动关联的,需要单独处理附件。在生成 client 端和 server 端代码的时候需要 enable MTOM。 Handler 具体代码在本文代码附件中, test.TestClientHanlder, test.TestServerHanlder。 写好了 handler 了之后还要为 service 注册 handler。

客户端 handler 样例代码如下:

客户端代码

  1. public boolean handleMessage(MessageContext arg0) {  
  2.         SOAPMessageContext ct = (SOAPMessageContext) arg0;  
  3.         boolean isRequestFlag = (Boolean) arg0  
  4.                 .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);  
  5.         SOAPMessage msg = ct.getMessage();  
  6.         if (isRequestFlag) {  
  7.             try {  
  8.                 SOAPBody body = msg.getSOAPBody();  
  9.                 Node port = body.getChildNodes().item(0);  
  10.                 String portContent = port.toString();  
  11.                 NodeList list = port.getChildNodes();  
  12.                 for (int i = 0; i < list.getLength(); i++) {  
  13.                     port.removeChild(list.item(i));  
  14.                 }  
  15.                 ByteArrayOutputStream outArr = new ByteArrayOutputStream();  
  16.                 GZIPOutputStream zip = new GZIPOutputStream(outArr);  
  17.                 zip.write(portContent.getBytes());  
  18.                 zip.flush();  
  19.                 zip.close();  
  20.                 byte[] arr = outArr.toByteArray();  
  21.                 TestDataSource ds = new TestDataSource(arr);  
  22.                 AttachmentPart attPart = msg.createAttachmentPart();  
  23.                 attPart.setDataHandler(new DataHandler(ds));  
  24.                 msg.addAttachmentPart(attPart);  
  25.             } catch (SOAPException e) {  
  26.                 e.printStackTrace();  
  27.             } catch (IOException e) {  
  28.                 e.printStackTrace();  
  29.             }  
  30.         }  
  31.         return true;  
  32.     } 

Web 服务端 handler 样例代码如下:

服务端代码

  1. public boolean handleMessage(MessageContext arg0) {  
  2.         SOAPMessageContext ct = (SOAPMessageContext) arg0;  
  3.         boolean isRequestFlag = (Boolean) arg0  
  4.                 .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);  
  5.         SOAPMessage msg = ct.getMessage();  
  6.         if (!isRequestFlag) {  
  7.             try {  
  8.                 Object obj = ct.get("Attachments");  
  9.                 Attachments atts = (Attachments) obj;  
  10.                 List list = atts.getContentIDList();  
  11.                 for (int i = 1; i < list.size(); i++) {  
  12.                     String id = (String) list.get(i);  
  13.                     DataHandler d = atts.getDataHandler(id);  
  14.                     InputStream in = d.getInputStream();  
  15.                     ByteArrayOutputStream out = new ByteArrayOutputStream();  
  16.                     GZIPInputStream zip = new GZIPInputStream(in);  
  17.                     byte[] arr = new byte[1024];  
  18.                     int n = 0;  
  19.                     while ((n = zip.read(arr)) > 0) {  
  20.                         out.write(arr, 0, n);  
  21.                     }  
  22.                     Document doc = DocumentBuilderFactory.newInstance()  
  23.                             .newDocumentBuilder()  
  24.                             .parse(new ByteArrayInputStream(out.toByteArray()));  
  25.                     SOAPBody body = msg.getSOAPBody();  
  26.                     Node port = body.getChildNodes().item(0);  
  27.                     port.appendChild(doc.getFirstChild().getFirstChild());  
  28.                 }  
  29.             } catch (SOAPException e) {  
  30.                 e.printStackTrace();  
  31.             } catch (IOException e) {  
  32.                 e.printStackTrace();  
  33.             } catch (SAXException e) {  
  34.                 e.printStackTrace();  
  35.             } catch (ParserConfigurationException e) {  
  36.                 e.printStackTrace();  
  37.             }  
  38.         }  
  39.         return true;  
  40.     } 

在 web.xml 中 service-ref 部分添加 handler. Server 端 handler 也是同样添加。

配置代码

  1. <handler-chains>  
  2.             <handler-chain>  
  3.                 <handler>  
  4.                     <handler-name>TestClientHandler</handler-name>  
  5.                     <handler-class>test.TestClientHandler  
  6.  </handler-class>  
  7.                 </handler>  
  8.             </handler-chain>  
  9.         </handler-chains>