内容简介:主机状态一直显示有问题,去向动态链接库请求数据时,除了第一台主机访问成功外,以后的每一台主机返回的结果都是研究了很久也没研究明白,最后求助潘老师。
问题描述
主机状态一直显示有问题,去向动态链接库请求数据时,除了第一台主机访问成功外,以后的每一台主机返回的结果都是 9(HOST_NOT_FOUND)
。
研究了很久也没研究明白,最后求助潘老师。
潘老师指出是指针有问题,主机的指针是我们构造出来的,虽然该指针指向对象的 name
和 context
与动态链接库服务那边的都一样,但是他那里可能是按地址处理的,不是同一个地址,就报主机找不到了。
经过测试,确实是这样。
不能直接构造指针,需要使用同步计算机数据时返回的指针进行操作。
所以,获取计算机状态,操作计算机都需要重新同步一下计算机,将指针同步过来。
假设用户操作很频繁的话,对动态链接库的压力就很大。指不定啥时候就炸了。
虽然我想到了这点,但也没想到好的解决方案。
潘老师最终的设计方案非常好,采用定时任务,当有计算机的操作时,不实时进行操作,而是先存起来,每隔一段时间统一进行操作,从而减轻服务器压力。
实现
设计
对主机进行关机或重启时,不立即执行,而是将其添加到一个要执行的任务列表中,当定时任务触发后,再统一执行。
定时任务
定时任务很简单,之前在计量中写过一个每天晚上定时统计数据的定时任务,这次写这个没什么难度,都不需要看文档了。
注释很详尽,相信聪明的你完全可以理解。
这里的存储计算机状态设置了一个主机名到计算机状态映射的 HashMap
,这里没有用 ConcurrentHashMap
,因为只有定时任务一个线程进行 put
,其他接口调用该 Map
只负责查询,不会出现冲突。
@Async @Scheduled(fixedRate = 10000) // 每隔10s执行 public void hostHandle() { logger.info("--- 开始执行定时任务 ---"); logger.debug("获取关机重启的订阅者"); Set<String> shutdownSubscribers = this.cloneStringSetAndClear(hostService.getShutdownSubscribers()); Set<String> rebootSubscribers = this.cloneStringSetAndClear(hostService.getRebootSubscribers()); logger.debug("获取主机结构体指针Map"); List<HostStruct.ByReference> byReferenceList = baseService.getHostStructReferenceList(); Map<String, HostStruct.ByReference> byReferenceMap = baseService.getHostStructReferenceMap(byReferenceList); if (!shutdownSubscribers.isEmpty()) { logger.info("存在关机订阅,执行关机操作"); for (String name : shutdownSubscribers) { logger.debug("获取结构体指针并关机"); HostStruct.ByReference byReference = byReferenceMap.get(name); baseService.shutdown(byReference); } } if (!rebootSubscribers.isEmpty()) { logger.info("存在重启订阅,执行重启操作"); for (String name : rebootSubscribers) { logger.debug("获取结构体指针并重启"); HostStruct.ByReference byReference = byReferenceMap.get(name); baseService.reboot(byReference); } } logger.debug("查询主机列表"); for (HostStruct.ByReference byReference : byReferenceList) { logger.debug("查询主机指针,同时获取主机信息"); Integer status = baseService.getHostStatus(byReference); logger.debug("添加到Map中"); hostService.getHostStatusMap().put(Native.toString(byReference.name), status); } logger.info("--- 定时任务执行完毕 ---"); } /** * 克隆字符串集合并清空原集合 * @param primarySet 原集合 * @return 克隆的字符串集合 */ private Set<String> cloneStringSetAndClear(Set<String> primarySet) { logger.debug("新建集合"); Set<String> set = new HashSet<>(primarySet); logger.debug("清空原集合"); primarySet.clear(); logger.debug("返回"); return set; }
todo
目前是用 Set
存储要操作的主机,但是经过查询, HashSet
、 LinkedHashSet
、 TreeSet
都是线程不安全的。
这里就怕执行定时任务的时候,突然来了一个关机的指令,两个线程同时访问 Set
,定时任务要克隆一个 Set
然后把这个清空,关机需要在 Set
中添加元素,两个线程如果交替执行,结果就很难说了。
去 concurrent
包下找,也没找到合适的。看了看,有第三方库实现的线程安全的 Set
,以后引入进来。
这里不知道是不是我用的有问题,是并发场景下不推荐用 Set
吗?为什么 concurrent
包下没有相关的实现类?
总结
感叹一句: C++
还是难啊!
C++
老师对我的评价是字写得还不错,哈哈哈。佩服 C++
工程师!
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
计算机程序设计艺术(第1卷)
[美] Donald E. Knuth / 清华大学出版社 / 2002-9 / 80.00元
第1卷首先介绍编程的基本概念和技术,然后详细讲解信息结构方面的内容,包括信息在计算机内部的表示方法、数据元素之间的结构关系,以及有效的信息处理方法。此外,书中还描述了编程在模拟、数值方法、符号计算、软件与系统设计等方面的初级应用。此第3版增加了数十项简单但重要的算法和技术,并根据当前研究发展趋势在数学预备知识方面做了大量修改。一起来看看 《计算机程序设计艺术(第1卷)》 这本书的介绍吧!