Skywalking对应的ES历史数据不删除的问题

结论

原因1 配置问题 配置文件中的recordDataTTL、otherMetricsDataTTL配置不生效, 可以认为是bug
解决方案:方法1:手动设置minuteMetricsDataTTL、hourMetricsDataTTL 、dayMetricsDataTTL。recordData的删除会使用dayMetricsDataTTL配置的值。方法2:修改源码

原因2 Skywalking Bug skywalking-6.2.0如果设置了nameSpace 在删除index的时候有bug, 需要改源码重新编译
解决方案:方法1:把namespace设置为空。方法2:修改源码

环境

Skywalking版本:6.2.0
ES实例:4核 * 14G, 三台实例,基于docker起的
OAPServer:只有一台,1500M
agent节点:也就是JVM实例大概50个

解决过程

1. 配置问题

通过查看源码找到删除ES历史数据的核心代码,如下。先根据该model(如Segement ,各种Metrics)的Downsampling配置和DataTTLConfig计算出截止时间,小于该截止时间的index需要删除


image.png

DownSampling是一个枚举

public enum Downsampling {
    None(0, ""), Second(1, "second"), Minute(2, "minute"), Hour(3, "hour"), Day(4, "day"), Month(5, "month");

    private final int value;
    private final String name;

    Downsampling(int value, String name) {
        this.value = value;
        this.name = name;
    }

    public int getValue() {
        return value;
    }

    public String getName() {
        return name;
    }
}

DataTTLConfig就是配置各个类型过期时间的配置,record和metrics

@Setter
@Getter
public class DataTTLConfig {
    private int recordDataTTL;
    private int minuteMetricsDataTTL;
    private int hourMetricsDataTTL;
    private int dayMetricsDataTTL;
    private int monthMetricsDataTTL;
}

回过头看deleteHistory的逻辑,主要看一下计算截止时间timeBefore的逻辑,可以看到截止时间只与model的Downsampling和DataTTLConfig有关
StorageTTL的实现类为ElasticsearchStorageTTL, ElasticsearchStorageTTL的工作就是根据DownSampling返回对应的TTLCalculator。举例TTLCalculator的实现类EsMinuteTTLCalculator,可以看到会根据当前时间和DataTTLConfig的MinuteMetricsDataTTL配置计算时间,单位为 , 而EsHourTTLCalculator会使用DataTTLConfig的hourMetricsDataTTL计算时间,TTLCalculator与DataTTLConfig是有对应关系的

public class ElasticsearchStorageTTL implements StorageTTL {

    @Override public TTLCalculator calculator(Downsampling downsampling) {
        switch (downsampling) {
            case Month:
                return new MonthTTLCalculator();
            case Hour:
                return new EsHourTTLCalculator();
            case Minute:
                return new EsMinuteTTLCalculator();
            default:
                return new DayTTLCalculator();
        }
    }
}

public class EsMinuteTTLCalculator implements TTLCalculator {
    @Override public long timeBefore(DateTime currentTime, DataTTLConfig dataTTLConfig) {
        return Long.valueOf(currentTime.plusDays(0 - dataTTLConfig.getMinuteMetricsDataTTL()).toString("yyyyMMdd"));
    }
}

这里顺便说一下为什么recordDataTTL配置不会生效,Record类型的DownSampling为Second,但是从上面可以看到ElasticsearchStorageTTL中并没有case Second,所以遇到Second的话会返回DayTTLCalculator,而DayTTLCalculator使用的dataTTLConfig的DayMetricsDataTTL,recordDataTTL也就没有用了

Record类型的Model会使用Second类型的Downsmapling

接下来只用DataTTLConfig是如何获取到的就可以了,从上面的deleteHistory代码可以看到DataTTLConfig是从CoreModule的ConfigService中读取的,其实也就是从application.yml的core Module配置读取的,不过StorageModuleElasticsearchProvider在启动的时候会用StorageModuleElasticsearchConfig覆盖CoreModule中的DataTTLConfig

org.apache.skywalking.oap.server.storage.plugin.elasticsearch.StorageModuleElasticsearchProvider

private void overrideCoreModuleTTLConfig() {
        ConfigService configService = getManager().find(CoreModule.NAME).provider().getService(ConfigService.class);

        configService.getDataTTLConfig().setRecordDataTTL(config.getRecordDataTTL());
        configService.getDataTTLConfig().setMinuteMetricsDataTTL(config.getMinuteMetricsDataTTL());
        configService.getDataTTLConfig().setHourMetricsDataTTL(config.getHourMetricsDataTTL());
        configService.getDataTTLConfig().setDayMetricsDataTTL(config.getDayMetricsDataTTL());
        configService.getDataTTLConfig().setMonthMetricsDataTTL(config.getMonthMetricsDataTTL());
    }

看下配置StorageModuleElasticsearchConfig,我们主要看与otherMetricsDataTTL相关的配置,从下面的代码可以看到,作者是想在otherMetricsDataTTL被赋值的时候自动把minuteMetricsDataTTL、hourMetricsDataTTL 、dayMetricsDataTTL给赋值上。但是由于系统启动的时候是通过反射直接修改的Field,所以setOtherMetricsDataTTL方法并不会被触发,这也就是我们在配置文件中配置了otherMetricsDataTTL也不会生效的原因,系统只会用默认的2

@Getter
public class StorageModuleElasticsearchConfig extends ModuleConfig {
    @Setter private int recordDataTTL = 7;
    @Setter private int minuteMetricsDataTTL = 2;
    @Setter private int hourMetricsDataTTL = 2;
    @Setter private int dayMetricsDataTTL = 2;
    private int otherMetricsDataTTL = 0;
    @Setter private int monthMetricsDataTTL = 18;

    public void setOtherMetricsDataTTL(int otherMetricsDataTTL) {
        if (otherMetricsDataTTL > 0) {
            minuteMetricsDataTTL = otherMetricsDataTTL;
            hourMetricsDataTTL = otherMetricsDataTTL;
            dayMetricsDataTTL = otherMetricsDataTTL;
        }
    }
}

系统启动时通过反射赋值Config的相关代码

org.apache.skywalking.oap.server.library.module.ModuleDefine

private void copyProperties(ModuleConfig dest, Properties src, String moduleName,
        String providerName) throws IllegalAccessException {
        if (dest == null) {
            return;
        }
        Enumeration<?> propertyNames = src.propertyNames();
        while (propertyNames.hasMoreElements()) {
            String propertyName = (String)propertyNames.nextElement();
            Class<? extends ModuleConfig> destClass = dest.getClass();

            try {
                Field field = getDeclaredField(destClass, propertyName);
                field.setAccessible(true);
                field.set(dest, src.get(propertyName));
            } catch (NoSuchFieldException e) {
                logger.warn(propertyName + " setting is not supported in " + providerName + " provider of " + moduleName + " module");
            }
        }
    }
配置问题的解决方案

方法1:直接在配置文件中配置minuteMetricsDataTTL、hourMetricsDataTTL 、dayMetricsDataTTL参数,而不使用默认的otherMetricsDataTTL。recordData的删除会使用dayMetricsDataTTL配置的值

方法2:修改源码,手动调用一下setOtherMetricsDataTTL


image.png

2. 删除Index的bug问题

这个问题相对比较明显,从上面的deleteHistory中我们看到根据alias查询出index,然后判断时间过期的index会被调用删除逻辑,问题就出在deleteIndex的地方。如下可以看到在删除之前会在传入的indexName前面添加namespace,问题是此时传入的idnexName已经包含了Namespace信息了(是根据alias直接从es中查询出来的),再添加一次namespace就会导致找不到index,而导致删除index失败

public boolean deleteIndex(String indexName) throws IOException {
        indexName = formatIndexName(indexName);
        DeleteIndexRequest request = new DeleteIndexRequest(indexName);
        DeleteIndexResponse response;
        response = client.indices().delete(request);
        logger.debug("delete {} index finished, isAcknowledged: {}", indexName, response.isAcknowledged());
        return response.isAcknowledged();
    }

public String formatIndexName(String indexName) {
        if (StringUtils.isNotEmpty(namespace)) {
            return namespace + "_" + indexName;
        }
        return indexName;
    }

解决方案也很简单, 添加一个deleteIndexWithFullIndexName方法,这个地方直接调用deleteIndexWithFullIndexName即可

public boolean deleteIndex(String indexName) throws IOException {
        String fullIndexName = formatIndexName(indexName);
        return deleteIndexWithFullIndexName(fullIndexName);
    }

    public boolean deleteIndexWithFullIndexName(String fullIndexName) throws IOException {
        DeleteIndexRequest request = new DeleteIndexRequest(fullIndexName);
        DeleteIndexResponse response;
        response = client.indices().delete(request);
        logger.debug("delete {} index finished, isAcknowledged: {}", fullIndexName, response.isAcknowledged());
        return response.isAcknowledged();
    }
image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,874评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,102评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,676评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,911评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,937评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,935评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,860评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,660评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,113评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,363评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,506评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,238评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,861评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,486评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,674评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,513评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,426评论 2 352

推荐阅读更多精彩内容