2012-11-07 4 views
15

테스트를 JERSEY Client + HTTPS과 함께 사용하여 secure web serviceJetty에서 실행되는지 테스트하고 있습니다. 내 전화 wr.get(ClientResponse.class) 중 하나는 블록 9-10 requests마다 10 초 동안 정지합니다. 코드 Apache client은 몇 밀리 초 안에 실행됩니다. Jetty to HTTP 모드로 전환하면 문제가 사라집니다.저지 클라이언트 HTTPS 성능 문제

내가 Jersey bundle & client 1.14 and Jetty 6.1.26



을 사용하고있는 아파치 클라이언트는

@Test 
public void testApacheClient() throws Exception 
{ 
    HttpClient client = new HttpClient(); 
    ProtocolSocketFactory socketFactory = new EasySSLProtocolSocketFactory(); 
    Protocol https = new Protocol("https", socketFactory, 443); 
    Protocol.registerProtocol("https", https); 

    //Finishes in < 1 second 
    for (int i = 0; i < 30; i++) 
    { 
    GetMethod getMethod = new GetMethod("https://localhost:8443/home"); 
    client.executeMethod(getMethod); 
    String entity = getMethod.getResponseBodyAsString(); 
    getMethod.releaseConnection(); 
    } 
} 



저지 클라이언트가 ClientResponse에서 엔티티를 보인다 가져

@Test 
public void testJerseyClient() throws Exception 

    HostnameVerifier hv = getHostnameVerifier(); 
    ClientConfig config = new DefaultClientConfig(); 
    SSLContext ctx = getSslContext(); 
    config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, 
     new HTTPSProperties(hv, ctx)); 

    Client jerseyClient = Client.create(config); 

    //Finishes in < 1 second 
    for (int i = 0; i < 30; i++) 
    { 
    WebResource wr = jerseyClient.resource("https://www.google.com"); 
    ClientResponse cr = wr.get(ClientResponse.class); 
    String entity = cr.getEntity(String.class); 
    cr.close(); 
    } 

    /* Pauses for 10 seconds after the 10th request, and subsequently after every 9th request. 
    Debugging shows waiting at line 'ClientResponse cr = ...' 
    */ 
    for (int i = 0; i < 30; i++) 
    { 
    WebResource wr = jerseyClient.resource("https://localhost:8443/home"); 
    ClientResponse cr = wr.get(ClientResponse.class); //10 second pause after requests 9, 18, 27 
    String entity = cr.getEntity(String.class); //This is triggering the problem 
    cr.close(); 
    } 

    //Finishes in < 1 second 
    for (int i = 0; i < 30; i++) 
    { 
    WebResource wr = jerseyClient.resource("https://localhost:8443/home"); 
    ClientResponse cr = wr.get(ClientResponse.class); 
    cr.close(); 
    } 
} 

중단 작동 문제가 발생하지만 HTTPS 모드이고 내 웹 서버 (google, facebook, etc이 아님)에 대해 실행 중입니다. 을 Jetty에 실행했는데이 문제가 발생합니다. 나는 또한 subnet에있는 여러 컴퓨터에서 웹 서버를 실행했으며 여러 대의 컴퓨터에서 테스트를 실시했습니다.



저지 HTTPS 클래스

private HostnameVerifier getHostnameVerifier() { 
    HostnameVerifier hv = new HostnameVerifier() { 
    public boolean verify(String arg0, SSLSession arg1) { return true; } 
    }; 
    return hv; 
} 

private SSLContext getSslContext() throws Exception {  
    private final SSLContext sslContext = SSLContext.getInstance("SSL"); 
    sslContext.init(null, new TrustManager[] { new X509TrustManager() { 
     public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } 
     public void checkClientTrusted(X509Certificate[] certs, String authType) {} 
     public void checkServerTrusted(X509Certificate[] certs, String authType) {} 
     } 
    }, new SecureRandom() 
); 
    return sslContext; 
} 



부두 SSL 커넥터

. SelectChannelConnector 및 HTTP를 사용하는 단위 테스트를 사용하면 문제가 사라집니다.

<Call name="addConnector"> 
    <Arg> 
    <New class="org.mortbay.jetty.security.SslSocketConnector"> 
     <Set name="allowRenegotiate">true</Set> 
     <Set name="Port">8443</Set> 
     <Set name="reuseAddress">true</Set> 
     <Set name="Host">mgmt-int</Set> 
     <Set name="maxIdleTime">30000</Set> 
     <Set name="handshakeTimeout">2000</Set> 
     <Set name="keystore"><SystemProperty name="jetty.home" default="/usr/app/web-app"/>/conf/keystore.jetty</Set> 
     <Set name="password">OBF:1vaaaaaaaaaaaaaaaaaaaa111111111v</Set> 
     <Set name="keyPassword">OBF:1vaaaaaaaaaaaaaaaaaaaa111111111v</Set> 
    </New> 
    </Arg> 
</Call> 
+0

귀하 또는 handshakeTimeout가 너무입니다 낮은 2000ms. 최소 10-15 초로 변경하십시오. – EJP

+0

handshakeTimeout을 15000ms로 늘렸고 문제가 여전히 발생합니다. – Karl

+0

예를 들어 스레드 덤프를 만들 수 있습니까? 클라이언트에서'kill -3 pid '를 사용하여이 상황이 발생하는 곳을 확인합니다. –

답변

1

실행중인 OS는 무엇입니까?

그냥 짐작할 수 있지만 느린 /dev/random 구현 (SecureRandom 통해)과 관련 될 수 있습니다. 여기

관련 토론 :

How to solve performance problem with Java SecureRandom?

나는 항상 웹 응용 프로그램에 JVM 매개 변수를 제어 할 수 있기 때문에, 나는 해결 방법으로 이것을 사용하고있다 :

static { 
    System.setProperty("java.security.egd", "file:///dev/urandom"); 
} 

돈 ' 그게 엄격히 권장되는 말인지는 모르지만 (그러나 그것은 나를 위해 문제를 해결합니다).

+0

저는 Linux 3.0.0-12-generic 및 2.6.32.49에서 Jetty를 실행했습니다.Jetty가로드 된 Java 클래스에 정적 블록을 추가했는데 도움이되지 않았습니다. Apache HTTPS 클라이언트는 Jetty 서버와 잘 작동하며 Jersey Client는 https google과 잘 작동합니다. 저지 클라이언트가 제티 서버에 대해 실행될 때만 문제가 해결됩니다. – Karl

0

약간의 TrustManager 구현을 수정 시도 : 당신의 getSSLContext의 말에 HttpsURLConnection.setDefaultSocketFactory를 호출하는 것을 잊지 마세요,

TrustManager[] trustAllCerts = new TrustManager[] { 
     new X509TrustManager() { 
      public X509Certificate[] getAcceptedIssuers() { 
       return null; 
      } 

      public void checkClientTrusted(X509Certificate[] certs, String authType) { 
       // Trust always 
      } 

      public void checkServerTrusted(X509Certificate[] certs, String authType) { 
       // Trust always 
      } 
     } 
    }; 

을 또한() 메소드 :

HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); 
+0

나는 이것을 시도하지는 않았지만, 나에게 잘 작동하는 아파치 클라이언트로 전환했다. – Karl