springboot+RabbitMQ+InfluxDB+Grafara监控实践

本文需要有相关spring boot 或spring cloud 相关微服务框架的基础,如果您具备相关基础可以很容易的实现下述过程!!!!!!! 希望

本文的所说对需要的您有所帮助

从这里我们开始进入闲聊阶段。

大家都知道 spring boot整合了很多很多的第三方框架,我们这里就简单讨论和使用 性能监控和JVM监控相关的东西。其他的本文不讨论虽然有些关联,所以开篇有说需要有相关spring boot框架基础说了这么多废话,下面真正进入主题。

这里首先给大家看下整体的数据流程图,其中两条主线一条是接口或方法性能监控数据收集,还有一条是spring boot 微服务JVM相关指标数据采集,最后都汇总到InfluxDB时序数据库中在用数据展示工具Grafara进行数据展示或报警。

〇、基础服务

基础服务比较多,其中包括RabbitMQ,Eureka注册中心,influxDB,Grafara(不知道这些东西 请百度或谷歌一下了解相关知识),下面简单说下各基础服务的功能:

RabbitMQ 一款很流行的消息中间件,主要用它来收集spring boot应用监控性能相关信息,为什么是RabbitMQ而不是什么别的 kafka等等,因为测试方便性能也够用,spring boot整合的够完善。

Eureka 注册中心,一般看过或用过spring cloud相关框架的都知道spring cloud注册中心主要推荐使用Eureka!至于为什么不做过多讨论不是本文主要讨论的关注点。本文主要用来同步和获取注册到注册中心的应用的相关信息。

InfluxDB和Grafara为什么选这两个,其他方案如 ElasticSearch 、Logstash 、Kibana,ELK的组合等!原因很显然 influxDB是时序数据库数据的压缩比率比其他(ElasticSearch )好的很多(当然本人没有实际测试过都是看一些文档)。同时InfluxDB使用SQL非常类似mysql等关系型数据库入门方便,Grafara工具可预警。等等!!!!!!!!!!!

好了工具就简单介绍到这里,至于这些工具怎么部署搭建请搭建先自行找资料学习,还是因为不是本文重点介绍的内容,不深入讨论。如果有docker相关基础的童鞋可以直接下载个镜像启动起来做测试使用(本人就是使用docker启动的上面的基础应用(Eureka除外))

一、被监控的应用

这里不多说被监控应用肯定是spring boot项目但是要引用一下相关包和相关注解以及修改相关配置文件

包引用,这些包是必须引用的

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
     <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-hystrix</artifactId>
    </dependency>

简单说下呢相关包的功能spring-cloud-starter-netflix-eureka-client用于注册中心使用的包,spring-cloud-starter-stream-rabbit 发送RabbitMQ相关包,spring-boot-starter-actuator发布监控相关rest接口包,

spring-cloud-starter-hystrix熔断性能监控相关包。

相关注解

@EnableHystrix//开启性能监控
@RefreshScope//刷新配置文件 与本章无关
@EnableAutoConfiguration
@EnableFeignClients//RPC调用与本章无关
@RestController
@SpringBootApplication
public class ServerTestApplication {
  protected final static Logger logger = LoggerFactory.getLogger(ServerTestApplication.class);

  public static void main(String[] args) {
    SpringApplication.run(ServerTestApplication.class, args);
  }
}

配置文件相关

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000
hystrix.threadpool.default.coreSize: 100
spring:
 application:
  name: spring-cloud-server2-test
 rabbitmq:
  host: 10.10.12.21
  port: 5672
  username: user
  password: password

encrypt:
 failOnError: false
server:
 port: 8081
eureka:
 instance:
  appname: spring-cloud-server2-test
  prefer-ip-address: true
 client:
  serviceUrl:
   defaultZone: http://IP:PORT/eureka/#注册中心地址
  eureka-server-total-connections-per-host: 500
endpoints:
 refresh:
  sensitive: false
 metrics:
  sensitive: false
 dump:
  sensitive: false
 auditevents:
  sensitive: false
 features:
  sensitive: false
 mappings:
  sensitive: false
 trace:
  sensitive: false
 autoconfig:
  sensitive: false
 loggers:
  sensitive: false

简单解释一下endpoints下面相关配置,主要就是 原来这些路径是需要授权访问的,通过配置让这些路径接口不再是敏感的需要授权访问的接口这应我们就可以轻松的访问注册到注册中心的每个服务的响应的接口。这里插一句接口性能需要在方法上面加上如下类似相关注解,然后才会有相关性能数据输出

@Value("${name}")
  private String name;

  @HystrixCommand(commandProperties = {
      @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "20000") }, threadPoolProperties = {
          @HystrixProperty(name = "coreSize", value = "64") }, threadPoolKey = "test1")
  @GetMapping("/testpro1")
  public String getStringtest1(){

    return name;
  }

好了到这里你的应用基本上就具备相关性能输出的能力了。你可以访问

如果是上图的接口 你的应用基本OK,为什么是基本因为你截图没有体现性能信息发送RabbitMQ的相关信息。这个需要看日志,加入你失败了评论区在讨论。我们先关注主线。

好的spring boot 应用就先说道这里。开始下一主题

二、性能指标数据采集

刚才访问http://IP:port/hystrix.stream这个显示出来的信息就是借口或方法性能相关信息的输出,如果上面都没有问题的话数据应该发送到了RabbitMQ上面了我们直接去RabbitMQ上面接收相关数据就可以了。

性能指标数据的采集服务主要应用以下包

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.github.miwurster/spring-data-influxdb -->
    <dependency>
      <groupId>org.influxdb</groupId>
      <artifactId>influxdb-java</artifactId>
      <version>2.8</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-autoconfigure</artifactId>
    </dependency>

直接贴代码

package application;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 *
 * @author zyg
 *
 */
@SpringBootApplication
public class RabbitMQApplication {

  public static void main(String[] args) {
    SpringApplication.run(RabbitMQApplication.class, args);
  }

}
package application;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;  

/**
 *
 * @author zyg
 *
 */
@Configuration
public class RabbitMQConfig {
  public final static String QUEUE_NAME = "spring-boot-queue";
  public final static String EXCHANGE_NAME = "springCloudHystrixStream";
  public final static String ROUTING_KEY = "#";

  // 创建队列
  @Bean
  public Queue queue() {
    return new Queue(QUEUE_NAME);
  }

  // 创建一个 topic 类型的交换器
  @Bean
  public TopicExchange exchange() {
    return new TopicExchange(EXCHANGE_NAME);
  }

  // 使用路由键(routingKey)把队列(Queue)绑定到交换器(Exchange)
  @Bean
  public Binding binding(Queue queue, TopicExchange exchange) {
    return BindingBuilder.bind(queue).to(exchange).with(ROUTING_KEY);
  }

  @Bean
  public ConnectionFactory connectionFactory() {
    //rabbitmq IP 端口号
    CachingConnectionFactory connectionFactory = new CachingConnectionFactory("IP", 5672);
    connectionFactory.setUsername("user");
    connectionFactory.setPassword("password");
    return connectionFactory;
  }

  @Bean
  public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
    return new RabbitTemplate(connectionFactory);
  }
}
package application;

import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.influxdb.InfluxDB;
import org.influxdb.InfluxDBFactory;
import org.influxdb.dto.Point;
import org.influxdb.dto.Point.Builder;
import org.influxdb.dto.Query;
import org.influxdb.dto.QueryResult;

/**
 *
 * @author zyg
 *
 */
public class InfluxDBConnect {
  private String username;// 用户名
  private String password;// 密码
  private String openurl;// 连接地址
  private String database;// 数据库

  private InfluxDB influxDB;

  public InfluxDBConnect(String username, String password, String openurl, String database) {
    this.username = username;
    this.password = password;
    this.openurl = openurl;
    this.database = database;
  }

  /** 连接时序数据库;获得InfluxDB **/
  public InfluxDB influxDbBuild() {
    if (influxDB == null) {
      influxDB = InfluxDBFactory.connect(openurl, username, password);
      influxDB.createDatabase(database);

    }
    return influxDB;
  }

  /**
   * 设置数据保存策略 defalut 策略名 /database 数据库名/ 30d 数据保存时限30天/ 1 副本个数为1/ 结尾DEFAULT
   * 表示 设为默认的策略
   */
  public void createRetentionPolicy() {
    String command = String.format("CREATE RETENTION POLICY \"%s\" ON \"%s\" DURATION %s REPLICATION %s DEFAULT",
        "defalut", database, "30d", 1);
    this.query(command);
  }

  /**
   * 查询
   *
   * @param command
   *      查询语句
   * @return
   */
  public QueryResult query(String command) {
    return influxDB.query(new Query(command, database));
  }

  /**
   * 插入
   *
   * @param measurement
   *      表
   * @param tags
   *      标签
   * @param fields
   *      字段
   */
  public void insert(String measurement, Map<String, String> tags, Map<String, Object> fields) {
    Builder builder = Point.measurement(measurement);
    builder.time(((long)fields.get("currentTime"))*1000000, TimeUnit.NANOSECONDS);
    builder.tag(tags);
    builder.fields(fields);
    //
    influxDB.write(database, "", builder.build());
  }

  /**
   * 删除
   *
   * @param command
   *      删除语句
   * @return 返回错误信息
   */
  public String deleteMeasurementData(String command) {
    QueryResult result = influxDB.query(new Query(command, database));
    return result.getError();
  }

  /**
   * 创建数据库
   *
   * @param dbName
   */
  public void createDB(String dbName) {
    influxDB.createDatabase(dbName);
  }

  /**
   * 删除数据库
   *
   * @param dbName
   */
  public void deleteDB(String dbName) {
    influxDB.deleteDatabase(dbName);
  }

  public String getUsername() {
    return username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  public String getPassword() {
    return password;
  }

  public void setPassword(String password) {
    this.password = password;
  }

  public String getOpenurl() {
    return openurl;
  }

  public void setOpenurl(String openurl) {
    this.openurl = openurl;
  }

  public void setDatabase(String database) {
    this.database = database;
  }
}
package application;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 *
 * @author zyg
 *
 */
@Configuration
public class InfluxDBConfiguration {

  private String username = "admin";//用户名
  private String password = "admin";//密码
  private String openurl = "http://IP:8086";//InfluxDB连接地址
  private String database = "test_db";//数据库

  @Bean
  public InfluxDBConnect getInfluxDBConnect(){
    InfluxDBConnect influxDB = new InfluxDBConnect(username, password, openurl, database);

    influxDB.influxDbBuild();

    influxDB.createRetentionPolicy();
    return influxDB;
  }
}
package application;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.fasterxml.jackson.databind.ObjectMapper;

/**
 *
 * @author zyg
 *
 */
@Component
public class Consumer {
  protected final static Logger logger = LoggerFactory.getLogger(Consumer.class);

  private ObjectMapper objectMapper = new ObjectMapper();

  @Autowired
  private InfluxDBConnect influxDB;

  @RabbitListener(queues = RabbitMQConfig.QUEUE_NAME)
  public void sendToSubject(org.springframework.amqp.core.Message message) {

    String payload = new String(message.getBody());
    logger.info(payload);

    if (payload.startsWith("\"")) {
      // Legacy payload from an Angel client
      payload = payload.substring(1, payload.length() - 1);
      payload = payload.replace("\\\"", "\"");
    }
    try {
      if (payload.startsWith("[")) {
        @SuppressWarnings("unchecked")
        List<Map<String, Object>> list = this.objectMapper.readValue(payload, List.class);
        for (Map<String, Object> map : list) {
          sendMap(map);
        }
      } else {
        @SuppressWarnings("unchecked")
        Map<String, Object> map = this.objectMapper.readValue(payload, Map.class);
        sendMap(map);
      }
    } catch (IOException ex) {
      logger.error("Error receiving hystrix stream payload: " + payload, ex);
    }
  }

  private void sendMap(Map<String, Object> map) {
    Map<String, Object> data = getPayloadData(map);
    data.remove("latencyExecute");
    data.remove("latencyTotal");
    Map<String, String> tags = new HashMap<String, String>();

    tags.put("type", data.get("type").toString());
    tags.put("name", data.get("name").toString());
    tags.put("instanceId", data.get("instanceId").toString());
    //tags.put("group", data.get("group").toString());

    influxDB.insert("testaaa", tags, data);

    // for (String key : data.keySet()) {
    // logger.info("{}:{}",key,data.get(key));
    // }

  }

  public static Map<String, Object> getPayloadData(Map<String, Object> jsonMap) {
    @SuppressWarnings("unchecked")
    Map<String, Object> origin = (Map<String, Object>) jsonMap.get("origin");
    String instanceId = null;
    if (origin.containsKey("id")) {
      instanceId = origin.get("host") + ":" + origin.get("id").toString();
    }
    if (!StringUtils.hasText(instanceId)) {
      // TODO: instanceid template
      instanceId = origin.get("serviceId") + ":" + origin.get("host") + ":" + origin.get("port");
    }
    @SuppressWarnings("unchecked")
    Map<String, Object> data = (Map<String, Object>) jsonMap.get("data");
    data.put("instanceId", instanceId);
    return data;
  }

}

这里不多说,就是接收RabbitMQ信息然后保存到InfluxDB数据库中。

三、JVM相关数据采集

JVM相关数据采集非常简单主要思想就是定时轮训被监控服务的接口地址然后把返回信息插入到InfluxDB中

服务引用的包不多说这个服务是需要注册到注册中心Eureka中的因为需要获取所有服务的监控信息。

插入InfluxDB代码和上面基本类似只不过多了一个批量插入方法

package com.zjs.collection;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
 *
 * @author zyg
 *
 */
@EnableEurekaClient
@SpringBootApplication
public class ApplictionCollection
{
  public static void main(String[] args) {
    SpringApplication.run(ApplictionCollection.class, args);
  }
}
/**
   * 批量插入
   *
   * @param measurement
   *      表
   * @param tags
   *      标签
   * @param fields
   *      字段
   */
  public void batchinsert(String measurement, Map<String, String> tags, List<Map<String, Object>> fieldslist) {
    org.influxdb.dto.BatchPoints.Builder batchbuilder=BatchPoints.database(database);

    for (Map<String, Object> map : fieldslist) {
      Builder builder = Point.measurement(measurement);
      tags.put("instanceId", map.get("instanceId").toString());
      builder.time((long)map.get("currentTime"), TimeUnit.NANOSECONDS);
      builder.tag(tags);
      builder.fields(map);
      batchbuilder.point(builder.build());
    }

    System.out.println(batchbuilder.build().toString());

    influxDB.write(batchbuilder.build());
  }
package com.zjs.collection;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

/**
 * 获取微服务实例
 *
 * @author zyg
 *
 */
@Component
@SpringBootApplication
@EnableScheduling
public class MicServerInstanceInfoHandle {

  protected final static Logger logger = LoggerFactory.getLogger(MicServerInstanceInfoHandle.class);

  final String pathtail = "/metrics/mem.*|heap.*|threads.*|gc.*|nonheap.*|classes.*";

  Map<String, String> tags;

  ThreadPoolExecutor threadpool;

  @Autowired
  DiscoveryClient dc;

  @Autowired
  RestTemplate restTemplate;

  final static LinkedBlockingQueue<Map<String, Object>> jsonMetrics = new LinkedBlockingQueue<>(1000);

  /**
   * 初始化实例 可以吧相关参数设置到配置文件
   */
  public MicServerInstanceInfoHandle() {

    tags = new HashMap<String, String>();
    threadpool = new ThreadPoolExecutor(4, 20, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100));

  }

  @Autowired
  private InfluxDBConnect influxDB;

  /**
   * metrics数据获取
   */
  @Scheduled(fixedDelay = 2000)
  public void metricsDataObtain() {
    logger.info("开始获取metrics数据");
    List<String> servicelist = dc.getServices();
    for (String str : servicelist) {

      List<ServiceInstance> silist = dc.getInstances(str);

      for (ServiceInstance serviceInstance : silist) {
        threadpool.execute(new MetricsHandle(serviceInstance));
      }
    }
  }

  /**
   * 将数据插入到influxdb数据库
   */
  @Scheduled(fixedDelay = 5000)
  public void metricsDataToInfluxDB() {
    logger.info("开始批量将metrics数据insert-influxdb");
    ArrayList<Map<String, Object>> metricslist = new ArrayList<>();
    MicServerInstanceInfoHandle.jsonMetrics.drainTo(metricslist);

    if (!metricslist.isEmpty()) {
      logger.info("批量插入条数:{}", metricslist.size());
      influxDB.batchinsert("metrics", tags, metricslist);
    }

    logger.info("结束批量metrics数据insert");
  }

  @Bean
  public RestTemplate getRestTemplate() {
    RestTemplate restTemplate = new RestTemplate();
    SimpleClientHttpRequestFactory achrf = new SimpleClientHttpRequestFactory();
    achrf.setConnectTimeout(10000);
    achrf.setReadTimeout(10000);
    restTemplate.setRequestFactory(achrf);
    return restTemplate;

  }

  class MetricsHandle extends Thread {

    private ServiceInstance serviceInstanc;

    public MetricsHandle(ServiceInstance serviceInstance){
      serviceInstanc=serviceInstance;
    }

    @Override
    public void run() {

      try {

        logger.info("获取 {}:{}:{} 应用metrics数据",serviceInstanc.getServiceId(),serviceInstanc.getHost(),serviceInstanc.getPort());

        @SuppressWarnings("unchecked")
        Map<String, Object> mapdata = restTemplate
            .getForObject(serviceInstanc.getUri().toString() + pathtail, Map.class);
        mapdata.put("instanceId", serviceInstanc.getServiceId() + ":" + serviceInstanc.getHost() + ":"
            + serviceInstanc.getPort());
        mapdata.put("type", "metrics");
        mapdata.put("currentTime", System.currentTimeMillis() * 1000000);
        MicServerInstanceInfoHandle.jsonMetrics.add(mapdata);

      } catch (Exception e) {
        logger.error("instanceId:{},host:{},port:{},path:{},exception:{}", serviceInstanc.getServiceId(),
            serviceInstanc.getHost(), serviceInstanc.getPort(), serviceInstanc.getUri(),
            e.getMessage());
      }
    }
  }

}

这里简单解释一下这句代码 final String pathtail = "/metrics/mem.*|heap.*|threads.*|gc.*|nonheap.*|classes.*"; ,metrics这个路径下的信息很多但是我们不是都需要所以我们需要有选择的获取这样节省流量和时间。上面关键类MicServerInstanceInfoHandle做了一个多线程访问主要应对注册中心有成百上千个服务的时候单线程可能轮序不过来,同时做了一个队列缓冲,批量插入到InfluxDB。

四、结果展示

如果你数据采集成功了就可以绘制出来上面的图形下面是对应的sql

SELECT mean("rollingCountFallbackSuccess"), mean("rollingCountSuccess") FROM "testaaa" WHERE ("instanceId" = 'IP:spring-cloud-server1-test:8082' AND "type" = 'HystrixCommand') AND $timeFilter GROUP BY time($__interval) fill(null)

SELECT mean("currentPoolSize") FROM "testaaa" WHERE ("type" = 'HystrixThreadPool' AND "instanceId" = '10.10.12.51:spring-cloud-server1-test:8082') AND $timeFilter GROUP BY time($__interval) fill(null)
SELECT "heap", "heap.committed", "heap.used", "mem", "mem.free", "nonheap", "nonheap.committed", "nonheap.used" FROM "metrics" WHERE ("instanceId" = 'SPRING-CLOUD-SERVER1-TEST:10.10.12.51:8082') AND $timeFilter

好了到这里就基本结束了。

五、优化及设想

上面的基础服务肯定都是需要高可用的,毋庸置疑都是需要学习的。如果有时间我也会向大家一一介绍,大家亦可以去搜索相关资料查看!

可能有人问有一个叫telegraf的小插件直接就能收集相关数据进行聚合结果监控,

其实我之前也是使用的telegraf这个小工具但是发现一个问题,

就是每次被监控的应用重启的时候相关字段名就会变,

因为他采集使用的是类实例的名字作为字段名,这应我们会很不方便,每次重启应用我们都要重新设置sql语句这样非常不友好,

再次感觉收集数据编码难度不大所以自己就写了收集数据的代码!如果有哪位大神对telegraf比较了解可以解决上面我说的问题记得给我留言哦!在这里先感谢!

有些地方是需要优化的,比如一些IP端口什么的都是可以放到配置文件里面的。

六、总结

从spring boot到现在短短的2、3年时间就迅速变得火爆,知识体系也变得完善,开发成本越来越低,

所以普及程度就越来越高,微服务虽然很好但是我们也要很好的善于运用,监控就是重要的一环,

试想一下你的机房运行着成千上万的服务,稳定运行和及时发现有问题的服务是多么重要的一件事情!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • ASP.NET Core2读写InfluxDB时序数据库的方法教程

    前言 在我们很多应用中会遇到有一种基于一系列时间的数据需要处理,通过时间的顺序可以将这些数据点连成线,再通过数据统计后可以做成多纬度的报表,也可通过机器学习来实现数据的预测告警.而时序数据库就是用于存放管理这种有着时间顺序数据的,时序数据库一般都支持时序数据的快速写入.持久化.多纬度的聚合查询等基本功能. InfluxDB简介 InfluxDB是一个基于时间序列数据而开发的高性能数据存储平台,它可以对时序数据进行高吞吐量的摄取.压缩和实时查询.InfluxDB是用Go语言编写的,它会编译成一个没

  • python+influxdb+shell编写区域网络状况表

    本文为大家分享了python+influxdb+shell写一个区域网络状况表,供大家参考,具体内容如下 shell脚本部分: ex:就是ping 各个目的ip10个包,然后获取丢包率和平均延迟时间,在Linux上设置为定时任务,每分钟执行一次.他会把数据写到influxdb服务器上面去,表示hk_vnloss和hk_vn01rtt,字段是loss和rtt,其他各区域的都是类似. python代码部分: 1.在Django项目的setting里面,配置influxdb数据库连接: ALLOWED

  • java使用influxDB数据库的详细代码

    本文实例为大家分享了java使用influxDB数据库的具体代码,供大家参考,具体内容如下 1.pom.xml中导入jar包依赖 <!-- 引入influxdb依赖 --> <dependency> <groupId>org.influxdb</groupId> <artifactId>influxdb-java</artifactId> <version>2.5</version> </dependen

  • Node.js 使用axios读写influxDB的方法示例

    Node.js读写数据到influxDB,目前已经有一个库node-influx, 这个库功能非常强大,但是我个人使用这个库的时候,遇到无法解决的问题. 使用curl都可以写数据到influxDB,但是用node-influx总是报错,搞了半天也无法解决,就索性不用它了. influxDB提供HTTP的API,也就是说Node.js中的axios或者request等HTTP客户端工具是可以直接和influx交互的. 需要注意的一点是,写到influxDB的数据格式必须是二进制流. 为此,要做两件

  • springboot+RabbitMQ+InfluxDB+Grafara监控实践

    本文需要有相关spring boot 或spring cloud 相关微服务框架的基础,如果您具备相关基础可以很容易的实现下述过程!!!!!!! 希望 本文的所说对需要的您有所帮助 从这里我们开始进入闲聊阶段. 大家都知道 spring boot整合了很多很多的第三方框架,我们这里就简单讨论和使用 性能监控和JVM监控相关的东西.其他的本文不讨论虽然有些关联,所以开篇有说需要有相关spring boot框架基础说了这么多废话,下面真正进入主题. 这里首先给大家看下整体的数据流程图,其中两条主线一

  • 一文搞懂并学会使用SpringBoot的Actuator运行状态监控组件的详细教程

    目录闲言碎语:背景Actuator介绍Rest方法来查看Actuatorpom.xml引入Actuator依赖配置application.yml运行项目Actuator配合SpringBootSecurity配置application.xml运行项目配置关闭项目API端口配置application.yml命令行执行post关闭指令附:Actuator端口信息附:SpringBoot自带的健康指示器赠言 闲言碎语:   最近刷抖音,看到了星爷的很多电影,感叹星爷给后世留下了很多的经典作品,我就在想

  • springboot + rabbitmq 如何实现消息确认机制(踩坑经验)

    本文收录在个人博客:www.chengxy-nds.top,技术资源共享,一起进步 最近部门号召大伙多组织一些技术分享会,说是要活跃公司的技术氛围,但早就看穿一切的我知道,这 T M 就是为了刷KPI.不过,话说回来这的确是件好事,与其开那些没味的扯皮会,多做技术交流还是很有助于个人成长的. 于是乎我主动报名参加了分享,咳咳咳~ ,真的不是为了那点KPI,就是想和大伙一起学习学习! 这次我分享的是 springboot + rabbitmq 如何实现消息确认机制,以及在实际开发中的一点踩坑经验,

  • SpringBoot+RabbitMQ方式收发消息的实现示例

    本篇会和SpringBoot做整合,采用自动配置的方式进行开发,我们只需要声明RabbitMQ地址就可以了,关于各种创建连接关闭连接的事都由Spring帮我们了~ 交给Spring帮我们管理连接可以让我们专注于业务逻辑,就像声明式事务一样易用,方便又高效. 祝有好收获,先赞后看,快乐无限. 本文代码:   https://gitee.com/he-erduo/spring-boot-learning-demo https://github.com/he-erduo/spring-boot-lea

  • Prometheus 入门教程之SpringBoot 实现自定义指标监控

    上篇文章我们已经可以在 Grafana 上看到对应的 SpringBoot 应用信息了,通过这些信息我们可以对 SpringBoot 应用有更全面的监控.但是如果我们需要对一些业务指标做监控,我们应该怎么做呢?这篇文章就带你一步步实现一个模拟的订单业务指标监控. 假设我们有一个订单系统,我们需要监控它的实时订单总额.10 分钟内的下单失败率.请求失败数.那么我们应该怎么做呢? 添加业务监控指标 在 spring-web-prometheus-demo 项目的基础上,我们添加一个 Promethe

  • Springboot+rabbitmq实现延时队列的两种方式

    什么是延时队列,延时队列应用于什么场景 延时队列顾名思义,即放置在该队列里面的消息是不需要立即消费的,而是等待一段时间之后取出消费. 那么,为什么需要延迟消费呢?我们来看以下的场景 网上商城下订单后30分钟后没有完成支付,取消订单(如:淘宝.去哪儿网) 系统创建了预约之后,需要在预约时间到达前一小时提醒被预约的双方参会 系统中的业务失败之后,需要重试 这些场景都非常常见,我们可以思考,比如第二个需求,系统创建了预约之后,需要在预约时间到达前一小时提醒被预约的双方参会.那么一天之中肯定是会有很多个

  • springboot Actuator的指标监控可视化功能详解

    springboot为我们提供了丰富的指标监控功能SpringBoot Actuator SpringBoot Actuator是springboot为简化我们对微服务项目的监控功能抽取出来的模块,使得我们每个微服务快速引用即可获得生产界别的应用监控.审计等功能. 后序文章会更新使用 我们先来看看怎么可视化 我们可以通过github上的开源项目 这里 我们创建一个springboot项目 作为可视化的服务端 使用新功能首先都是引入依赖 需要web项目 <dependency> <grou

  • SpringBoot集成内存数据库hsqldb的实践

    目录 目标 为什么 操作步骤 工程截图 运行 效果 总结 目标 在SpringBoot中集成内存数据库hsqldb. 为什么 像H2.hsqldb.derby.sqlite这样的内存数据库,小巧可爱,做小型服务端演示程序,非常好用.最大特点就是不需要你另外安装一个数据库. 操作步骤 修改pom.xml文件 <dependency> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId&

  • SpringBoot集成内存数据库Sqlite的实践

    目录 目标 为什么 操作步骤 工程截图 运行 效果 完整源代码 目标 在SpringBoot中集成内存数据库Sqlite. 为什么 像H2.hsqldb.derby.sqlite这样的内存数据库,小巧可爱,做小型服务端演示程序,非常好用.最大特点就是不需要你另外安装一个数据库. 操作步骤 1.修改pom.xml文件 <dependency> <groupId>org.xerial</groupId> <artifactId>sqlite-jdbc</a

  • 手把手带你掌握SpringBoot RabbitMQ延迟队列

    目录 1. 简介 2. 安装插件 3. 实现延迟队列 3.1 引入所需依赖 3.2 application.yaml 3.3 RabbitConfig 3.4 Producer 3.5 Consumer 3.6 测试代码 3.7 启动测试 1. 简介 我们在上一篇博文中遗留了一个小问题,就是虽然TTL + DLX能实现延迟队列的功能,但是有两个问题. 首先业务场景为:比如海底捞预约,每个人预约的时间段不一致,有个可能一个小时后,有的可能三个小时等,当快到预约时间点需要给用户进行短信通知. 通过给

随机推荐