当前位置: 首页 > 知识库问答 >
问题:

OpenHFT/历史记录映射失败

赵飞雨
2023-03-14

我使用一个VanillaChroncile临时存储和检索条目,除了有巨大的负载外,它工作得非常好。我得到地图失败异常。虽然我有处理此异常的恢复逻辑,但我想知道为什么首先会出现此异常。任何帮助都将不胜感激。

     public enum PreAuthEventChronicle {
INSTANCE;
private String basePath = PropertyUtilsEnum.INSTANCE.getChronicleDirPath();
private final Logger logger = Logger.getLogger(PreAuthEventChronicle.class);
private long indexBlockSize = 64L;
// Length of the excerpt.
private final int excerptLength = 1024;
private final int cycleLength = "yyyyMMddhhmmss";
// Number of entries that are stored in the chronicle queue.
private final long entriesPerCycle = 1L << 20;
// Format for the folder. Chronicle writes in GMT time zone.
private final String format = ApplicationConstants.CHRONICLE_FORMAT;
private Chronicle chronicle = null;
private List<PreAuthEventListener> listeners = new      ArrayList<PreAuthEventListener>();

public Chronicle getChr() {
    return chronicle;
}

/**
 * There can only be one chronicle built.
 */
private PreAuthEventChronicle() {
    if (basePath != null) {
        if (!basePath.endsWith(ApplicationConstants.FILE_SEP)) {
            basePath = basePath + ApplicationConstants.FILE_SEP + ApplicationConstants.CHRONICLE_DATA_PATH;
        }
        logger.debug("Starting from a clean state");
        cleanUp();
        logger.debug("Building a Vanilla Chronicle instance with path: " + basePath);
        buildChronicle();
    } else {
        throw new RuntimeException("No directory specified for chronicle to be built.");
    }
}

private void buildChronicle() {
    logger.debug("Begin-Starting to build a vanilla chronicle");
    try {
        if (chronicle != null) {
            chronicle.clear();
            chronicle = null;
        }
        chronicle = ChronicleQueueBuilder.vanilla(basePath).cycleLength(cycleLength, false).cycleFormat(format)
                .indexBlockSize(indexBlockSize).entriesPerCycle(entriesPerCycle).build();
    } catch (IOException e) {
        logger.error("Error building chronicle" + e.getMessage());
    }
    logger.debug("End-Finished building the vanilla chronicle");
}

/**
 * Clean up the resources
 */
public void cleanUp() {
    logger.debug("Begin-Cleaning up chronicle resources");
    File f = new File(basePath);
    if (f.exists() && f.isDirectory()) {
        File[] dirs = f.listFiles();
        for (File dir : dirs) {
            if (dir.isDirectory()) {
                try {
                    FileUtils.deleteDirectory(dir);
                } catch (IOException ignore) {
                }
            }
        }
    }
    buildChronicle();
    logger.debug("End-Done cleaning up chronicle resources");
}

/**
 * Write the object to the chronicle queue, and notify the listeners
 * 
 * @param event
 * @throws IOException
 */
public synchronized void writeObject(Object event) throws IOException {
    ExcerptAppender appender = INSTANCE.getChr().createAppender();
    if (appender != null && event != null) {
        logger.debug("Begin-Writing event to the chronicle queue");
        appender.startExcerpt(excerptLength);
        appender.writeObject(event);
        appender.finish();
        appender.clear();
        appender.close();
        notifyListeners();
        logger.debug("End-Done writing event to the chronicle queue.");
    }
}

/**
 * Read the object from the queue
 * 
 * @return
 * @throws IOException
 */
public synchronized Object readObject() throws IOException {
    ExcerptTailer reader = INSTANCE.getChr().createTailer().toStart();
    Object evt = null;
    while (reader != null && reader.nextIndex()) {
        logger.debug("Begin-Reading event from the chronicle queue");
        evt = reader.readObject();
        reader.finish();
        reader.clear();
        reader.close();
        logger.debug("End-Done reading the event from the chronicle queue.");
    }
    return evt;
}

/**
 * Attach a listener
 * 
 * @param listen
 */
public void attachListener(PreAuthEventListener listen) {
    listeners.add(listen);
}

/**
 * Notify the listeners that an event has been written.
 */
private void notifyListeners() {
    for (PreAuthEventListener listener : listeners) {
        logger.debug("Notification received from the chronicle queue. Performing action.");
        listener.perform();
    }
}

}

共有1个答案

闻人河
2023-03-14

了解您得到的异常情况会很有用,但我敢打赌原因是OutOfMemoryError。

关于您的代码:

  • 你想要滚动每一秒,这是可能的,但不是真正有效的每个滚动,Chronicle-Queue需要mmap至少两个区域
  • readObject/WriteObject是不需要的同步方法,因为Va nillaChronque是线程安全的
  • 在readObject中,你关闭了每个循环中的尾轮,这可能会导致映射区域在每次迭代中被取消映射/映射,最好在循环之外调用关闭()
  • 在WriteObject中,你显式地关闭摘录,如果你不能控制调用该方法的线程数量,这是可以的,但这可能不是最有效的方法,因为每个新线程都必须映射一个新区域
  • 不需要调用[ailer|appender]. Clear()
 类似资料:
  • 读取播放历史信息 调用地址 http://api.bilibili.cn/history 返回 返回值字段 字段类型 字段说明 results int 返回的记录总数目 list object 返回数据 返回字段 “list” 子项 返回值字段 字段类型 字段说明 aid int 视频编号 typeid int 视频分类ID typename string 视频分类名称 title string

  • 历史记录 控制台维护 Elasticsearch 成功执行的最后500个请求列表。点击窗口右上角的时钟图标即可查看历史记录。这个图标会打开历史记录面板,您可以在其中查看历史请求。您也可以在这里选择一个请求,它将被添加到编辑器中当前光标所在的位置。 图 9. 历史记录面板

  • 3.3.1.1. 同步的文件历史记录 微力同步记录对文件的添加,修改、删除的操作记录,通过历史记录列表可查看时间时间及发生设备,如下: 事件时间,显示添加、修改、删除等操作发生的时间; 文件时间,显示该文件的最后修改时间; 操作类型,显示此次针对该文件所进行的操作的类型; 发生设备,显示进行此操作的设备名称; 目录,显示该文件所属同步目录; 清空历史记录,点击后可清除所有记录,此操作仅清除记录而已

  • 入口: 在路线规划右上角,有历史记录入口,无论“单路线规划”、“多路线规划”的结果,都会自动进行记录,点击进入该界面 在“路线规划”模块下展开二级模块“历史记录”,可以点击进入 历史记录列表 支持按照时间搜索记录 支持单个删除记录 支持一键删除全部记录 支持点击查看规划历史详情 历史详情 记录规划人、规划时间、规划结果 结果详情界面回放、支持点击查看

  • 我尝试用values.NewHeapInstance创建value对象,但失败了,出现错误: 文档中说Byte[]和ByteBuffer是开箱即用的,但是我找不到一个实用的例子,所以决定在这里询问一下。

  • 可确认下载失败或无法与互联网连接时等,最新的10件错误历史记录。 轻触列表的错误项目,会显示详细内容。部分项目还可确认建议解决方法。