记一次部署项目踩过的坑

4 篇文章 0 订阅
3 篇文章 0 订阅

7月初公司接到一个项目,很简单ssm的项目,其中有一块就是数据入库。

编写入库代码,我擅长的很啊,对不对,和磊哥怎么也算是混了一年,不会个入库,岂不是很丢人。

刷刷刷……

没错。很快这个脚本就如火如荼的用上了。

结果真是不尽如人意,是的,没错,报错了!!!

java.lang.OutOfMemoryError: Java heap space 堆内存异常,不得不说,bug真是程序员的好朋友,通过这一周的学习,我学习了堆内存溢出的原因,解决方案,如何调整jar包的内存大小等等等等。

且慢,尽管学习了这么多,但是问题还是没解决,这尼玛。原始代码如下:

/**
 * 数值预报
 * 
 * @author gaoyongqin
 *
 */
public class SzybDB {

	public static void intoDB(File inFile) {
		// 经度,纬度,温度,过去一小时降水
		// Lat,Lon,TEM,PRE_1h
		PreparedStatement prep = null;
		Connection con = C3P0Inner.getConnection();
		String foreignKeySql = "insert into data_szyb values";
		StringBuilder foreignKeyValue = new StringBuilder();

		int i = 0;
		String str = null;
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHH");
		BufferedReader br = null;
		String format = sdf.format(new Date());
		try {
			br = new BufferedReader(new InputStreamReader(new FileInputStream(inFile)));
			while ((str = br.readLine()) != null) {
				i++;
				// 该文件第一行直接就是数据,所以不用过滤掉表头
				foreignKeyValue.append(",").append("(").append("null").append(",'");
				String replace = str.replace(" ", "','");
				String name = inFile.getName();
				foreignKeyValue.append(replace).append("','").append(name.substring(0, name.indexOf(".")));
				foreignKeyValue.append("','").append(format).append("')");
				if (i % 5000 == 0) {
					try {
						foreignKeyValue.deleteCharAt(0);
						prep = con.prepareStatement(foreignKeySql + foreignKeyValue.toString()
								+ "ON DUPLICATE KEY UPDATE TEM=VALUES(TEM),PRE_1h=VALUES(PRE_1h)"
								+ ",updateTime=VALUES(updateTime)");
						prep.executeUpdate();
					} catch (SQLException e) {
						e.printStackTrace();
					} 
					foreignKeyValue = new StringBuilder();
				}
			}
			if (foreignKeyValue != null && !"".equals(foreignKeyValue)) {
				try {
					foreignKeyValue.deleteCharAt(0);
					prep = con.prepareStatement(foreignKeySql + foreignKeyValue.toString()
							+ "ON DUPLICATE KEY UPDATE TEM=VALUES(TEM),PRE_1h=VALUES(PRE_1h)"
							+ ",updateTime=VALUES(updateTime)");
					prep.executeUpdate();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				System.out.println("数值预报数据在  :" + sdf.format(new Date()) + " 时,入库成功");
			} else {
				System.out.println("数值预报数据在  :" + sdf.format(new Date()) + " 时,无数据");
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {

			try {
				if (br != null) {
					br.close();
				}
				if (prep != null) {
					prep.close();
				}
				if (con != null) {
					con.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}

丝毫不夸张,我找了我代码的原因找了一周,甚至于我一度认为我的代码没有任何的问题,肯定是jar包进程的内存开的不够大,我还请教了磊哥。迪哥,喜喜。磊哥还教我如何使用jmap等工具

nohup java -Djava.library.path=/home/qht/jdk1.7.0_79/jre/bin -Xms4096m -Xmx4096m -XX:+UseG1GC -jar pythonListen.jar zdyb &>log.log &
/home/qht/jdk1.7.0_79/bin/jmap -heap 30869
/home/qht/jdk1.7.0_79/bin/jmap -histo:live 30869

 

我调整了运行jar包的进程内存大小,自己得意的不行,安全的跑了一天的数据,第二天悲催的又堆内存溢出了,这下我不淡定了。感情没几天就要去内蒙部署项目了,现在还在这崩着呢!其中除了内存溢出,还有一个错误:

Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet successfully received from the server was 59,977 milliseconds ago.  The last packet sent successfully to the server was 1 milliseconds ago.

链接超时了,我压根儿没把这两个错误联系在一起,这为我后面找了这个bug找了两周埋下了伏笔。讲真的,我又学会了如何去处理这个链接超时:

参考:https://www.cnblogs.com/chrischennx/p/7279215.html?utm_source=itdadao&utm_medium=referral

Cause: java.sql.SQLException: Could not retrieve transation read-only status server 异常解决

查看和设置隔离级别:https://blog.csdn.net/Rain___Blue/article/details/88564679

第一种:调节wait_timeout,

设置mysql超时:
mysql -uroot -p -h 127.0.0.1

set  global  interactive_timeout=31536000;
set  global  wait_timeout=31536000;

将wait_timeout设置成一年。

第二种:

为了避免空闲时间过长超过最大空闲时间而被断开,我们设置三个配置:

validationQuery: SELECT 1
testWhileIdle: true
timeBetweenEvictionRunsMillis: 28000

其中timeBetweenEvictionRunsMillis需要小于mysql的wait_timeout

但是这种方法无法避免重启的情况,不过一般数据库不会频繁重启,影响不大,如果非得频繁重启,可以通过设置testOnBorrow,即申请连接的时候先试一试连接是否可用,不过带来的影响就是性能降低,需要根据实际需求合理取舍。

其中因为我是用的c3p0链接的数据库,所以设置的参数有点不一样,但是想法是一样的。

参考:https://blog.csdn.net/mmake1994/article/details/86561940

 

好了,后面再说一下那个内存溢出吧!!!

后面其实我想通了,为什么内存溢出了,然后就是链接超时了,哦~~~~(你应该了解我的心情。)

那大约就应该是链接没有关闭???抱着这样的想法,我改了我的代码!

/**
 * 数值预报
 * 
 * @author gaoyongqin
 *
 */
public class SzybDB {

	public static void intoDB(File inFile) {
		// 经度,纬度,温度,过去一小时降水
		// Lat,Lon,TEM,PRE_1h
		PreparedStatement prep = null;
		Connection con = C3P0Inner.getConnection();
		String foreignKeySql = "insert into data_szyb values";
		StringBuilder foreignKeyValue = new StringBuilder();

		int i = 0;
		String str = null;
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHH");
		BufferedReader br = null;
		String format = sdf.format(new Date());
		try {
			br = new BufferedReader(new InputStreamReader(new FileInputStream(inFile)));
			while ((str = br.readLine()) != null) {
				i++;
				// 该文件第一行直接就是数据,所以不用过滤掉表头
				foreignKeyValue.append(",").append("(").append("null").append(",'");
				String replace = str.replace(" ", "','");
				String name = inFile.getName();
				foreignKeyValue.append(replace).append("','").append(name.substring(0, name.indexOf(".")));
				foreignKeyValue.append("','").append(format).append("')");
				if (i % 5000 == 0) {
					try {
						foreignKeyValue.deleteCharAt(0);
						prep = con.prepareStatement(foreignKeySql + foreignKeyValue.toString()
								+ "ON DUPLICATE KEY UPDATE TEM=VALUES(TEM),PRE_1h=VALUES(PRE_1h)"
								+ ",updateTime=VALUES(updateTime)");
						prep.executeUpdate();
					} catch (SQLException e) {
						e.printStackTrace();
					} finally {
						try {
							if (prep != null) {
								prep.close();
							}
						} catch (SQLException e) {
							e.printStackTrace();
						}
					}
					foreignKeyValue = new StringBuilder();
				}
			}
			if (foreignKeyValue != null && !"".equals(foreignKeyValue)) {
				try {
					foreignKeyValue.deleteCharAt(0);
					prep = con.prepareStatement(foreignKeySql + foreignKeyValue.toString()
							+ "ON DUPLICATE KEY UPDATE TEM=VALUES(TEM),PRE_1h=VALUES(PRE_1h)"
							+ ",updateTime=VALUES(updateTime)");
					prep.executeUpdate();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				System.out.println("数值预报数据在  :" + sdf.format(new Date()) + " 时,入库成功");
			} else {
				System.out.println("数值预报数据在  :" + sdf.format(new Date()) + " 时,无数据");
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {

			try {
				if (br != null) {
					br.close();
				}
				if (prep != null) {
					prep.close();
				}
				if (con != null) {
					con.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}

仔细对比代码,没错,我在每一次链接完数据库之后都会在finally里把prep链接关闭。然后结合着jmap查看,果然,正如我所料。一切都是那么的好,那么的优秀,哎呀,困扰我3周的问题就这样解决了,我真是心情大好,也不知道怎么了,自己也工作了这么久,还是这么的……菜!!我真是有点悲哀啊!

废话不多说,也算是学习到了一点点的东西吧,让我在这条路上是铺砖添瓦了!

打完,收工!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值