美文网首页
剑走偏锋:使用阿里云SLS日志服务实现类似prometheus+

剑走偏锋:使用阿里云SLS日志服务实现类似prometheus+

作者: epetAPI | 来源:发表于2020-05-21 23:04 被阅读0次

    欢迎关注我的github,以后所有文章源码都会陆续更新上去

    随着微服务的流行,势必线上服务数量会越来越多,对每一个服务的管控也变得越来越繁琐,一个可视化的系统资源/性能监控成为刚需。通常我们都会选择一些开源的很常见的产品:prometheus+grafana几乎是一种默认选择,实际使用下来个人感觉确实也是体验最好的。
    不过我司在去年未部署这一套方案前,JAVA团队已经有迫切需要可视化监控和报警的需求(JVM内存是否设置合理,GC花费时间到底有多少,线程池大小和队列是否够用,数据库连接池是否高效,hystrix是否触发熔断等等),没有可视化,全都是靠猜。而正好我们有使用阿里云的SLS日志服务产品,对其有一定程度的了解,加上本身也算是一种时序性数据解决方案,特别适合做系统监控。此篇文章只适用于已经使用阿里云SLS日志服务的团队作为另外一种实现思路的参考,通常我还是会推荐prometheus+grafana。

    认识SLS

    详细的介绍建议大家直接阅读官方文档,这里只做以下四点说明

    1. 日志内容 完整metric日志内容(还有一些日志本身附加很有用的信息),以及丰富的字段索引设置

      image.png
    2. 查询语法 非常丰富简单的类SQL的语法,用于筛选符合条件的日志内容

      image.png
    3. 分析语法 大量的分析语法和函数,用得上的用不上的都有(甚至还包括了机器学习语法和函数)。。,主要是用于对筛选出来的日志进行二次处理

      image.png
    image.png
    1. 可视化图表和告警 这是我们最需要的,默认支持的已经覆盖我们目前的应用场景了,后面会有真实线上服务可视化监控截图
      image.png

    micrometer

    1. micrometer是一个非常短小精悍的基于JAVA实现的系统指标监控底层组件,spring cloud metric默认就是使用micrometer,官方也提供了很多市面上流行的监控系统实现方案(可以看到图片里圈红的influx和prometheus),那么我们要做的就是模仿实现一套基于阿里云SLS的解决方案

      image.png
    2. meter 主要就是以下6种类型

      image.png

    SlsMeter

    重头戏来了,要想实现类似prometheus时序性数据收集功能,那么我得把各种类型的meter数据记录在内存中后,定期隔间时间推送给SLS日志服务器,然后通过查询和分析语法即可到我们的目的,总体架构图如下:


    image.png
    1. SlsMeter
    /**
     * sls基础计量类
     *
     * @author ty
     */
    public class SlsMeter {
        private final String name;
        private final Map<String, String> tags;
        private final String type;
        private final long time;
    
        public SlsMeter(String name, Map<String, String> tags, String type, long time) {
            this.name = name;
            this.tags = Collections.unmodifiableMap(tags);
            this.type = type;
            this.time = time;
        }
    
        public String getName() {
            return name;
        }
    
        public Map<String, String> getTags() {
            return tags;
        }
    
        public String getType() {
            return type;
        }
    
        public long getTime() {
            return time;
        }
    
        @Override
        public String toString() {
            return "SlsMeter{" +
                    "name='" + name + '\'' +
                    ", tags=" + tags +
                    ", type='" + type + '\'' +
                    ", time=" + time +
                    '}';
        }
    }
    
    • name 标记收集指标信息的唯一性,eg:jvm_memory_used,jvm_memory_max
    • tags 同一指标信息会有不同维度,特别适合分组统计,eg:id=>PS Eden Space,id=>PS Old Gen,通过tag就可以实现不同代内存的使用情况
    • type meter类型,对应micromerter的6种meter,只不过做了重新划分
    /**
     * 计量类型
     *
     * @author ty
     */
    public enum MetricType {
        /**
         * {@link io.micrometer.core.instrument.Counter} AND {@link io.micrometer.core.instrument.FunctionCounter}
         */
        COUNTER("counter"),
        /**
         * {@link io.micrometer.core.instrument.Gauge} AND {@link io.micrometer.core.instrument.TimeGauge}
         */
        GAUGE("gauge"),
        /**
         * {@link io.micrometer.core.instrument.Timer} AND {@link io.micrometer.core.instrument.FunctionTimer}
         * AND {@link io.micrometer.core.instrument.DistributionSummary}
         */
        HISTOGRAM("histogram"),
        /**
         * {@link io.micrometer.core.instrument.LongTaskTimer}
         */
        LONG_TASK_TIMER("long_task_timer"),
        /**
         * unknown
         */
        UNKNOWN("unknown");
        private final String type;
    
        MetricType(String type) {
            this.type = type;
        }
    
        public String getType() {
            return type;
        }
    }
    
    1. meter子类 全部继承SlsMeter这个基类,实现不同的值类型计算,这里只截取一部分代码,详细代码可以在我的codingman1990拉取
      image.png
    /**
     * counter
     *
     * @author ty
     */
    public class SlsCounter extends SlsMeter {
        private BigDecimal value;
    
        public SlsCounter(String name, Map<String, String> tags, String type, long time) {
            super(name, tags, type, time);
        }
    
        public BigDecimal getValue() {
            return value;
        }
    
        public void setValue(BigDecimal value) {
            this.value = value;
        }
    
        @Override
        public String toString() {
            return "SlsCounter{" +
                    super.toString() +
                    "value=" + value +
                    '}';
        }
    }
    
    /**
     * meter
     *
     * @author ty
     */
    public class SlsTimer extends SlsMeter {
        private BigDecimal sum;
        private long count;
        private BigDecimal mean;
        private BigDecimal upper;
    
        public SlsTimer(String name, Map<String, String> tags, String type, long time) {
            super(name, tags, type, time);
        }
    
        public BigDecimal getSum() {
            return sum;
        }
    
        public void setSum(BigDecimal sum) {
            this.sum = sum;
        }
    
        public long getCount() {
            return count;
        }
    
        public void setCount(long count) {
            this.count = count;
        }
    
        public BigDecimal getMean() {
            return mean;
        }
    
        public void setMean(BigDecimal mean) {
            this.mean = mean;
        }
    
        public BigDecimal getUpper() {
            return upper;
        }
    
        public void setUpper(BigDecimal upper) {
            this.upper = upper;
        }
    
        @Override
        public String toString() {
            return "SlsTimer{" +
                    super.toString() +
                    "sum=" + sum +
                    ", count=" + count +
                    ", mean=" + mean +
                    ", upper=" + upper +
                    '}';
        }
    }
    
    1. SlsMeterRegistry 基于SLS实现的各项指标数据注册器,也可理解为指标数据收集器,其实底层就是基于记录文本日志实现的,等待SLS客户端ilogtail收集上传到远端日志服务器。核心代码如下:
    /**
     * 阿里云日志服务meter采集
     *
     * @author ty
     */
    public class SlsMeterRegistry extends StepMeterRegistry {
        @Override
        protected void publish() {
            createLoggerIfNecessary();
            this.getMeters().forEach(meter -> {
                SlsMeter slsMeter;
                if (meter instanceof Counter) {
                    slsMeter = writeCounter((Counter) meter);
                } else if (meter instanceof FunctionCounter) {
                    slsMeter = writeCounter((FunctionCounter) meter);
                } else if (meter instanceof Gauge) {
                    slsMeter = writeGauge((Gauge) meter);
                } else if (meter instanceof Timer) {
                    slsMeter = writeTimer((Timer) meter);
                } else if (meter instanceof FunctionTimer) {
                    slsMeter = writeTimer((FunctionTimer) meter);
                } else if (meter instanceof DistributionSummary) {
                    slsMeter = writeDistributionSummary((DistributionSummary) meter);
                } else if (meter instanceof LongTaskTimer) {
                    slsMeter = writeLongTaskTimer((LongTaskTimer) meter);
                } else {
                    slsMeter = writeUnknownMeter(meter);
                }
                log(slsMeter);
            });
        }
    }
    

    再加上具体的每一个Meter读取转化为我们想要的数据格式


    image.png
    1. AutoConfiguration 使用spring boot永远少不了的自动配置,依靠配置文件即可自动开启该功能
    /**
     * sls集成micrometer自动配置
     *
     * @author ty
     */
    @Configuration
    @AutoConfigureBefore({CompositeMeterRegistryAutoConfiguration.class, SimpleMetricsExportAutoConfiguration.class})
    @AutoConfigureAfter(MetricsAutoConfiguration.class)
    @ConditionalOnBean(Clock.class)
    @ConditionalOnProperty(prefix = "management.metrics.export.sls", name = "enabled", havingValue = "true")
    @EnableConfigurationProperties(SlsProperties.class)
    public class SlsMetricsExportAutoConfiguration {
        @Bean
        @ConditionalOnMissingBean
        public SlsConfig slsConfig(SlsProperties slsProperties) {
            return new SlsPropertiesConfigAdapter(slsProperties);
        }
    
        @Bean
        @ConditionalOnMissingBean
        public SlsMeterRegistry slsMeterRegistry(SlsConfig slsConfig, Clock clock) {
            return new SlsMeterRegistry(slsConfig, clock);
        }
    }
    

    spring.factories

    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    com.epet.microservices.common.metrics.export.sls.SlsMetricsExportAutoConfiguration
    

    效果展示

    这里我把之前使用SLS实现的展示效果和现在使用Prometheus实现的效果放在一起对比(因为绝大部分系统已经迁移到prometheus,所以会有部分sls截图无数据),可以发现每一项功能都是可以实现的,不过确实grafana展示效果更炫。

    1. 监控总览
      image.png
      image.png
    1. JVM
      image.png
      image.png
    image.png
    image.png
    1. Tomcat
      image.png
    image.png
    1. ThreadPool
      image.png
    image.png
    1. HikariCP
      image.png
    image.png
    1. Hystrix
      image.png
    image.png

    结论

    基于阿里云SLS日志服务是完全可实现和prometheus+grafana一致的可视化系统监控功能,不过确实grafana看起来会更高大上一些,而且毕竟是开源,所以prometheus+grafana作为首选更合适。而文章提出的这种基于阿里云SLS日志服务实现的思路更适合一些本身已经在使用这个产品的团队,或者作为另外一种尝试的野路子。详细代码可移步我的github

    相关文章

      网友评论

          本文标题:剑走偏锋:使用阿里云SLS日志服务实现类似prometheus+

          本文链接:https://www.haomeiwen.com/subject/oclxahtx.html