内容简介:主机状态一直显示有问题,去向动态链接库请求数据时,除了第一台主机访问成功外,以后的每一台主机返回的结果都是研究了很久也没研究明白,最后求助潘老师。
问题描述
主机状态一直显示有问题,去向动态链接库请求数据时,除了第一台主机访问成功外,以后的每一台主机返回的结果都是 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++
工程师!
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web Data Mining
Bing Liu / Springer / 2006-12-28 / USD 59.95
Web mining aims to discover useful information and knowledge from the Web hyperlink structure, page contents, and usage data. Although Web mining uses many conventional data mining techniques, it is n......一起来看看 《Web Data Mining》 这本书的介绍吧!