2015-09-28 84 views
0

我下面的代碼是使用apache http客戶端4.5版本的池連接管理器。如果我發出50個請求,我看到在netstat中有50個不同的tcp端口正在使用,但是在任何時候最多使用5個連接。我曾在線鯊中看到過濾器tcp.flags.syn==1 && tcp.flags.ack==0它在過濾器中創建了50個數據包,因此它使用不同的連接而不是使用相同的連接,所以爲什麼不能這樣做?HTTP客戶端4.5不重複使用相同的連接使用java中的池連接管理器

我的代碼:

import javax.net.ssl.SSLContext; 

import org.apache.http.HttpEntity; 
import org.apache.http.HttpHost; 
import org.apache.http.client.ClientProtocolException; 
import org.apache.http.client.methods.CloseableHttpResponse; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.config.Registry; 
import org.apache.http.config.RegistryBuilder; 
import org.apache.http.conn.routing.HttpRoute; 
import org.apache.http.conn.socket.ConnectionSocketFactory; 
import org.apache.http.conn.socket.PlainConnectionSocketFactory; 
import org.apache.http.conn.ssl.NoopHostnameVerifier; 
import org.apache.http.conn.ssl.SSLConnectionSocketFactory; 
import org.apache.http.entity.StringEntity; 
import org.apache.http.impl.client.CloseableHttpClient; 
import org.apache.http.impl.client.HttpClients; 
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; 
import org.apache.http.util.EntityUtils; 
import org.glassfish.jersey.SslConfigurator; 
import org.json.JSONException; 
import org.json.JSONObject; 

public class App3Conn { 
    private static CloseableHttpClient client; 


    static String target="https://example.com"; 

    static PoolingHttpClientConnectionManager cm ; 
static{ 

SslConfigurator sslConfig = SslConfigurator.newInstance() 
      .securityProtocol("TLS") 
      .keyStoreFile("/Users/file") 
      .keyStorePassword("passw") 
      .keyStoreType("JKS") 
      .trustStoreFile("/Users/file"); 

    SSLContext sslCtx = sslConfig.createSSLContext(); 
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslCtx,NoopHostnameVerifier.INSTANCE); 
    Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory>create() 
      .register("http", PlainConnectionSocketFactory.getSocketFactory()) 
      .register("https", sslsf) 
      .build(); 


    cm = new PoolingHttpClientConnectionManager(r); 
    cm.setMaxTotal(15); 
    cm.setDefaultMaxPerRoute(5); 

    client = HttpClients.custom().setSSLSocketFactory(sslsf).setConnectionManager(cm).build(); 


} 
public static void main(String a[]) throws JSONException, ClientProtocolException, IOException 
{ 

    JSONObject jsonMessage = new JSONObject(); 



    JSONObject jsonResponse; 

    jsonMessage.put("keyID", "keyID"); 


    StringEntity se = new StringEntity(jsonMessage.toString()); 
    CloseableHttpResponse response2; 
    HttpPost httpPost = new HttpPost(target); 
    httpPost.setEntity(se); 
    httpPost.setHeader("Accept", "application/json"); 
    httpPost.setHeader("Content-type", "application/json"); 
    httpPost.setHeader("Connection", "keep-alive"); 
    int i; 
    for(i=0;i<50;i++) 
    { 

     response2 = client.execute(httpPost); 


    HttpEntity entity2 = response2.getEntity(); 
    String result = EntityUtils.toString(entity2); 

    EntityUtils.consume(entity2); 


    jsonResponse = new JSONObject(result); 

    String text = jsonResponse.getString("result"); 


    response2.close(); 
    } 
} 
} 
+0

可能與您的TLS配置有關。我懷疑它認爲它每次都需要一個新的連接,並沒有意識到它可以重用連接。也許嘗試如果刪除它可以修復一些不同的服務器的症狀。如果是這樣,SSLConnectionSocketFactory可能是問題。我實際上並沒有使用它,所以無法進一步幫助你。 –

+0

檢查哪一方正在關閉連接以及HTTP標頭說什麼。 Keep-Alive只是客戶的建議,而不是服務器的必需品。請求完成後,服務器仍然可以關閉連接。 –

+0

服務器有24小時保持活着財產 – Labeo

回答

0

我以前見過這一個。這取決於Apache連接池的工作方式。一個不透明的state成員與池條目相關聯,並且在請求(租用)池條目時必須匹配請求的狀態。

當連接租賃嘗試進行時,請求的statenull。但是,當連接放回池中時,state將設置爲SSL對等方的X500Principal對象。這發生在DefaultUserTokenHandler類中。幸運的是,當我們創建HttpClient類時,這是可以覆蓋的。這裏有一個例子:

HttpClient apacheHttpClient = HttpClients.custom() 
    .setConnectionReuseStrategy(new DefaultConnectionReuseStrategy()) 
    .setConnectionManager(new PoolingHttpClientConnectionManager(r)) 
    .setUserTokenHandler(new UserTokenHandler() { 
     @Override 
     public Object getUserToken(HttpContext context) { 
     return null; 
     } 
    }) 
    .build(); 

做檢查,你沒有失去你從DefaultUserTokenHandler依賴和不使用此方法什麼,如果你創建了HttpClient可以通過相同的HTTP路徑連接到多個SSL同行。在我的情況下,這個客戶端用於連接到一個SSL服務器。