15

での実行をテストするためにでJUnitテストを使用しています。への呼び出しの 1 つが、 の各ブロックの後に 10 秒間ハングします。同等のコードは数ミリ秒で実行されます。モードを切り替えると、問題はなくなります。JERSEY Client + HTTPSsecure web serviceJettywr.get( ClientResponse.class)9-10 requestsApache clientJetty to HTTP

私は使っているJersey bundle & client 1.14 and Jetty 6.1.26



Apache クライアントが動作する

@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();
  }
}



Jersey クライアントがハングする

@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();
  }
}

からエンティティを取得するClientResponseと問題が発生するようですが、モードでのみHTTPS、Web サーバーに対して実行されます (ではないgoogle, facebook, etc)。実行Jersey ServletContainer and Struts ActionServletしましJettyたが、両方で問題が発生します。subnetまた、複数のマシンから単体テストを行い、別のマシンで Web サーバーを実行しました。



ジャージー 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;
}



Jetty 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>
4

2 に答える 2

1

これらはどのOSで実行されていますか?

単なる推測ですが、/dev/random実装が遅いことに関連している可能性があります(経由SecureRandom)。

ここでの関連する議論:

Java SecureRandomでパフォーマンスの問題を解決するにはどうすればよいですか?

WebアプリでJVMパラメーターを常に制御できるとは限らないため、これを回避策として使用しています。

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

それが厳密に言えば推奨されているかどうかはわかりません(しかし、それは私にとって問題を解決します)。

于 2012-11-08T20:42:24.007 に答える
0

trustManager の実装を少し変更してみてください。

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
            }
        }
    };

また、getSSLContext() メソッドの最後で HttpsURLConnection.setDefaultSocketFactory を呼び出すことを忘れないでください。

HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
于 2013-02-21T13:18:30.497 に答える