2014-01-08 84 views
6

我有一個高容量的Java應用程序,我必須發送http帖子到另一臺服務器。 目前我使用org.apache.commons.httpclient庫:java非阻塞HTTP客戶端

private static void sendData(String data) { 
HttpClient httpclient = new HttpClient(); 
StringRequestEntity requestEntity; 
try { 
    requestEntity = new StringRequestEntity(data, "application/json", "UTF-8"); 
    String address = "http://<my host>/events/" 
    PostMethod postMethod = new PostMethod(address); 
    postMethod.setRequestEntity(requestEntity); 

    httpclient.executeMethod(postMethod); 

} catch (Exception e) { 
    LOG.error("Failed to send data ", e); 

} 
} 

這意味着我會把我的http請求同步,這不適合我的多線程大批量應用。所以我想將這些調用改爲異步非阻塞http調用。

我正在通過一些選項,如apache async clientxsocket,但無法使其工作。

嘗試ning

private static void sendEventToGrpahiteAsync(String event) { 
LOG.info("\n" + "sendEventToGrpahiteAsync"); 
try (AsyncHttpClient asyncHttpClient = new AsyncHttpClient()) { 
    BoundRequestBuilder post = asyncHttpClient.preparePost(); 
    post.addHeader("Content-Type", "application/json"); 
    post.setBodyEncoding("UTF-8"); 
    post.setBody(event); 
    post.execute(new HttpRequestCompletionHandler()); 
} catch (Exception e) { 
    LOG.error("Failed to sending event", e); 
} 
} 

我想阿帕奇HttpAsyncClient

private static void sendEventToGrpahiteAsync(String event) { 
LOG.info("\n" + "sendEventToGrpahiteAsync"); 
try (CloseableHttpAsyncClient httpclient = HttpAsyncClients.createDefault()) { 
    httpclient.start(); 
    HttpPost request = new HttpPost(addr); 
    StringEntity entity = new StringEntity(event, ContentType.create("application/json", Consts.UTF_8)); 
    request.setEntity(entity); 
    httpclient.execute(request, null); 
} catch (Exception e) { 
    LOG.error("Failed to sending event", e); 
} 
} 

我試圖xsocket

private static void sendEventToGrpahiteAsync2(String event) { 
LOG.info("\n" + "sendEventToGrpahiteAsync"); 
try (INonBlockingConnection con = new NonBlockingConnection(<SERVER_IP>, 80); 
    IHttpClientEndpoint httpClientConnection = new HttpClientConnection(con)) { 
    IHttpResponseHandler responseHandler = new MyResponseHandler(); 
    IHttpRequest request = new PostRequest(url_address, "application/json", Consts.UTF_8.toString(), event); 
    request.setTransferEncoding(Consts.UTF_8.toString()); 
    httpClientConnection.send(request, responseHandler); 
} catch (Exception e) { 
    LOG.error("Failed to sending event", e); 
} 
} 

我沒有得到任何異常,但後沒有得到的目標也是如此。 要明確,目標是graphite server,所以一旦帖子到達,它清楚地在一個圖表中看到。同步帖子效果很好,我可以在圖表上看到結果,但是沒有任何異步帖子顯示在我的目標圖表上。

我錯過了什麼?

感謝

+0

只需將'apache async client'的第一個示例轉換爲使用'HttpPost'而不是'HttpGet'。 –

+0

如何通過一個工作示例發佈答案並獲得一些信用? – forhas

回答

1

明白了。

我使用的所有庫都是使用額外的IO線程來實現的,所以我的過程可能在完全握手之前結束。

一旦我在http調用之後添加Thread.sleep(2000),事情就很好。 所以對於一個網絡應用程序(這是我的情況),我建議的實現就好(但對於Java過程,你可能會考慮NickJ的答案)。

1

您可以使用Java執行人框架:

首先,創建一個可贖回做你的工作:

public class MyCallable implements Callable<MyResult> { 
    @Override 
    public MyResult call() throws Exception { 
    //do stuff 
    return result; 
    } 
} 

獲取一個Exectutor將運行調用。有各種不同的方式來獲得一個,這裏有一個例子:

ExecutorService executor = Executors.newFixedThreadPool(NTHREDS); 

最後,運行它:

MyCallable callable = new MyCallable(); 
Future<MyResult> futureResult = executor.submit(callable); 

獲取結果:

boolean resultReady = futureResult.isDone(); //is the result ready yet? 
Result r = futureResult.get(); //wait for result and return it 

try { 
    Result r = futureResult.get(10, TimeUnit.SECONDS); //wait max. 10 seconds for result 
} catch (TimeOutException e) { 
    //result still not ready after waiting 10 seconds 
} 
+0

不錯,但我寧願使用一個圖書館爲我做這件事,除非沒有,但據我所知,有一些。 – forhas

+4

這不是簡單地根據請求觸發線程而不是真正的非阻塞I/O? – necromancer

+3

這是沒有什麼不同,然後阻止調用線程。您應該使用NIO客戶端來執行適當的非阻塞請求。 – HaxElit