做了一个物流的信息对接平台,从下级平台获取车辆的gps信息采用tcp 长连接,200辆车没30秒刷新一次数据,跑了2天jvm 溢出了就大神指导下则么解决,
public class Serve {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap(); // (2)
b.group(bossGroup, workerGroup)
//设置协议类型
.channel(NioServerSocketChannel.class)
//设置处理类
.childHandler(new ChannelInitializer<SocketChannel>(){
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new ServeHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture f = b.bind(40009).sync();
System.out.println("服务已启动");
f.channel().closeFuture().sync();
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
public class ServeHandler extends ChannelHandlerAdapter{
HandlerExcutorPool excuPool=new HandlerExcutorPool(100, 500); //新建线程池
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
try{
ByteBuf buf=(ByteBuf)msg;
byte[] data=new byte[buf.readableBytes()];
buf.readBytes(data);
if(data[0]==0x5b&&data[data.length-1]==0x5d){
byte[] content=new byte[data.length-2];
content=common.subBytes(data, 1, data.length-2);
byte[] relCon=EscapedUtil.Escaped(content);
byte[] headAndBody=new byte[relCon.length-2];
byte[] headArr=new byte[22];
//抽出数据头和数据体
for(int i=0;i<relCon.length-2;i++){
headAndBody[i]=(byte) (relCon[i]);
if(i<22){
headArr[i]=(byte) (relCon[i]);
}
}
//数据转义
//headAndBody=EscapedUtil.Escaped(headAndBody);
//crc校验
int crc=GetCrc16_CCITT.GetCrc16_CCITT(headAndBody);
//System.out.println(Integer.toHexString(crc));
int crc1=(relCon[relCon.length-2]&0xff)<<8|(relCon[relCon.length-1]&0xff);
if((crc&0xffff)==(crc1&0xffff)){
//得到数据头的bean
Head809 head=HeadService.get809Head(headAndBody);
//业务分发
if((head.getMsg_id()&0xffff)==MegId.UP_CONNECT_REQ){ //登入请求
LoginService login=new LoginService(headAndBody);
byte[] rebodyData=login.checkLogin(headAndBody,head.msg_gnsscenterid); // 检查用户名密码和接入码
headArr[8]=0x10;
headArr[9]=0x02;
byte[] relData=common.getRelData(headArr, rebodyData);
//往客户端发送应答信息
ctx.channel().writeAndFlush(Unpooled.copiedBuffer(relData));
}else if((head.getMsg_id()&0xffff)==MegId.UP_DISCONNECT_REQ){
headArr[8]=0x10;
headArr[9]=0x04;
byte[] relData=common.getRelData(headArr);
ctx.channel().writeAndFlush(Unpooled.copiedBuffer(relData)).addListener(ChannelFutureListener.CLOSE);
}else if((head.getMsg_id()&0xffff)==MegId.UP_LINKTEST_REQ){
headArr[8]=0x10;
headArr[9]=0x06;
byte[] relData=common.getRelData(headArr);
ctx.channel().writeAndFlush(Unpooled.copiedBuffer(relData));
}else if((head.getMsg_id()&0xffff)==MegId.UP_EXG_MSG){
excuPool.executor(new PositionService(headAndBody)); // 线程池
}
}
}
System.gc();
}finally {
ReferenceCountUtil.release(msg);
}
}
public class HandlerExcutorPool {
private ExecutorService excutor;
public HandlerExcutorPool(int maxPoolSize,int queueSize){
this.excutor=new ThreadPoolExecutor(
Runtime.getRuntime().availableProcessors(),
maxPoolSize,
120L,
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(queueSize));
}
public void executor(Runnable task){
this.excutor.execute(task);
}
}
public class PositionService implements Runnable {
//public static HashMap<String, String> carMap=new HashMap<String, String>();
private byte[] arr;
public PositionService(byte[] data){
this.arr=data;
}
private CarPositionInfo positionHandler(byte[] data) throws UnsupportedEncodingException{
byte[] body=common.subBytes(data, 22, data.length-22);
byte[] carId=common.subBytes(body, 0, 21);
byte[] type=common.subBytes(body, 22, 2);
byte[] lastLength=common.subBytes(body, 24, 4);
long leng=(((lastLength[0]&0xff)<<24)|((lastLength[1]&0xff)<<16)|((lastLength[2]&0xff)<<8)|(lastLength[3]&0xff))&0x00000000ffffffff;
byte[] last=common.subBytes(body, 28,36);
String carNum=new String(carId, "GBK");
int subType=(((type[0]&0xff)<<8)|(type[1]&0xff))&0x0000ffff;
CarPositionInfo posiInfo=new CarPositionInfo();
posiInfo.setCarId(carNum);
if(subType==MegId.UP_EXG_MSG_REAL_LOCATION){
boolean entrpt=last[0]==0x00?false:true;
int year=(((last[3]&0xff)<<8)|(last[4]&0xff))&0x0000ffff;
short month=(short) (last[2]&0x00ff);
short day=(short) (last[1]&0x00ff);
short hour=(short) (last[5]&0x00ff);
short min=(short) (last[6]&0x00ff);
short sec=(short) (last[7]&0x00ff);
String date=""+year+"-"+month+"-"+day+" "+hour+":"+min+":"+sec;
long lon=(((last[8]&0xff)<<24)|((last[9]&0xff)<<16)|((last[10]&0xff)<<8)|(last[11]&0xff))&0x00000000ffffffff;
long lat=(((last[12]&0xff)<<24)|((last[13]&0xff)<<16)|((last[14]&0xff)<<8)|(last[15]&0xff))&0x00000000ffffffff;
String lonStr=""+lon/1000000+"."+getStr(""+lon%1000000,6);
String latStr=""+lat/1000000+"."+getStr(""+lat%1000000,6);
int vec=(((last[16]&0xff)<<8)|(last[17]&0xff))&0x0000ffff;
posiInfo.setEncrypt(entrpt);
posiInfo.setDate(date);
posiInfo.setLon(Double.valueOf(lonStr));
posiInfo.setLat(Double.valueOf(latStr));
posiInfo.setVec(vec);
}
return posiInfo;
}
public void sendMsg(byte[] data) {
try{
CarPositionInfo carInfo=positionHandler(data);
HttpRequestUtils req=new HttpRequestUtils();
Map map=req.getparams();
SimpleDateFormat simp=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
map.put("entity_name", carInfo.carId.trim().replaceAll(" +", ""));
map.put("latitude", carInfo.lat);
map.put("longitude", carInfo.lon);
map.put("speed", carInfo.vec);
map.put("coord_type", carInfo.encrypt?2:1);
map.put("loc_time", (simp.parse(carInfo.date).getTime())/1000);
String json=req.httpPostRequest("http://api.map.baidu.com/trace/v2/track/addpoint", map);
}catch (Exception e) {
e.printStackTrace();
}
}
private String getStr(String a,int b){
String str="";
if(a.length()>=b)
return a;
else{
for(int i=a.length();i<b;i++){
str+="0";
}
return str+a;
}
}
public void run() {
try {
sendMsg(this.arr);
} catch (Exception e) {
e.printStackTrace();
}
}
}
主要跑的ServeHandler中的excuPool.executor(new PositionService(headAndBody)); 这段代码跑了2天jvm内存溢出求解则么玩
是不是创建线程消耗了了太多的native memory资源,; JDk安装目录、bin文件夹下,运行jconsole.exe,看一下线程相关信息。
HandlerExcutorPool excuPool=new HandlerExcutorPool(100, 500); //新建线程池
--- 这里100是不是没必要这么大,有个10就差不多了