当前位置: 首页 > news >正文

陕西交通建设集团西长分公司网站网站备案名称修改

陕西交通建设集团西长分公司网站,网站备案名称修改,九江集团网站建设,wordpress 数据库配置我们一个java服务上线后#xff0c;偶尔会发生内存OOM(Out Of Memory)问题#xff0c;但由于OOM导致服务不响应请求#xff0c;健康检查多次不通过#xff0c;最后部署平台kill了java进程#xff0c;这导致定位这次OOM问题也变得困难起来。 最终#xff0c;在多次review代…我们一个java服务上线后偶尔会发生内存OOM(Out Of Memory)问题但由于OOM导致服务不响应请求健康检查多次不通过最后部署平台kill了java进程这导致定位这次OOM问题也变得困难起来。 最终在多次review代码后发现是SQL意外地查出大量数据导致的如下 sql idconditionswhereif testouterId ! nulland outer_id #{outerId}/ifif testorderType ! null and orderType ! and order_type #{orderType}/if.../where /sqlselect idqueryListByConditions resultMaporderResultMapselect * from order include refidconditions/ /select查询逻辑类似上面的示例在Service层有个根据outer_id的查询方法然后直接调用了Mapper层一个通用查询方法queryListByConditions。 但我们有个调用量极低的场景可以不传outer_id这个参数导致这个通用查询方法没有添加这个过滤条件导致查了全表进而导致OOM问题。 我们内部对这个问题进行了复盘考虑到OOM问题还是蛮常见的所以给大家也分享下。 事前# 在OOM问题发生前为什么测试阶段没有发现问题 其实在编写技术方案时是有考虑到这个场景的但在提测时忘记和测试同学沟通此场景导致遗漏了此场景的测试验证。 关于测试用例不全面其实不管是疏忽问题、经验问题、质量意识问题或人手紧张问题从人的角度来说都很难彻底避免人没法像机器那样很听话的、不疏漏的执行任何指令。 既然人做不到那就让机器来做这就是单元测试、自动化测试的优势通过逐步积累测试用例可覆盖的场景就会越来越多。 当然实施单元测试等方案也会增加不少成本需要权衡质量与研发效率谁更重要毕竟在需求不能砍的情况下质量与效率的关系是得此失彼这是任何一本项目管理的书都提到过的。 事中# 在感知到OOM问题发生时由于进程被部署平台kill导致现场丢失难以快速定位到问题点。 一般java里面是推荐使用-XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath/home/dump/这种JVM参数来保存现场的这两个参数的意思是当JVM发生OOM异常时自动dump堆内存到文件中但在我们的场景中这个方案难以生效如下 在堆占满之前会发生很多次FGCjvm会尽最大努力腾挪空间导致还没有OOM时系统实际已经不响应了然后被kill了这种场景无dump文件生成。就算有时幸运JVM发生了OOM异常开始dump由于dump文件过大(我们约10G)导致dump文件还没保存完进程就被kill了这种场景dump文件不完整无法使用。 为了解决这个问题有如下2种方案 方案1利用k8s容器生命周期内的Hook# 我们部署平台是套壳k8s的k8s提供了preStop生命周期钩子在容器销毁前会先执行此钩子只要将jmap -dump命令放入preStop中就可以在k8s健康检查不通过并kill容器前将内存dump出来。 要注意的是正常发布也会调用此钩子需要想办法绕过我们的办法是将健康检查也做成脚本当不通过时创建一个临时文件然后在preStop脚本中判断存在此文件才dumppreStop脚本如下 if [ -f /tmp/health_check_failed ]; thenecho Health check failed, perform dumping and cleanups...;pidps h -o pid --sort-pmem -C java|head -n1|xargs;if [[ $pid ]]; thenjmap -dump:formatb,file/home/work/logs/applogs/heap.hprof $pidfi elseecho No health check failure detected. Exiting gracefully.; fi 注也可以考虑在堆占用高时才dump内存效果应该差不多。 方案2容器中挂脚本监控堆占用占用高时自动dump# #!/bin/bashwhile sleep 1; donow_time$(date %F_%H-%M-%S)pidps h -o pid --sort-pmem -C java|head -n1|xargs;[[ ! $pid ]] { unset n pre_fgc; sleep 1m; continue; }data$(jstat -gcutil $pid|awk NR1{print $4,$(NF-2)});read old fgc $data;echo $now_time: $old $fgc;if [[ $(echo $old|awk $180{print $0}) ]]; then(( n ))else(( n0 ))fiif [[ $n -ge 3 || $pre_fgc $fgc -gt $pre_fgc $n -ge 1 ]]; thenjstack $pid /home/dump/jstack-$now_time.log;if [[ $ ~ dump ]];thenjmap -dump:formatb,file/home/dump/heap-$now_time.hprof $pid;elsejmap -histo $pid /home/dump/histo-$now_time.log;fi{ unset n pre_fgc; sleep 1d; continue; }fipre_fgc$fgc done每秒检查老年代占用3次超过80%或发生一次FGC后还超过80%记录jstack、jmap数据此脚本保存为jvm_old_mon.sh文件。 然后在程序启动脚本中加入nohup bash jvm_old_mon.sh dump 即可添加dump参数时会执行jmap -dump导全部堆数据不添加时执行jmap -histo导对象分布情况。 事后# 为了避免同类OOM case再次发生可以对查询进行兜底在底层对查询SQL改写当发现查询没有limit时自动添加limit xxx避免查询大量数据。 优点对数据库友好查询数据量少。 缺点添加limit后可能会导致查询漏数据或使得本来会OOM异常的程序添加limit后正常返回并执行了后面意外的处理。 我们使用了Druid连接池使用Druid Filter实现的话大致如下 public class SqlLimitFilter extends FilterAdapter {// 匹配limit 100或limit 100,100private static final Pattern HAS_LIMIT_PAT Pattern.compile(LIMIT\\s[\\d?](\\s*,\\s*[\\d?])?\\s*$, Pattern.CASE_INSENSITIVE);private static final int MAX_ALLOW_ROWS 20000;/*** 若查询语句没有limit自动加limit* return 新sql*/private String rewriteSql(String sql) {String trimSql StringUtils.stripToEmpty(sql);// 不是查询sql不重写if (!StringUtils.lowerCase(trimSql).startsWith(select)) {return sql;}// 去掉尾部分号boolean hasSemicolon false;if (trimSql.endsWith(;)) {hasSemicolon true;trimSql trimSql.substring(0, trimSql.length() - 1);}// 还包含分号说明是多条sql不重写if (trimSql.contains(;)) {return sql;}// 有limit语句不重写int idx StringUtils.lowerCase(trimSql).indexOf(limit);if (idx -1 HAS_LIMIT_PAT.matcher(trimSql.substring(idx)).find()) {return sql;}StringBuilder sqlSb new StringBuilder();sqlSb.append(trimSql).append( LIMIT ).append(MAX_ALLOW_ROWS);if (hasSemicolon) {sqlSb.append(;);}return sqlSb.toString();}Overridepublic PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql)throws SQLException {String newSql rewriteSql(sql);return super.connection_prepareStatement(chain, connection, newSql);}//...此处省略了其它重载方法 }本来还想过一种方案使用MySQL的流式查询并拦截jdbc层ResultSet.next()方法在此方法调用超过指定次数时抛异常但最终发现MySQL驱动在ResultSet.close()方法调用时还是会读取剩余未读数据查询没法提前终止故放弃之。
http://www.hkea.cn/news/14531479/

相关文章:

  • 观光园网站建设关于建设公司网站的申请
  • 做网站的服务器有什么作用音乐网站界面
  • 现在企业做网站一般用什么框架导航类网站怎么做
  • 学院网站群建设方案网站建设是什么意思
  • 中国建设银行保函查询网站做网站第一
  • 阜阳网站是体育设施建设发布有没有网站
  • 网站页面上的悬浮窗怎么做做网站管理怎么赚钱
  • 闵行广州网站建设网站怎么做子网页
  • 请人做网站需要注意什么条件宜宾网站制作公司
  • 大渡口集团网站建设网站关键词长尾词
  • 男女上做床全播放网站任丘住房建设局网站
  • 学而思最早是做网站的吗华中农业大学基因编辑在线设计网站
  • 网站直播软件开发电子化业务管理与网站建设
  • 建立网站需要多少钱多少钱28湖南岚鸿口碑营销是什么
  • 入境游旅游网站建设球队排名世界
  • 柳州公司网站建设北京公司的网站建设
  • 宁波网站推广优化公司电话深圳网络推广招聘
  • 志愿者网站 建设方案大型门户网站
  • 广州营销网站建设设计广告片制作公司
  • 网站排名提升工具离石古楼角网站建设
  • 怎么做贷款网站网站做管制户外刀具
  • 移动网站设计上机考试济宁网站建设500元
  • 论述农产品电商网站建设怎么做微信推广和宣传
  • 网站被黑咋样的怎样做网站卖网站
  • 微型购物网站建设模板宁波学校网站建设
  • 松滋网站开发广州优秀网站设计
  • 空间设计公司百度做网站优化多少钱一年
  • 环保网站可以做哪些方面有没有做兼职的网站吗
  • 有经验的中山网站建设crm系统功能模块
  • 做网站大连各种购物网站大全