mirror of
https://github.com/wahyd4/pinpoint.git
synced 2026-08-17 16:56:15 +10:00
[강운덕] [LUCYSUS-1744] 메시지 멀티플랙싱 기능 변경.
git-svn-id: http://svn.bds.nhncorp.com/pe/hippo-tomcat-profiler/trunk@502 84d0f5b1-2673-498c-a247-62c4ff18d310
This commit is contained in:
@@ -6,101 +6,123 @@ import java.net.DatagramSocket;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.profiler.dto.Header;
|
||||
import com.profiler.util.DefaultTBaseLocator;
|
||||
import com.profiler.util.HeaderTBaseSerializer;
|
||||
import com.profiler.util.TBaseLocator;
|
||||
import org.apache.thrift.TBase;
|
||||
import org.apache.thrift.TException;
|
||||
import org.apache.thrift.TSerializer;
|
||||
import org.apache.thrift.protocol.TBinaryProtocol;
|
||||
|
||||
import com.profiler.config.TomcatProfilerConfig;
|
||||
import com.profiler.dto.JVMInfoThriftDTO;
|
||||
import com.profiler.dto.RequestDataListThriftDTO;
|
||||
import com.profiler.dto.RequestThriftDTO;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author netspider
|
||||
*
|
||||
*/
|
||||
public class DataSender extends Thread {
|
||||
|
||||
private final Logger logger = Logger.getLogger(DataSender.class.getName());
|
||||
private final Logger logger = Logger.getLogger(DataSender.class.getName());
|
||||
|
||||
private final LinkedBlockingQueue<TBase<?, ?>> addedQueue = new LinkedBlockingQueue<TBase<?, ?>>(4096);
|
||||
private final LinkedBlockingQueue<TBase<?, ?>> addedQueue = new LinkedBlockingQueue<TBase<?, ?>>(4096);
|
||||
|
||||
private final InetSocketAddress requestDataAddr = new InetSocketAddress(TomcatProfilerConfig.SERVER_IP, TomcatProfilerConfig.REQUEST_DATA_LISTEN_PORT);
|
||||
private final InetSocketAddress requestTransactionDataAddr = new InetSocketAddress(TomcatProfilerConfig.SERVER_IP, TomcatProfilerConfig.REQUEST_TRANSACTION_DATA_LISTEN_PORT);
|
||||
private final InetSocketAddress jvmDataAddr = new InetSocketAddress(TomcatProfilerConfig.SERVER_IP, TomcatProfilerConfig.JVM_DATA_LISTEN_PORT);
|
||||
private final InetSocketAddress serverAddress = new InetSocketAddress(TomcatProfilerConfig.SERVER_IP, TomcatProfilerConfig.DEFUALT_PORT);
|
||||
|
||||
private static class SingletonHolder {
|
||||
public static final DataSender INSTANCE = new DataSender();
|
||||
}
|
||||
private DatagramSocket udpSocket = null;
|
||||
private TBaseLocator locator = new DefaultTBaseLocator();
|
||||
// 주의 single thread용임
|
||||
private HeaderTBaseSerializer serializer = new HeaderTBaseSerializer();
|
||||
|
||||
public static DataSender getInstance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
private DataSender() {
|
||||
udpSocket = createSocket();
|
||||
setName("HIPPO-DataSender");
|
||||
setDaemon(true);
|
||||
start();
|
||||
}
|
||||
|
||||
private DataSender() {
|
||||
setName("HIPPO-DataSender");
|
||||
setDaemon(true);
|
||||
start();
|
||||
}
|
||||
private DatagramSocket createSocket() {
|
||||
try {
|
||||
DatagramSocket datagramSocket = new DatagramSocket();
|
||||
datagramSocket.setSoTimeout(1000 * 5);
|
||||
datagramSocket.connect(serverAddress);
|
||||
return datagramSocket;
|
||||
} catch (SocketException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addDataToSend(TBase<?, ?> data) {
|
||||
// TODO: addedQueue가 full일 때 IllegalStateException처리.
|
||||
return addedQueue.add(data);
|
||||
}
|
||||
public boolean addDataToSend(TBase<?, ?> data) {
|
||||
// TODO: addedQueue가 full일 때 IllegalStateException처리.
|
||||
return addedQueue.add(data);
|
||||
}
|
||||
|
||||
// TODO: send timeout추
|
||||
// TODO: addedqueue에서 bulk로 drain
|
||||
// TODO: sender thread가 한 개로 충분한가.
|
||||
public void run() {
|
||||
while (true) {
|
||||
DatagramSocket udpSocket = null;
|
||||
try {
|
||||
TBase<?, ?> dto = addedQueue.take();
|
||||
// TODO TSerializer대신에 HeaderTBaseSerializer로 하고 Header를 생성하여 같이 넘기면 되며
|
||||
// 받는 쪽에서. HeaderTBaseDeSerialize로 받으면 됨.
|
||||
// 단 header의 type 정보를 수동으로 넣어야 되는지가 불편함이 있음.
|
||||
TSerializer serializer = new TSerializer(new TBinaryProtocol.Factory());
|
||||
byte[] sendData = serializer.serialize(dto);
|
||||
|
||||
// TODO: 포트 하나로 통일 시켜야 함. 일단 임시로 이렇게..
|
||||
InetSocketAddress address = null;
|
||||
if (dto instanceof RequestDataListThriftDTO) {
|
||||
address = requestDataAddr;
|
||||
} else if (dto instanceof RequestThriftDTO) {
|
||||
address = requestTransactionDataAddr;
|
||||
} else if (dto instanceof JVMInfoThriftDTO) {
|
||||
address = jvmDataAddr;
|
||||
}
|
||||
// TODO: sender thread가 한 개로 충분한가.
|
||||
public void run() {
|
||||
while (true) {
|
||||
try {
|
||||
TBase<?, ?> dto = take();
|
||||
if (dto == null) {
|
||||
continue;
|
||||
}
|
||||
send(dto);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.WARNING, "Unexpected Error", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (address == null) {
|
||||
throw new IllegalArgumentException("Can't resolve receiver address.");
|
||||
}
|
||||
private void send(TBase<?, ?> dto) {
|
||||
byte[] sendData = serialize(dto);
|
||||
if (sendData == null) {
|
||||
return;
|
||||
}
|
||||
DatagramPacket packet = new DatagramPacket(sendData, sendData.length);
|
||||
if (udpSocket == null) {
|
||||
// socket생성에 문제가 있으면 재생성?
|
||||
udpSocket = createSocket();
|
||||
}
|
||||
if (udpSocket != null) {
|
||||
try {
|
||||
udpSocket.send(packet);
|
||||
if (logger.isLoggable(Level.FINE)) {
|
||||
logger.fine("Data sent. " + dto);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.WARNING, "packet send error " + dto, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DatagramPacket packet = new DatagramPacket(sendData, sendData.length, address);
|
||||
|
||||
udpSocket = new DatagramSocket();
|
||||
udpSocket.send(packet);
|
||||
// TODO: addedqueue에서 bulk로 drain
|
||||
private TBase<?, ?> take() {
|
||||
try {
|
||||
return addedQueue.poll(5, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: for test 로그레벨 바꾸기.
|
||||
logger.info(String.format("Data sent. %s", dto));
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (TException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (udpSocket != null) {
|
||||
udpSocket.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private byte[] serialize(TBase<?, ?> dto) {
|
||||
Header header = createHeader(dto);
|
||||
try {
|
||||
return serializer.serialize(header, dto);
|
||||
} catch (TException e) {
|
||||
if (logger.isLoggable(Level.INFO)) {
|
||||
logger.log(Level.INFO, "Serialize fail:" + dto, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Header createHeader(TBase<?, ?> dto) {
|
||||
short type = locator.typeLookup(dto);
|
||||
Header header = new Header();
|
||||
header.setType(type);
|
||||
return header;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user