2016-11-10 79 views
6

我們在生產,現在相當長的一段一個問題...獲取響應代碼時文件描述符泄漏。 (CXF,SSL)

這是一個後續的:my other question但方式更多的細節,所以我認爲它張貼作爲一個新的問題是有道理的(如果沒有,我只是將這個信息添加到其他問題)。

這裏有雲:

因此,我們必須利用CXF使用的應用程序(IBM)的Java 6的WebLogic在AIX文件描述符泄漏,我們解決我們自己的也有JSB的Web服務,其路線走向我們的ws。

當使用File Leak Detector作爲代理啓動weblogic並轉儲getCurrentOpenFiles()並以編程方式過濾Listener.SocketRecord時,我們有2000多個打開的套接字;

這是java的套接字和文件描述符,淨插座正確關閉,通過時間(用netstat查看),但計劃的人保持開放(以及(和那些與

lsof -p $pid_of_managed_server 2> /dev/null|grep TCP|wc -l 

查看)最終導致太多的開放文件問題))。

這是JVM內部的打開文件描述符的一個堆的頭:

record socket to tst-cjcsr.just.fgov.be/10.239.7.19:443 by thread:[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)' on Thu Nov 10 10:25:56 CET 2016 
    at java.net.PlainSocketImpl.create(PlainSocketImpl.java:188) 
    at java.net.Socket.createImpl(Socket.java:411) 
    at java.net.Socket.connect(Socket.java:544) 
    at weblogic.net.http.HttpsClient.openWrappedSSLSocket(HttpsClient.java:565) 
    at weblogic.net.http.HttpsClient.openServer(HttpsClient.java:296) 
    at weblogic.net.http.HttpsClient.openServer(HttpsClient.java:373) 
    at weblogic.net.http.HttpsClient.New(HttpsClient.java:528) 
    at weblogic.net.http.HttpsURLConnection.connect(HttpsURLConnection.java:239) 
    at weblogic.net.http.HttpURLConnection.getInputStream(HttpURLConnection.java:409) 
    at weblogic.net.http.SOAPHttpsURLConnection.getInputStream(SOAPHttpsURLConnection.java:37) 
    at weblogic.net.http.HttpURLConnection.getResponseCode(HttpURLConnection.java:1038) 
    at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.getResponseCode(URLConnectionHTTPConduit.java:266) 
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.doProcessResponseCode(HTTPConduit.java:1550) 
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1579) 
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1520) 
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1317) 
    at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56) 
    at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:632) 
    at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62) 
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272) 
    at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:572) 
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:481) 
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:382) 
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:335) 
    at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96) 
    at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:136) 
    at com.sun.proxy.$Proxy380.requestCriminalRecord(Unknown Source) 
    at be.fgov.just.cjr.application.dossier.DossierBean$1.call(DossierBean.java:225) 

我可以想像,這是一個應用性的問題,因爲我找不到其他情況下與網上類似的缺陷。

有沒有人可以從這個堆棧更有意義?

例如:它令我奇怪的是,HTTPConduit.close()想創建連接...

還有一點: 問題不會隨着技術的非同一堆棧發生-https調用。 (這確實是有道理的,因爲堆棧跟蹤中提到的Http 小號客戶端)

CXF版本:2.7.18

CXF配置:

<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:jaxws="http://cxf.apache.org/jaxws" 
     xmlns:soap="http://cxf.apache.org/bindings/soap" 
     xmlns:cxf="http://cxf.apache.org/core" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xsi:schemaLocation=" 
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
      http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd 
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd 
      http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> 
    <import resource="classpath:META-INF/cxf/cxf.xml"/> 

    <context:property-placeholder location="file:${config.file.location}cjr-extract-${cjr.environment}.properties"/> 

    <jaxws:client id="CJCSCGService" 
        serviceClass="be.fgov.just.cjr.ws.extract.generated.CJCSCGService" 
        address="${ws.extract.wsdl.endpoint}"> 
     <jaxws:binding> 
      <soap:soapBinding version="1.2"/> 
     </jaxws:binding> 
    </jaxws:client> 

    <cxf:bus> 
     <cxf:outInterceptors> 
      <bean class="our.package.interceptors.SomeInterceptor" 
        id="webSecurityInterceptor"> 
       <constructor-arg> 
        <map> 
         <entry key="action" value="Timestamp Signature"/> 
         <entry key="user" value="${org.apache.ws.security.crypto.merlin.keystore.alias}"/> 
         <entry key="passwordCallbackRef"> 
          <ref bean="passwordCallBack"/> 
         </entry> 
         <!--entry key="signaturePropFile" value="properties/our.properties"/--> 
         <entry key="signaturePropFile" value="file:${location}/our.properties"/> 
         <entry key="signatureKeyIdentifier" value="DirectReference" /> 
        </map> 
       </constructor-arg> 
      </bean> 
     </cxf:outInterceptors> 
     <cxf:properties> 
      <entry key="signatureParts" 
        value="{Element}{http://www.w3.org/2003/05/soap-envelope}Body;{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp"/> 
     </cxf:properties> 
    </cxf:bus> 

    <bean id="passwordCallBack" class="our.package.authentication.PasswordCallbackHandler"> 
     <property name="password" value="${password}"/> 
     <property name="alias" value="${org.apache.ws.security.crypto.merlin.keystore.alias}"/> 
    </bean> 
</beans> 

的Java:

java version "1.6.0" 
Java(TM) SE Runtime Environment (build pap3260sr15fp1-20140110_01(SR15 FP1)) 
IBM J9 VM (build 2.4, JRE 1.6.0 IBM J9 2.4 AIX ppc-32 jvmap3260sr15- 
20131231_180656 (JIT enabled, AOT enabled) 
J9VM - 20131231_180656 
JIT - r9_20130920_46510ifx3 
GC - GA24_Java6_SR15_20131231_1152_B180656) 
JCL - 20140107_01 

的Weblogic 10.3 .6

感謝提示,指針,當然 - 如果可能的話),答案;-)

S.

EJP請求的代碼,那就是:

調用本身:

private CJCSCGService cjcscgService; 

private Callable<RequestCriminalRecordResponse> callService(final RequestCriminalRecordRequest request) { 
    return new Callable<RequestCriminalRecordResponse>() { 
     @Override 
     public RequestCriminalRecordResponse call() throws Exception { 
      try { 
       return cjcscgService.requestCriminalRecord(request); // this is line 225. 
      } catch (Exception e) { 
       facesMessages.error("technicalError"); 
       log.error("Encountered technical error", e); 
       return null; 
      } 
     } 
    }; 
} 

生成的Web服務:

package be.fgov.just.cjr.ws.extract.generated; 

import javax.jws.WebMethod; 
import javax.jws.WebParam; 
import javax.jws.WebResult; 
import javax.jws.WebService; 
import javax.jws.soap.SOAPBinding; 
import javax.xml.bind.annotation.XmlSeeAlso; 


/** 
* This class was generated by the JAX-WS RI. 
* JAX-WS RI 2.1.7-b01- 
* Generated source version: 2.1 
* 
*/ 
@WebService(name = "CJCSCGService", targetNamespace = "http://secret/service-v1.0-rc2") 
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE) 
@XmlSeeAlso({ 
    ObjectFactory.class 
}) 
public interface CJCSCGService { 
    /** 
    * 
    * @param requestCriminalRecordRequest 
    * @return 
    *  returns be.fgov.just.cjr.ws.extract.generated.RequestCriminalRecordResponse 
    */ 
    @WebMethod(action = "http://secret/service/RequestCriminalRecord") 
    @WebResult(name = "requestCriminalRecordResponse", targetNamespace = "http://secret/service-v1.0-rc2", partName = "requestCriminalRecordResponse") 
    public RequestCriminalRecordResponse requestCriminalRecord(
     @WebParam(name = "requestCriminalRecordRequest", targetNamespace = "http://secret/service-v1.0-rc2", partName = "requestCriminalRecordRequest") 
     RequestCriminalRecordRequest requestCriminalRecordRequest); 
} 

有:

<http-conf:conduit name="*.http-conduit"> 
    <http-conf:client Connection="Close" /> 
</http-conf:conduit> 

的連接( os級別)關閉;但我們仍然存在泄漏(上述行爲)。

有:

<http-conf:conduit name="*.http-conduit"> 
    <http-conf:client Connection="Keep-Alive" /> 
</http-conf:conduit> 

兩個連接(操作系統級別)作爲文件描述符繼續上漲...

(附加信息:在操作系統級別的連接下去(超時後,我猜測)但文件描述符保持打開...)

+0

@EJP問題在於配置CXF。這就是爲什麼沒有代碼。我不能去粘貼CXF的代碼:我們只是不知道內部發生了什麼。你想要調用的代碼?好吧,這不是問題,幾分鐘後就會完成,但它不會給你任何提示。 –

+0

@EJP:所有打開的文件描述符似乎卡在java.net.PlainSocketImpl.create(PlainSocketImpl.java:188);我們可以在OpenJdk中搜索這些代碼,但不能在IBM中搜索(這會導致問題);堆棧跟蹤使用了很多weblogic內部代碼,我們稱之爲cxf,但我們的代碼僅限於Olivier提供的代碼(使用我提供的配置) – Bamboomy

+0

您是否嘗試過超時?如果你沒有檢查,但我發現這個問題http://stackoverflow.com/questions/5656458/java-net-socketexception-too-many-open-files/37605213#37605213 – HRgiger

回答

1

從我的角度來看,問題與cxf配置有關,也許weblogic + cxf的相互作用也是一個問題,因爲它是管理連接的cxf組件(請參閱堆棧跟蹤)。所以我建議嘗試使用不同的保持活動設置(如何設置保持活動描述here)。似乎這並沒有幫助打敗文件描述符。

UPDATE:

更多地考慮您的問題後:

at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.getResponseCode(URLConnectionHTTPConduit.java:266) 
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.doProcessResponseCode(HTTPConduit.java:1550) 
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1579) 
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1520) 
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1317) 

好像關閉HTTP連接,當CXF試圖得到一些響應代碼回,並創建一個套接字,併爲這些插槽只是等待永遠不會無限期地產生泄漏的響應。整個流程在簡化客戶端工作流程部分中描述爲here。那麼,接下來的問題是,tst-cjcsr.just.fgov.be有沒有回覆?而且,我的下一個建議是按照上述link中的描述爲http-conf:client配置ReceiveTimeout

+0

這與HRgiger的評論有何不同? Bamboomy已經聲明連接已關閉。它只是保持打開的文件描述符。 –

+1

從我的角度來看,這個問題與cxf配置有關,或許weblogic + cxf的相互作用也是一個問題。通過將keep-alive設置爲false,我希望cxf將顯式關閉套接字,因此文件描述符將被釋放。而且Bamboomy表示,如果我理解正確,程序打開的套接字將保持打開狀態 – borowis

+1

對我來說,我會給它一個靈感並讓你知道,明天早上會有這個信息;謝謝你的建議(以及開箱即用的想法)) – Bamboomy