网站域名怎么做杰恩设计网站是谁做的
news/
2025/10/4 22:12:48/
文章来源:
网站域名怎么做,杰恩设计网站是谁做的,公司做网站怎么收费,wordpress 模板标签JVM 案例
案例一#xff1a;服务器内存不足#xff0c;影响Java应用
问题#xff1a; 收到报警#xff0c;某Java应用集群中一台服务器可用内存不足#xff0c;超过报警阈值。 排查过程#xff1a; 首先#xff0c;通过Hickwall查看该应用各项指标#xff0c;发现无论…JVM 案例
案例一服务器内存不足影响Java应用
问题 收到报警某Java应用集群中一台服务器可用内存不足超过报警阈值。 排查过程 首先通过Hickwall查看该应用各项指标发现无论是请求数量、CPU使用率、还是JMX的各项指标均未发现异常。仅系统内存占用很高但是从JMX指标中看Java应用的Heap Memory、GC等都是正常的在合理大小和范围内未发现内存泄漏等问题。故怀疑不是Java应用本身的问题而是系统上其他组件出了问题但是从Hickwall等工具上又看不出其他组件的信息。然后直接ssh登录到该服务器由于是内存问题故直接使用简单的top命令根据内存占用排序后发现是logagent进程占用了接近一半的系统内存。
由于账号权限限制无法进一步处理诱因找到后随即反馈给网站运营中心的同事帮忙临时将logagent进程杀死系统恢复正常。后续经网站运营中心同事排查发现是logagent内部bug导致处理格式异常的日志文件时发生内存泄漏后续打上补丁进行修复。 问题原因及思考 目前公司各项监控工具已经比较完善开发人员应熟练掌握并了解其中各项指标的含义能够在分析具体问题时灵活运用各个工具快速定位解决问题。
同时本案例虽然不是业务系统的问题但这一案例也提醒了开发人员线上实际问题可能是各方各面的除了具备Java技术栈的相关的排障技能外同时也要有基本的Linux操作能力在已有工具无法帮助解决问题时多一种途径快速定位问题毕竟运营中心的同事人力有限可能无法及时提供支持。
扩展
Java Full GC频繁 可通过Hickwall中的JMX Full gc time/count指标观察Full GC情况正常情况下不应有Full GC出现Full GC意味着 STWJVM会阻塞其他所有线程来进行垃圾回收频繁的Full GC会严重影响应用的性能。如果出现Full GC通常意味着Java堆内存大小无法满足需求如果不是代码缺陷导致可通过以上OOM中JVM Sampler工具相关方法排查则需要增加堆内存大小。
大数据量处理
案例一大循环引起的 cpu 负载过高的问题
问题 x应用在一次发布时cpu出现负载过高其负载率突破200%并且响应时间也大幅度超时。 代码
ListCityDataModel cities cityDomainService.allCities();
for (CityDataModel city : cities) {if (city.getCityCode().equalsIgnoreCase(flight.getDepartCity())) {dCountry city.getCountryCode();}if (city.getCityCode().equalsIgnoreCase(flight.getArriveCity())) {aCountry city.getCountryCode();}
}通过在测试环境尝试调用一次服务请求发现其循环的数据是城市列表。该列表的长度达到12000而且发现该循环本身被执行了11次String::equalsIgnoreCase方法执行了18万次也就是说这是一个典型的大循环的代码。 并且通过记录日志发现在生产中该块代码平均每次请求都会调用24万次左右这导致很多cpu资源都集中在该方法上使得cpu load大幅度提高。
问题解决 由于代码中的大循环非常耗费cpu资源通过分析这里的Strings::equalsIgnoreCase方法的主要作用在于遍历判断取数据。 根据这种查找数据的情况优先选择使用HashMap替代用空间换时间经过修改后重新发布其cpu利用率明显下降恢复正常。
思考总结 【1】使用循环时需要特别注意大循环优先使用O(1)的HashMap大循环对于cpu性能的压榨在这个问题上表现地淋漓尽致。 【2】镜像机器由于是使用生产流量转发访问所以镜像发布高度贴近实际生产发布。在每次发布前先使用镜像机器预发布可以尽可能地将潜在的问题暴露出来。另外性能实验室中提供了cpu热点、内存分配热点和锁竞争热点的Flamegraph在预发布中遇到问题时也可以更加直观地帮忙解决问题并且不会对实际生产机器造成影响。 【3】此次发布前虽然在测试环境进行了压测但是并没有复现出该问题分析原因其与特定的压测的请求相关。由于在压测时使用的请求没有经过某些代码分支使得循环的次数相比较少故而在测试环境压测时没有暴露该问题。 【4】以上总结除了代码层面的使用注意外可以进行测试环境多种请求压力测试以及生产镜像机器预发布等手段来检测和杜绝这种潜在的问题发生。
案例二多层嵌套 map
问题 某日某查询服务器开始不断拉出集群造成线上订单下跌。 遇到问题需咨询解决。。。
缓存
案例一篡改缓存
问题 查询接口下发错误数据故障
故障描述 包含故障开始时间发现时间控制措施故障排除细节
TimeEvent15:00接到产品邮件告知下单调用查询接口的结果与前端的数据不一致要求紧急对问题进行排查。15:05开始对问题进行排查同时了解问题大概影响范围。16:00定位到是因为代码bug导致的接口在下发时输出的结果不正确。3月1日接口由.net切换到了java版查询接口。16:20开始着手对bug进行修复并进行紧急发布。16:20与产品沟通影响范围以及问题订单的处理办法。16:30确定影响的单量10万16:50着手准备修复问题订单SQL18:00完成紧急修复的上线
故障分析 【1】为什么接口会下发错误 .Net接口转Java过程中引发的代码bug修改了本地缓存对象。
【2】为什么这个错误在代码review中没有被发现 代码review不充分。虽然接口的逻辑并不复杂但是代码量较多40个文件2000 additions and 1000 deletions在review过程中遗漏了该错误。
【3】为什么在测试过程中没有发现该bug? 测试不充分同时这个bug的触发存在一定概率性当多个订单引用同一个基础服务对象时在对礼盒进行遍历计算时最后一个订单的计算结果会覆盖前面所有引用了该基础服务对象的订单。如果测试时选择的订单没有触发该·bug··.Net·和·Java·版本的对比结果是一致的。
【4】为什么影响的单量达·10W·以上规模 该bug从2月12日发布直到3月3日才发现持续了22天。
【5】为什么从2月12日起该问题直到3月3日才发现 目前对于这类问题缺乏有效的检测机制只能被动的等待客户投诉发生后才会反馈到开发团队。
分析总结 【1】通过以上故障示例我们可以发现缓存被修改带来的影响通常具有以下特性 ■ 不容易发现因为数据可能只在特定条件下被修改。 ■ 影响面非常广因为数据本身是被频繁使用才会被加入缓存。 ■ 不确定性因为数据被修改具有“随机性”该特性导致影响范围难以确定数据也难以清洗。 【2】缓存篡改通常如何发生 ■ 从缓冲获取一个对象引用后续过程中修改了该对象的内部成员。
public class CityCache {private static final CityCache INSTANCE new CityCache();private final MapString, City cityMap new HashMap();public static CityCache getInstance() {return INSTANCE;}private CityCache() {// 此处为了简便没有写定时刷新loadDataFromDB();}public City getCityByCode(String cityCode) {return cityMap.get(cityCode);}private void loadDataFromDB() {// load cities from database and put them into cityMap}
}Data
public class City {public City() {}public City(String code, int id) {this.code code;this.id id;}private String code;private int id;
}Test
public void errorTest() {// 通过SHA获取到缓存实体该实体的三字码与SHA相同City city1 CityCache.getInstance().getCityByCode(SHA);assertTrue(SHA.equals(city1.getCode()));// 业务代码直接修改了city1的三字码CityCache中的实体被修改city1.setCode(BJS);// ...// 再次通过SHA获取到缓存实体该实体的三字码与SHA不相同了非期望值City city2 CityCache.getInstance().getCityByCode(SHA);assertFalse(SHA.equals(city2.getCode()));
}Test
public void correctTest() {// 通过SHA获取到缓存实体该实体的三字码与SHA相同City city1 CityCache.getInstance().getCityByCode(SHA);assertTrue(SHA.equals(city1.getCode()));// 业务代码不能直接修改缓存实体正确做法是先Copy一个对象修改Copy对象的属性后续业务使用该Copy对象City cityCopy new City(city1.getCode(), city1.getId());cityCopy.setCode(BJS);// ...// 通过SHA获取到缓存实体该实体的三字码与SHA相同City city2 CityCache.getInstance().getCityByCode(SHA);assertTrue(SHA.equals(city2.getCode()));
}■ 从缓冲获取一个集合引用后续过程中往该集合中添加/删除了元素。public class CityCache {private static final CityCache INSTANCE new CityCache();Getterprivate final MapString, City cityMap new HashMap();public static CityCache getInstance() {return INSTANCE;}private CityCache() {// // 此处为了简便没有写定时刷新loadDataFromDB();}private void loadDataFromDB() {// load cities from database and put them into cityMap}
}Data
public class City {public City() {}public City(String code, int id) {this.code code;this.id id;}private String code;private int id;
}Test
public void errorTest() {MapString, City cityMap CityCache.getInstance().getCityMap();// 通过SHA获取到缓存实体该实体的三字码与SHA相同City city1 cityMap.get(SHA);assertTrue(SHA.equals(city1.getCode()));// 业务代码直接修改缓存集合cityMap.put(SHA, new City(BJS, 2));// cityMap.remove(SHA);// 再次通过SHA获取到缓存实体该实体的三字码与SHA不相同了非期望值City city2 CityCache.getInstance().getCityMap().get(SHA);assertFalse(SHA.equals(city2.getCode()));
}■ 缓存实体被修改public class CityCache {private static final CityCache INSTANCE new CityCache();Getterprivate final MapString, City cityMap new HashMap();public static CityCache getInstance() {return INSTANCE;}private CityCache() {// // 此处为了简便没有写定时刷新loadDataFromDB();}private void loadDataFromDB() {// load cities from database and put them into cityMap}
}Data
public class City {public City() {}public City(String code, int id) {this.code code;this.id id;}private String code;private int id;
}Test
public void errorTest() {MapString, City cityMap CityCache.getInstance().getCityMap();// 通过SHA获取到缓存实体该实体的三字码与SHA相同City city1 cityMap.get(SHA);assertTrue(SHA.equals(city1.getCode()));// 运行期间非预期的修改了缓存集合中的对象cityMap.forEach((k, v) - {if (!SHA.equals(k)) {return;}// ...v.setCode(BJS);});// 再次通过SHA获取到缓存实体该实体的三字码与SHA不相同了非期望值City city2 CityCache.getInstance().getCityMap().get(SHA);assertFalse(SHA.equals(city2.getCode()));
}【3】如何避免缓存篡改 ■ 在可能需要修改数据的场景从缓存获取一个深拷贝对象/集合。 ■ 将缓存对象设计为只读状态确保一旦构建就不可再修改其内部数据。
多线程
多线程这个话题想必开发人员或多或少都会接触到。 使用多线程最主要的原因是提高系统的资源利用率。 但在使用的过程中可能会遇到各种各样的问题死循环便是其中比较棘手的一类。 下文分析了多线程环境下的死循环场景希望对大家有所帮助。
死循环危害 程序进入假死状态 当某个请求导致死循环该请求会在很大一段时间内都无法获取接口的返回。
CPU 使用率飙升 代码出现死循环后由于没有休眠一直不断抢占cpu资源导致cpu长时间处于繁忙状态必定会使cpu使用率飙升。
内存使用率飙升 代码出现死循环时循环体内有大量创建对象的逻辑垃圾回收器无法及时回收会导致内存使用率飙升。同时如果垃圾回收器频繁回收对象也会造成cpu使用率飙升。
StackOverflowError栈溢出 在一些递归调用的场景如果出现死循环多次循环后最终会报 StackOverflowError 栈溢出程序直接挂掉。
案例一多线程环境下的死循环案例
问题 循环条件不正确 案例 这里以二分查找为例
int search(ListInteger nums, int target) {int l 0, r nums.size() - 1;while (l r) {int mid (l r) / 2;if (nums.get(mid) target)r mid - 1;else// 可能出问题位置l mid;}if (nums.get(l) target)return l;elsereturn -1;
}首先会不会产生死循环的关键是l和r是否在每次循环后至少有一个的值发生了改变 而while循环体中若走入了else语句l的值有可能不发生变化就会导致死循环的产生。 可以对循环体做以下调整
while (l r) {int mid (l r) / 2;if (nums.get(mid) target)r mid;elsel mid 1;
}案例二flag 线程间不可见
有时候我们的代码需要一直做某件事情直到某个条件达到有个状态告诉它要终止任务了它就会自动退出。 这时候很多人都会想到用while(flag)实现这个功能
public class FlagTest {private boolean flag true;public void setFlag(boolean flag) {this.flag flag;}public void fun() {while (flag) {}System.out.println(done);}public static void main(String[] args) throws InterruptedException {final FlagTest flagTest new FlagTest();new Thread(() - flagTest.fun()).start();Thread.sleep(200);flagTest.setFlag(false);}
}这段代码在子线程中执行无限循环当主线程休眠200毫秒后将flag变成false这时子线程就会自动退出了。想法是好的但是实际上这段代码进入了死循环不会因为flag变成false而自动退出。 为什么会这样 线程间flag是不可见的这时如果flag加上了volatile关键字变成
private volatile boolean flag true; 会强制把共享内存中的值刷新到主内存中让多个线程间可见程序可以正常退出。
案例三HashMap JDK7/8 死循环
问题 JDK7 rehash(扩容)时和JDK8链表更改为红黑树时。链接
案例四自己手动写死循环
定时任务比如有个需求要求每隔5分钟从远程拉取数据覆盖本地数据。 这时候如果你不想用其他的定时任务框架可以实现一个简单的定时任务具体代码如下
public static void sync() {new Thread(() - {while (true) {try {System.out.println(sync data);Thread.sleep(1000 * 60 * 5);} catch (Exception e) {log.error(e);}}}).start();
}其实很多JDK中的定时任务比如Timer类的底层也是用了while(true)的无限循环也就是死循环来实现的。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/927605.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!