QC的试验告一段落,现在准备开发仪器监控和仪器控制,最终把QC传输数据采用接口传。前期准备好了监听程序和TCP设备的基础程序,现在需要做仪器数据监控界面。对于连设备有个说重要也不重要,说不重要缺了又很难受的功能,就是传入日志记录(Trace)。
这个信息的特点是:
1.数据量大
2.没必要长久保存
3.没必要大量保存
4.要能查最近的
所以这数据用表存储就太浪费空间了。用表存储固定数量、多了删也会因为数据量大产生大量表日志。所以表不太合适。那么为了这东西引入Radis环境也不值得,所以基于Queue定制了可本地化的队列来给Trace用。
先实现Trace对象
package JRT.Core.Debug; import JRT.Core.MultiPlatform.JRTContext; import java.io.*; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedDeque; /** * 供仪器等调试用的日志队列,仪器日志数据存数据库太多了,也没有必要,存内存队列又没有持久化,封装定时持久化的TraceQueue给仪器做Trace用 */ public class TraceQueue { /** * 跟踪队列 */ private ConcurrentLinkedDequetraceQueue = new ConcurrentLinkedDeque(); /** * 唯一标识 */ private String key; /** * 本地名称 */ private String localName; /** * 最大数量 */ public int MaxSize = 50000; /** * 构造函数 * * @param queueKey 唯一键 * @param maxSize 最大大小 * @throws Exception */ public TraceQueue(String queueKey, int maxSize) throws Exception { key = queueKey; String fileName = Paths.get(JRTContext.WebBasePath, "trace").toString(); File dir = new File(fileName); if (!dir.exists()) { dir.mkdir(); } fileName = Paths.get(fileName, key + ".queue").toString(); localName = fileName; File localFile = new File(localName); //从本地加载数据 if (localFile.exists()) { traceQueue = DeserializeDeque(localName); } } /** * 往队列尾部加入数据 * * @param str */ public void AddLast(String str) { traceQueue.addLast(str); //数量大于最大就丢弃之前的 if (traceQueue.size() > MaxSize) { traceQueue.poll(); } } /** * 清空队列 */ public void Clear() { traceQueue.clear(); } /** * 保存到本地 */ public void Save() throws Exception { SerializeDeque(traceQueue, localName); } /** * 序列化队列到本地文件 * * @param deque 队列 * @param fileName 文件名称 * @throws IOException */ private void SerializeDeque(ConcurrentLinkedDeque deque, String fileName) throws IOException { //将Deque内容转换为ArrayList以便序列化 ArrayList list = new ArrayList<>(deque); try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName))) { oos.writeObject(list); } } /** * 从本地文件反序列化文件到队列 * * @param fileName * @return 队列 * @throws IOException * @throws ClassNotFoundException */ private ConcurrentLinkedDeque DeserializeDeque(String fileName) throws IOException, ClassNotFoundException { // 从文件反序列化ArrayList try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName))) { @SuppressWarnings("unchecked") ArrayList list = (ArrayList ) ois.readObject(); //将ArrayList内容转换回Deque ConcurrentLinkedDeque deque = new ConcurrentLinkedDeque<>(list); return deque; } } }
再提供Manager
package JRT.Core.Debug; import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import JRT.Core.Debug.TraceQueue; /** * 跟踪管理器,仪器Trace通过GetTraceHandler得到Trace句柄,定时器通过SaveAllTraceQueue定时写文件,网站结束时候写文件 */ public class TraceManager { /** * 所有的日志队列 */ private static ConcurrentHashMapallTrace = new ConcurrentHashMap<>(); /** * 得到Trace句柄 * * @param key 唯一键 * @param maxSize 最大大小 * @return Trace句柄 */ public static TraceQueue GetTraceHandler(String key, int maxSize) throws Exception { if (allTrace.containsKey(key)) { return allTrace.get(key); } else { TraceQueue one = new TraceQueue(key, maxSize); allTrace.put(key, one); return one; } } /** * 保存所有的跟踪队列 */ public static void SaveAllTraceQueue() { Iterator > iterator = allTrace.entrySet().iterator(); while (iterator.hasNext()) { ConcurrentHashMap.Entry entry = iterator.next(); try { entry.getValue().Save(); } catch (Exception ex) { JRT.Core.Util.LogUtils.WriteExceptionLog("保存TraceQueue异常", ex); } } } }
使用方式
测试Trace
import JRT.Core.Debug.TraceManager; import JRT.Core.Debug.TraceQueue; import JRTBLLBase.BaseHttpHandlerNoSession; import JRTBLLBase.Helper; /** * 测试Trace */ public class ashTraceTest extends BaseHttpHandlerNoSession { /** * 测试 * @return */ public String Test() throws Exception { //得到Trace句柄 TraceQueue trace= TraceManager.GetTraceHandler("1-trace",2000); for(int i=0;i<1;i++) { trace.AddLast("M->H:"+Helper.GetNowTimeStr()+" 第"+(i+1)+"条日志"); //Thread.currentThread().sleep(200); } //trace.Clear(); trace.Save(); return "共"+trace.GetTraceDataSize()+"条日志,"+Helper.Object2Json(trace.GetTraceData()); } }
可以准备开始仪器数据监控了
还没有评论,来说两句吧...