/**
* Dianping.com Inc.
* Copyright (c) 2003-2013 All Rights Reserved.
*/
package com.dianping.pigeon.remoting.http.invoker;
import java.net.ConnectException;
import java.util.List;
import com.dianping.pigeon.remoting.common.channel.Channel;
import com.dianping.pigeon.remoting.common.codec.SerializerType;
import com.dianping.pigeon.remoting.invoker.process.ResponseProcessor;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import com.dianping.pigeon.remoting.common.domain.InvocationRequest;
import com.dianping.pigeon.remoting.common.domain.InvocationResponse;
import com.dianping.pigeon.remoting.common.exception.NetworkException;
import com.dianping.pigeon.remoting.common.util.Constants;
import com.dianping.pigeon.remoting.common.util.InvocationUtils;
import com.dianping.pigeon.remoting.invoker.AbstractClient;
import com.dianping.pigeon.remoting.invoker.client.ClientConfig;
import com.dianping.pigeon.remoting.invoker.domain.ConnectInfo;
public class HttpInvokerClient extends AbstractClient {
private ConnectInfo connectInfo;
private HttpInvokerExecutor httpInvokerExecutor;
private String serviceUrlPrefix = null;
private String defaultServiceUrl = null;
private boolean isConnected = false;
public static final String CONTENT_TYPE_SERIALIZED_OBJECT = "application/x-java-serialized-object";
public HttpInvokerClient(ClientConfig clientConfig, ConnectInfo connectInfo, ResponseProcessor responseProcessor) {
super(clientConfig, responseProcessor);
this.connectInfo = connectInfo;
if (logger.isInfoEnabled()) {
logger.info("http client:" + connectInfo);
}
serviceUrlPrefix = "http://" + connectInfo.getHost() + ":" + connectInfo.getPort() + "/";
defaultServiceUrl = serviceUrlPrefix + "service";
httpInvokerExecutor = new HttpInvokerExecutor();
HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
HttpConnectionManagerParams params = new HttpConnectionManagerParams();
params.setMaxTotalConnections(300);
params.setDefaultMaxConnectionsPerHost(50);
params.setConnectionTimeout(1000);
params.setTcpNoDelay(true);
params.setSoTimeout(3000);
params.setStaleCheckingEnabled(true);
connectionManager.setParams(params);
HttpClient httpClient = new HttpClient();
httpClient.setHttpConnectionManager(connectionManager);
httpInvokerExecutor.setHttpClient(httpClient);
}
@Override
public ConnectInfo getConnectInfo() {
return connectInfo;
}
@Override
public void doOpen() {
InvocationRequest request = InvocationUtils.newRequest(Constants.HEART_TASK_SERVICE,
Constants.HEART_TASK_METHOD, null, SerializerType.HESSIAN.getCode(), Constants.MESSAGE_TYPE_HEART, 5000,
null);
request.setSequence(0);
request.setCreateMillisTime(System.currentTimeMillis());
request.setCallType(Constants.CALLTYPE_REPLY);
InvocationResponse response = null;
try {
response = this.write(request);
if (response != null && response.getSequence() == 0) {
isConnected = true;
}
} catch (Throwable e) {
close();
isConnected = false;
}
}
@Override
public InvocationResponse doWrite(InvocationRequest invocationRequest) throws NetworkException {
return write(defaultServiceUrl, invocationRequest);
}
public InvocationResponse write(String url, InvocationRequest request) throws NetworkException {
final int timeout = request.getTimeout();
httpInvokerExecutor.setReadTimeout(timeout);
try {
InvocationResponse invocationResponse = httpInvokerExecutor.executeRequest(url, request);
this.isConnected = true;
return invocationResponse;
} catch (ConnectException e) {
this.isConnected = false;
throw new NetworkException("remote call failed:" + url + ", request:" + request, e);
} catch (Throwable e) {
throw new NetworkException("remote call failed:" + url + ", request:" + request, e);
}
}
@Override
public String getHost() {
return connectInfo.getHost();
}
@Override
public String getAddress() {
return connectInfo.getHost() + ":" + connectInfo.getPort();
}
@Override
public int getPort() {
return connectInfo.getPort();
}
@Override
public boolean isActive() {
return super.isActive() && isConnected;
}
@Override
public void doClose() {
}
@Override
public List<Channel> getChannels() {
return null;
}
@Override
public String toString() {
return this.getAddress();
}
public boolean equals(Object obj) {
if (obj instanceof HttpInvokerClient) {
HttpInvokerClient nc = (HttpInvokerClient) obj;
return this.getAddress().equals(nc.getAddress());
} else {
return super.equals(obj);
}
}
@Override
public int hashCode() {
return getAddress().hashCode();
}
@Override
public String getProtocol() {
return Constants.PROTOCOL_HTTP;
}
}