现在正在做一个监控的工作,看似简单,但如果多想想还是有很多技巧和问题可以探讨的
需求场景:
- 客户端应该是一个静态类
- 客户端调用该类的记录信息API频度可能很大
- 该类记录信息的API应该是异步的,保证主体性能
- 能够提供多种记录的方式
- 能够记录多种数据方式
需求其实可以分为两部分:
- 对于需要记录的信息最终可能有多种形式来表达
- 使用什么方式(媒体)来表达,比如log,socket,或者消息系统
所以设计的时候,在最开始用Recorder和Out两个接口来表达。
其中Recorder中定义以下方法
/**
* 信息记录者借口
* @author dongxuan.lb
*
*/
public interface Recorder {
/**
* 记录信息
* @param keys
*/
void record(String... keys);
/**
* 该Recorder的名称
* @return
*/
String getName();
void setName(String name);
/**
* 将记录输出
* 同时清理内部数据
* 内部使用Out接口
*/
void free();
}
Out接口很简单:
/**
* 记录输出接口
* @author dongxuan.lb
*
*/
public interface Out {
void output(String info);
}
复杂的输出由具体的子类来完成。
到这里,这两个接口是完全解耦的,彼此没有什么关系。
========================================================================
到这里,可以开始设计具体的Recorder类了。(不同的业务需求可以自己实现Recorder)
这里需要具体化的需求:
写道
主体会接收到一个字符窜数组,不定长度
该API能够在一定时期后输出出现过的key以及该key的次数
比如A.record("a","a","b")
可能的结果是
a=2|b=1
当然这里record中的字符串长度不会非常大,通常小于100个,但是调用该api的频度非常大,可能在1000至10000
监控方面的设计,在使用API记录是不能同步阻塞住 主体业务,所以使用线程方式进行异步。
在这里使用了ThreadPoolExecutor作为作为线程池。
protected ThreadPoolExecutor recorderPool = new ThreadPoolExecutor(
coreSize, coreSize * 2, 30, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(60),
new RecorderThreadFactory("recorderPool"),
new ThreadPoolExecutor.CallerRunsPolicy());
这里需要注意的是coreSize和maxPoolSize的设置,当然这里也是可以调优的地方。
当然使用ThreadPoolExecutor最主要的是RejectedExecutionHandler的具体实现可以高度自由化
当核心处理不过来的时候可以选择自己实现的RejectedExecutionHandler,以满足业务需求
AbstractKeyCountRecorder中代码
private Integer coreSize = Runtime.getRuntime().availableProcessors();
/*
* 记录者线程池
*/
protected ThreadPoolExecutor recorderPool = new ThreadPoolExecutor(
coreSize, coreSize * 2, 30, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(60),
new RecorderThreadFactory("recorderPool"),
new ThreadPoolExecutor.CallerRunsPolicy());
protected abstract Runnable getWorker(String... key);
@Override
public void record(String... keys) {
recorderPool.execute(getWorker(keys));
}
========================================================================
回到具体需求上来。
首先为了记录key的次数,需要一个map来作为记录存数,其中map的K中存储key的名称,map的V中存储key的出现次数。
但这里有两个问题:
- 使用hashMap线程不安全,get和put方法均有可能出现并发问题,导致记录错误
- map中的V存在自加操作,在操作也会有线程问题
事实证明,
map的同步影响的是性能问题,而V得类型选择则非常影响最终结果的正确与否(当然背后还是同步问题)
========================================================================
map的同步选择:
- 选择hashtable
- 使用Collections.synchronizedMap()方式
- 使用ConcurrentHashMap
- 自己手动维护同步
在这里,不想过多介绍这个问题,不过比较奇怪的是,我测试下来,Collections.synchronizedMap()方式比较耗性能
最终为了方便,直接选择ConcurrentHashMap
========================================================================
这里需要重点指出的是,map中V的选型,通常就使用Integer就可以了,但是在这里,虽然map的put,get方法已经同步,但是当多个线程去取同一个V的值时可能看到的是一样的,这样当自加后在put进去,就丢掉了几次记录。
所以如果使用Integer作为计数器类,结果必然小了很多。
那么自然想到的便是AtomInteger类了。内部使用的机制比较复杂,在《java Thread》那本书上有提到过。
写道
private Map<String, AtomicInteger> hitMap = new ConcurrentHashMap<String, AtomicInteger>(1000);
========================================================================
之前说过,Recorder和Out很好的解耦了,到了具体的Recorder中,由传入的out负责具体的输出部分
外部注入out实体
public LevelKeyCountRecorder(Out out) {
this();
this.out = out;
}
当需要输出时调用Out的output方法
@Override
public void free() {
if(!hitMap.isEmpty()) {
StringBuilder value = new StringBuilder();
for (final Entry<String, AtomicInteger> entry : hitMap.entrySet()) {
value.append(
entry.getKey()
+ "="
+ entry.getValue()
+ "|");
}
out.output(value.toString());
hitMap.clear();
}
}
=======================================================================
最后 ,使用日志输出结果
Logger logger = Logger.getLogger(LevelKeyCountRecorder.class);
Out logOut = new LogOut(logger);
Recorder levelRecorder = new LevelKeyCountRecorder(logOut)
- 大小: 29.6 KB
分享到:
相关推荐
本文档主要介绍了多媒体行业质量监控的最佳实践,通过对当前主流客户质量监控体系模型的提炼,输出了客户端日志上报数据推荐、质量监控通用指标及报警方式建议。该文档可帮助相关业务同学更清晰了解媒体类客户质量...
它能有效监视、控制和记录内部电脑在互联网上的活动,实时记录局域网内计算机所有收发的邮件、浏览的网页以及FTP上传下载的文件,监视和管理网内用户的聊天行为,控制网内用户访问指定网络资源或网络协议。...
- **软件定位:** 网络视频监控软件-4000(v2.0)是一款专门为嵌入式网络硬盘录像机设计的客户端应用软件。它能够支持多种类型的网络视频设备,包括但不限于嵌入式网络硬盘录像机、网络视频服务器、IP Camera以及IP ...
- 用户可以选择登录模式:管理平台、控制客户端或配置客户端。 - 登录管理平台后,可以查看或发布公告、查看消息、查看报警和异常信息等。 **3.1.1 安装浏览器插件** 首次访问时,可能需要安装一个插件来支持特定...
在Windows操作系统中,记录登录客户端信息主要涉及到收集用户的登录时间、登录来源(IP地址)以及登录会话的状态等数据。这些信息对于跟踪用户行为、维护系统安全及合规性具有重要意义。 #### 二、基本命令行操作 ...
描述了视频监控界面的布局和各部分的功能。 4.1.2 实时视频播放 介绍了实时视频的监控和播放操作。 4.1.3 紧急录像 说明了紧急情况下的录像功能。 4.1.4 抓图 描述了如何在视频流中抓取静态图片。 4.1.5 云台控制 ...
【局域网监控系统概要设计说明书】 局域网监控系统是一款专为企事业单位设计的小型软件,旨在帮助管理者实时监测局域网内主机的活动。开发者宋钊通过本系统的设计说明书,为用户、开发人员和测试人员提供了详细的...
DSC(数据记录与监控)模块是LabVIEW中的一个功能扩展,它提供了一套工具,用于构建监控和数据采集系统或多通道数据记录应用程序。通过使用LabVIEW的DSC模块,开发者可以连接PLC(可编程逻辑控制器)与PAC(可编程...
远程监控系统设计中,GPRS网络是系统的关键组成部分,它将控制信息和反馈信息以IP数据包的形式通过Internet/GPRS网络进行传输,从而实现对终端设备的远程无线监控。 在本设计中,DTU(Data Transmission Unit,数据...
标题中的“老监控相机软解码客户端程序”指的是一个专门设计用于处理老款监控相机的软件,例如海康和大华等品牌的产品。这类客户端通常是为了在计算机或网络设备上接收并解码这些相机发送的视频流。由于是老款相机,...
`:silence => false`表示开启日志记录,如果设置为`true`则会关闭日志输出。 HttpLog库支持记录各种HTTP客户端库的请求,如Net::HTTP、HTTParty、Faraday等。当你使用这些库发起HTTP请求时,HttpLog会捕获请求的...
- **查看所有打印输出请求**:监控所有待处理的打印作业。 - **查看单个打印机的输出请求**:只查看某个特定打印机的输出请求列表。 #### 八、安全任务 - **角色与用户的关联**:为用户分配特定的角色。 - **用户...
文档《用Bginfo收集客户端信息,记录用户登录情况.pdf》是针对IT专业人员的一份实用指南,指导他们如何有效地使用Bginfo工具来收集客户端信息,并特别关注如何记录用户的登录情况,以便更好地管理和监控网络环境中的...
高清视频监控系统不仅能够对进出园区的人员、物资流动及周边环境进行实时监控,还能通过对生产区域、仓储、办公区等关键部位的视频监控和录像记录,协助进行生产调度、数据分析等工作,从而提高企业的整体运营效率。...
- **软件结构**:系统采用了C/S(安全、实时)和B/S(便利、广泛)相结合的系统构架,以C/S结构的网管监控客户端作为系统的主应用操作平台,B/S结构用于实时数据监控、视频监控、告警状态浏览监控平台。 - **采集...
总之,主机监控和容器监控是现代IT运维的关键组成部分,通过JSON格式的数据交换,我们可以获取到详尽的系统性能信息,进而实现高效管理和优化。在分析这些数据时,不仅要关注当前的资源使用情况,还需要结合历史数据...
综上所述,《监狱远程视频监控方案》旨在通过对监狱252间监室进行远程视频集中联网监控管理视频设计,实现监狱安全管理水平的全面提升。通过采用先进的视频监控技术和合理的系统设计,不仅可以提高监狱的安全防范...