初め、
解決策を見つけるために多くのことを検索しましたが、適切な解決策を見つけることができませんでした。
環境
- (生産的) Mongoose WebServer は単純な GET 要求に応答します (すべてのデータは QueryString を介して送信されます)
- Apache HttpClient (単一インスタンス!) は、数十万の単一リクエストを順番に作成するために使用されます。
マングースと対話するApache HttpClientは非常にうまく機能します
// after each request getMethod.releaseConnection(); ...
問題
- (モック) Sun HttpServer を使用した WebServer の実装は、FireFox / Curl で正常に動作します
- 本番サーバーに対して実行する場合と同様に Apache HttpClient を使用すると、クライアントでのパフォーマンスがひどい (~ 1 リクエスト/秒)
- ネットで見つかった次のコードで Apache HttpClient を使用すると、
- クライアントでの大幅なパフォーマンスの向上
- 処理された要求と同じ数の CLOSE_WAIT 状態のオープン ソケットによるリソースの浪費 (使用可能な FD がなくなるまで!)
コード:
HttpConnectionManager mgr = httpClient.getHttpConnectionManager();
if (mgr instanceof SimpleHttpConnectionManager) {
((SimpleHttpConnectionManager)mgr).shutdown();
}
明らかに、http サーバーの実装に何かが欠けているため、この極端な「遅さ」が発生します。
ヒント/ヘルプをいただければ幸いです。
前もって感謝します!
コード
HttpServer
public static void main(String[] args) throws Exception {
//System.setProperty("sun.net.httpserver.maxIdleConnections", "10");
//System.setProperty("sun.net.httpserver.idleInterval", "2000");
HttpServer server = HttpServer.create();
server.bind(new InetSocketAddress("localhost", 11111), -1);
InetSocketAddress addr = server.getAddress();
HttpContext contextSearch = server.createContext("/search.to",
new TrufflesSearchHandler());
contextSearch.getFilters().add(new ParameterFilter());
server.setExecutor(null); // creates a default executor
server.start();
}
HttpHandler
static class SearchHandler implements HttpHandler {
private JSONParser jsonParser = new JSONParser();
public void handle(HttpExchange exchange) throws IOException {
Map<String, Object> params = (Map<String, Object>) exchange
.getAttribute("parameters");
String expectedResponse = "";
int expectedHitPlace = -1;
try {
expectedResponse = (String) params.get("expectedResponse");
expectedHitPlace = Integer.parseInt((String) params
.get("expectedHitPlace"));
} catch (Exception e) {
e.printStackTrace();
}
JSONArray resultArray = null;
try {
resultArray = (JSONArray) jsonParser.parse(new String(Base64
.decodeBase64(expectedResponse)));
fillResponseWithDummyData(resultArray, expectedHitPlace);
} catch (ParseException e) {
e.printStackTrace();
}
String response = "{ \"results\": " + resultArray + "}";
Headers headers = exchange.getResponseHeaders();
headers.add("Connection", "keep-alive");
headers.add("Content-Type", "text/plain");
headers.add("Content-length", "" + response.getBytes().length);
// headers.add("Keep-Alive", "timeout=5 max=10");
exchange.sendResponseHeaders(200, 0);
// exchange.sendResponseHeaders(200, response.getBytes().length);
OutputStream os = exchange.getResponseBody();
os.write(response.getBytes());
os.flush();
os.close();
// exchange.close();
}
ParameterFilter
@SuppressWarnings("restriction")
public class ParameterFilter extends Filter {
@Override
public String description() {
return "Parses the requested URI for parameters";
}
@Override
public void doFilter(HttpExchange exchange, Chain chain)
throws IOException {
parseGetParameters(exchange);
parsePostParameters(exchange);
chain.doFilter(exchange);
}
private void parseGetParameters(HttpExchange exchange)
throws UnsupportedEncodingException {
Map<String, Object> parameters = new HashMap<String, Object>();
URI requestedUri = exchange.getRequestURI();
String query = requestedUri.getRawQuery();
parseQuery(query, parameters);
exchange.setAttribute("parameters", parameters);
}
private void parsePostParameters(HttpExchange exchange)
throws IOException {
if ("post".equalsIgnoreCase(exchange.getRequestMethod())) {
@SuppressWarnings("unchecked")
Map<String, Object> parameters =
(Map<String, Object>)exchange.getAttribute("parameters");
InputStreamReader isr =
new InputStreamReader(exchange.getRequestBody(),"utf-8");
BufferedReader br = new BufferedReader(isr);
String query = br.readLine();
parseQuery(query, parameters);
}
}
private void parseQuery(String query, Map<String, Object> parameters)
throws UnsupportedEncodingException {
String encoding = System.getProperty("file.encoding");
if (query != null) {
String pairs[] = query.split("[&]");
for (String pair : pairs) {
String param[] = pair.split("[=]");
String key = null;
String value = null;
if (param.length > 0) {
key = URLDecoder.decode(param[0],
encoding);
}
if (param.length > 1) {
value = URLDecoder.decode(param[1],
encoding);
}
if (parameters.containsKey(key)) {
Object obj = parameters.get(key);
if(obj instanceof List<?>) {
List<String> values = (List<String>)obj;
values.add(value);
} else if(obj instanceof String) {
List<String> values = new ArrayList<String>();
values.add((String)obj);
values.add(value);
parameters.put(key, values);
}
} else {
parameters.put(key, value);
}
}
}
}
}