本文需要有相关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项目但是要引用一下相关包和相关注解以及修改相关配置文件

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

    

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-web</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.springframework.cloud</groupId>
  7. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  8. </dependency>
  9. <dependency>
  10. <groupId>org.springframework.cloud</groupId>
  11. <artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
  12. </dependency>
  13. <dependency>
  14. <groupId>org.springframework.cloud</groupId>
  15. <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.springframework.boot</groupId>
  19. <artifactId>spring-boot-starter-actuator</artifactId>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.springframework.cloud</groupId>
  23. <artifactId>spring-cloud-starter-hystrix</artifactId>
  24. </dependency>

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

  1.       spring-cloud-starter-hystrix熔断性能监控相关包。
          
          相关注解
  1. @EnableHystrix//开启性能监控
  2. @RefreshScope//刷新配置文件 与本章无关
  3. @EnableAutoConfiguration
  4. @EnableFeignClients//RPC调用与本章无关
  5. @RestController
  6. @SpringBootApplication
  7. public class ServerTestApplication {
  8. protected final static Logger logger = LoggerFactory.getLogger(ServerTestApplication.class);
  9.  
  10. public static void main(String[] args) {
  11. SpringApplication.run(ServerTestApplication.class, args);
  12. }
  13. }

    配置文件相关

  1. hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000
  2. hystrix.threadpool.default.coreSize: 100
  3. spring:
  4. application:
  5. name: spring-cloud-server2-test
  6. rabbitmq:
  7. host: 10.10.12.21
  8. port: 5672
  9. username: user
  10. password: password
  11.  
  12. encrypt:
  13. failOnError: false
  14. server:
  15. port: 8081
  16. eureka:
  17. instance:
  18. appname: spring-cloud-server2-test
  19. prefer-ip-address: true
  20. client:
  21. serviceUrl:
  22. defaultZone: http://IP:PORT/eureka/#注册中心地址
  23. eureka-server-total-connections-per-host: 500
  24. endpoints:
  25. refresh:
  26. sensitive: false
  27. metrics:
  28. sensitive: false
  29. dump:
  30. sensitive: false
  31. auditevents:
  32. sensitive: false
  33. features:
  34. sensitive: false
  35. mappings:
  36. sensitive: false
  37. trace:
  38. sensitive: false
  39. autoconfig:
  40. sensitive: false
  41. loggers:
  42. sensitive: false

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

  1.   @Value("${name}")
  2. private String name;
  3.  
  4. @HystrixCommand(commandProperties = {
  5. @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "20000") }, threadPoolProperties = {
  6. @HystrixProperty(name = "coreSize", value = "64") }, threadPoolKey = "test1")
  7. @GetMapping("/testpro1")
  8. public String getStringtest1(){
  9.  
  10. return name;
  11. }
  1.   好了到这里你的应用基本上就具备相关性能输出的能力了。你可以访问

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

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

  1.  

  二、性能指标数据采集

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

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

  1.      <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-web</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-amqp</artifactId>
  8. </dependency>
  9. <!-- https://mvnrepository.com/artifact/com.github.miwurster/spring-data-influxdb -->
  10. <dependency>
  11. <groupId>org.influxdb</groupId>
  12. <artifactId>influxdb-java</artifactId>
  13. <version>2.8</version>
  14. </dependency>
  15. <dependency>
  16. <groupId>org.springframework.boot</groupId>
  17. <artifactId>spring-boot-autoconfigure</artifactId>
  18. </dependency>

    直接贴代码

  1. package application;
  2.  
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5.  
  6. /**
  7. *
  8. * @author zyg
  9. *
  10. */
  11. @SpringBootApplication
  12. public class RabbitMQApplication {
  13.  
  14. public static void main(String[] args) {
  15. SpringApplication.run(RabbitMQApplication.class, args);
  16. }
  17.  
  18. }
  1. package application;
  2.  
  3. import org.springframework.amqp.core.Binding;
  4. import org.springframework.amqp.core.BindingBuilder;
  5. import org.springframework.amqp.core.Queue;
  6. import org.springframework.amqp.core.TopicExchange;
  7. import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
  8. import org.springframework.amqp.rabbit.connection.ConnectionFactory;
  9. import org.springframework.amqp.rabbit.core.RabbitTemplate;
  10. import org.springframework.context.annotation.Bean;
  11. import org.springframework.context.annotation.Configuration;
  12.  
  13. /**
  14. *
  15. * @author zyg
  16. *
  17. */
  18. @Configuration
  19. public class RabbitMQConfig {
  20. public final static String QUEUE_NAME = "spring-boot-queue";
  21. public final static String EXCHANGE_NAME = "springCloudHystrixStream";
  22. public final static String ROUTING_KEY = "#";
  23.  
  24. // 创建队列
  25. @Bean
  26. public Queue queue() {
  27. return new Queue(QUEUE_NAME);
  28. }
  29.  
  30. // 创建一个 topic 类型的交换器
  31. @Bean
  32. public TopicExchange exchange() {
  33. return new TopicExchange(EXCHANGE_NAME);
  34. }
  35.  
  36. // 使用路由键(routingKey)把队列(Queue)绑定到交换器(Exchange)
  37. @Bean
  38. public Binding binding(Queue queue, TopicExchange exchange) {
  39. return BindingBuilder.bind(queue).to(exchange).with(ROUTING_KEY);
  40. }
  41.  
  42. @Bean
  43. public ConnectionFactory connectionFactory() {
  44. //rabbitmq IP 端口号
  45. CachingConnectionFactory connectionFactory = new CachingConnectionFactory("IP", 5672);
  46. connectionFactory.setUsername("user");
  47. connectionFactory.setPassword("password");
  48. return connectionFactory;
  49. }
  50.  
  51. @Bean
  52. public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
  53. return new RabbitTemplate(connectionFactory);
  54. }
  55. }
  1. package application;
  2.  
  3. import java.util.Map;
  4. import java.util.concurrent.TimeUnit;
  5.  
  6. import org.influxdb.InfluxDB;
  7. import org.influxdb.InfluxDBFactory;
  8. import org.influxdb.dto.Point;
  9. import org.influxdb.dto.Point.Builder;
  10. import org.influxdb.dto.Query;
  11. import org.influxdb.dto.QueryResult;
  12.  
  13. /**
  14. *
  15. * @author zyg
  16. *
  17. */
  18. public class InfluxDBConnect {
  19. private String username;// 用户名
  20. private String password;// 密码
  21. private String openurl;// 连接地址
  22. private String database;// 数据库
  23.  
  24. private InfluxDB influxDB;
  25.  
  26. public InfluxDBConnect(String username, String password, String openurl, String database) {
  27. this.username = username;
  28. this.password = password;
  29. this.openurl = openurl;
  30. this.database = database;
  31. }
  32.  
  33. /** 连接时序数据库;获得InfluxDB **/
  34. public InfluxDB influxDbBuild() {
  35. if (influxDB == null) {
  36. influxDB = InfluxDBFactory.connect(openurl, username, password);
  37. influxDB.createDatabase(database);
  38.  
  39. }
  40. return influxDB;
  41. }
  42.  
  43. /**
  44. * 设置数据保存策略 defalut 策略名 /database 数据库名/ 30d 数据保存时限30天/ 1 副本个数为1/ 结尾DEFAULT
  45. * 表示 设为默认的策略
  46. */
  47. public void createRetentionPolicy() {
  48. String command = String.format("CREATE RETENTION POLICY \"%s\" ON \"%s\" DURATION %s REPLICATION %s DEFAULT",
  49. "defalut", database, "30d", 1);
  50. this.query(command);
  51. }
  52.  
  53. /**
  54. * 查询
  55. *
  56. * @param command
  57. * 查询语句
  58. * @return
  59. */
  60. public QueryResult query(String command) {
  61. return influxDB.query(new Query(command, database));
  62. }
  63.  
  64. /**
  65. * 插入
  66. *
  67. * @param measurement
  68. * 表
  69. * @param tags
  70. * 标签
  71. * @param fields
  72. * 字段
  73. */
  74. public void insert(String measurement, Map<String, String> tags, Map<String, Object> fields) {
  75. Builder builder = Point.measurement(measurement);
  76. builder.time(((long)fields.get("currentTime"))*1000000, TimeUnit.NANOSECONDS);
  77. builder.tag(tags);
  78. builder.fields(fields);
  79. //
  80. influxDB.write(database, "", builder.build());
  81. }
  82.  
  83. /**
  84. * 删除
  85. *
  86. * @param command
  87. * 删除语句
  88. * @return 返回错误信息
  89. */
  90. public String deleteMeasurementData(String command) {
  91. QueryResult result = influxDB.query(new Query(command, database));
  92. return result.getError();
  93. }
  94.  
  95. /**
  96. * 创建数据库
  97. *
  98. * @param dbName
  99. */
  100. public void createDB(String dbName) {
  101. influxDB.createDatabase(dbName);
  102. }
  103.  
  104. /**
  105. * 删除数据库
  106. *
  107. * @param dbName
  108. */
  109. public void deleteDB(String dbName) {
  110. influxDB.deleteDatabase(dbName);
  111. }
  112.  
  113. public String getUsername() {
  114. return username;
  115. }
  116.  
  117. public void setUsername(String username) {
  118. this.username = username;
  119. }
  120.  
  121. public String getPassword() {
  122. return password;
  123. }
  124.  
  125. public void setPassword(String password) {
  126. this.password = password;
  127. }
  128.  
  129. public String getOpenurl() {
  130. return openurl;
  131. }
  132.  
  133. public void setOpenurl(String openurl) {
  134. this.openurl = openurl;
  135. }
  136.  
  137. public void setDatabase(String database) {
  138. this.database = database;
  139. }
  140. }
  1. package application;
  2.  
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5.  
  6. /**
  7. *
  8. * @author zyg
  9. *
  10. */
  11. @Configuration
  12. public class InfluxDBConfiguration {
  13.  
  14. private String username = "admin";//用户名
  15. private String password = "admin";//密码
  16. private String openurl = "http://IP:8086";//InfluxDB连接地址
  17. private String database = "test_db";//数据库
  18.  
  19. @Bean
  20. public InfluxDBConnect getInfluxDBConnect(){
  21. InfluxDBConnect influxDB = new InfluxDBConnect(username, password, openurl, database);
  22.  
  23. influxDB.influxDbBuild();
  24.  
  25. influxDB.createRetentionPolicy();
  26. return influxDB;
  27. }
  28. }
  1. package application;
  2.  
  3. import java.io.IOException;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.Map;
  7.  
  8. import org.slf4j.Logger;
  9. import org.slf4j.LoggerFactory;
  10. import org.springframework.amqp.rabbit.annotation.RabbitListener;
  11. import org.springframework.beans.factory.annotation.Autowired;
  12. import org.springframework.stereotype.Component;
  13. import org.springframework.util.StringUtils;
  14.  
  15. import com.fasterxml.jackson.databind.ObjectMapper;
  16.  
  17. /**
  18. *
  19. * @author zyg
  20. *
  21. */
  22. @Component
  23. public class Consumer {
  24. protected final static Logger logger = LoggerFactory.getLogger(Consumer.class);
  25.  
  26. private ObjectMapper objectMapper = new ObjectMapper();
  27.  
  28. @Autowired
  29. private InfluxDBConnect influxDB;
  30.  
  31. @RabbitListener(queues = RabbitMQConfig.QUEUE_NAME)
  32. public void sendToSubject(org.springframework.amqp.core.Message message) {
  33.  
  34. String payload = new String(message.getBody());
  35. logger.info(payload);
  36.  
  37. if (payload.startsWith("\"")) {
  38. // Legacy payload from an Angel client
  39. payload = payload.substring(1, payload.length() - 1);
  40. payload = payload.replace("\\\"", "\"");
  41. }
  42. try {
  43. if (payload.startsWith("[")) {
  44. @SuppressWarnings("unchecked")
  45. List<Map<String, Object>> list = this.objectMapper.readValue(payload, List.class);
  46. for (Map<String, Object> map : list) {
  47. sendMap(map);
  48. }
  49. } else {
  50. @SuppressWarnings("unchecked")
  51. Map<String, Object> map = this.objectMapper.readValue(payload, Map.class);
  52. sendMap(map);
  53. }
  54. } catch (IOException ex) {
  55. logger.error("Error receiving hystrix stream payload: " + payload, ex);
  56. }
  57. }
  58.  
  59. private void sendMap(Map<String, Object> map) {
  60. Map<String, Object> data = getPayloadData(map);
  61. data.remove("latencyExecute");
  62. data.remove("latencyTotal");
  63. Map<String, String> tags = new HashMap<String, String>();
  64.  
  65. tags.put("type", data.get("type").toString());
  66. tags.put("name", data.get("name").toString());
  67. tags.put("instanceId", data.get("instanceId").toString());
  68. //tags.put("group", data.get("group").toString());
  69.  
  70. influxDB.insert("testaaa", tags, data);
  71.  
  72. // for (String key : data.keySet()) {
  73. // logger.info("{}:{}",key,data.get(key));
  74. // }
  75.  
  76. }
  77.  
  78. public static Map<String, Object> getPayloadData(Map<String, Object> jsonMap) {
  79. @SuppressWarnings("unchecked")
  80. Map<String, Object> origin = (Map<String, Object>) jsonMap.get("origin");
  81. String instanceId = null;
  82. if (origin.containsKey("id")) {
  83. instanceId = origin.get("host") + ":" + origin.get("id").toString();
  84. }
  85. if (!StringUtils.hasText(instanceId)) {
  86. // TODO: instanceid template
  87. instanceId = origin.get("serviceId") + ":" + origin.get("host") + ":" + origin.get("port");
  88. }
  89. @SuppressWarnings("unchecked")
  90. Map<String, Object> data = (Map<String, Object>) jsonMap.get("data");
  91. data.put("instanceId", instanceId);
  92. return data;
  93. }
  94.  
  95. }

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

  三、JVM相关数据采集

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

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

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

    

  1. package com.zjs.collection;
  2.  
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5. import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
  6.  
  7. /**
  8. *
  9. * @author zyg
  10. *
  11. */
  12. @EnableEurekaClient
  13. @SpringBootApplication
  14. public class ApplictionCollection
  15. {
  16. public static void main(String[] args) {
  17. SpringApplication.run(ApplictionCollection.class, args);
  18. }
  19. }
  1. /**
  2. * 批量插入
  3. *
  4. * @param measurement
  5. * 表
  6. * @param tags
  7. * 标签
  8. * @param fields
  9. * 字段
  10. */
  11. public void batchinsert(String measurement, Map<String, String> tags, List<Map<String, Object>> fieldslist) {
  12. org.influxdb.dto.BatchPoints.Builder batchbuilder=BatchPoints.database(database);
  13.  
  14. for (Map<String, Object> map : fieldslist) {
  15. Builder builder = Point.measurement(measurement);
  16. tags.put("instanceId", map.get("instanceId").toString());
  17. builder.time((long)map.get("currentTime"), TimeUnit.NANOSECONDS);
  18. builder.tag(tags);
  19. builder.fields(map);
  20. batchbuilder.point(builder.build());
  21. }
  22.  
  23. System.out.println(batchbuilder.build().toString());
  24.  
  25. influxDB.write(batchbuilder.build());
  26. }
  1. package com.zjs.collection;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.Map;
  7. import java.util.concurrent.ArrayBlockingQueue;
  8. import java.util.concurrent.LinkedBlockingQueue;
  9. import java.util.concurrent.ThreadPoolExecutor;
  10. import java.util.concurrent.TimeUnit;
  11.  
  12. import org.slf4j.Logger;
  13. import org.slf4j.LoggerFactory;
  14. import org.springframework.beans.factory.annotation.Autowired;
  15. import org.springframework.boot.autoconfigure.SpringBootApplication;
  16. import org.springframework.cloud.client.ServiceInstance;
  17. import org.springframework.cloud.client.discovery.DiscoveryClient;
  18. import org.springframework.context.annotation.Bean;
  19. import org.springframework.http.client.SimpleClientHttpRequestFactory;
  20. import org.springframework.scheduling.annotation.EnableScheduling;
  21. import org.springframework.scheduling.annotation.Scheduled;
  22. import org.springframework.stereotype.Component;
  23. import org.springframework.web.client.RestTemplate;
  24.  
  25. /**
  26. * 获取微服务实例
  27. *
  28. * @author zyg
  29. *
  30. */
  31. @Component
  32. @SpringBootApplication
  33. @EnableScheduling
  34. public class MicServerInstanceInfoHandle {
  35.  
  36. protected final static Logger logger = LoggerFactory.getLogger(MicServerInstanceInfoHandle.class);
  37.  
  38. final String pathtail = "/metrics/mem.*|heap.*|threads.*|gc.*|nonheap.*|classes.*";
  39.  
  40. Map<String, String> tags;
  41.  
  42. ThreadPoolExecutor threadpool;
  43.  
  44. @Autowired
  45. DiscoveryClient dc;
  46.  
  47. @Autowired
  48. RestTemplate restTemplate;
  49.  
  50. final static LinkedBlockingQueue<Map<String, Object>> jsonMetrics = new LinkedBlockingQueue<>(1000);
  51.  
  52. /**
  53. * 初始化实例 可以吧相关参数设置到配置文件
  54. */
  55. public MicServerInstanceInfoHandle() {
  56.  
  57. tags = new HashMap<String, String>();
  58. threadpool = new ThreadPoolExecutor(4, 20, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100));
  59.  
  60. }
  61.  
  62. @Autowired
  63. private InfluxDBConnect influxDB;
  64.  
  65. /**
  66. * metrics数据获取
  67. */
  68. @Scheduled(fixedDelay = 2000)
  69. public void metricsDataObtain() {
  70. logger.info("开始获取metrics数据");
  71. List<String> servicelist = dc.getServices();
  72. for (String str : servicelist) {
  73.  
  74. List<ServiceInstance> silist = dc.getInstances(str);
  75.  
  76. for (ServiceInstance serviceInstance : silist) {
  77. threadpool.execute(new MetricsHandle(serviceInstance));
  78. }
  79. }
  80. }
  81.  
  82. /**
  83. * 将数据插入到influxdb数据库
  84. */
  85. @Scheduled(fixedDelay = 5000)
  86. public void metricsDataToInfluxDB() {
  87. logger.info("开始批量将metrics数据insert-influxdb");
  88. ArrayList<Map<String, Object>> metricslist = new ArrayList<>();
  89. MicServerInstanceInfoHandle.jsonMetrics.drainTo(metricslist);
  90.  
  91. if (!metricslist.isEmpty()) {
  92. logger.info("批量插入条数:{}", metricslist.size());
  93. influxDB.batchinsert("metrics", tags, metricslist);
  94. }
  95.  
  96. logger.info("结束批量metrics数据insert");
  97. }
  98.  
  99. @Bean
  100. public RestTemplate getRestTemplate() {
  101. RestTemplate restTemplate = new RestTemplate();
  102. SimpleClientHttpRequestFactory achrf = new SimpleClientHttpRequestFactory();
  103. achrf.setConnectTimeout(10000);
  104. achrf.setReadTimeout(10000);
  105. restTemplate.setRequestFactory(achrf);
  106. return restTemplate;
  107.  
  108. }
  109.  
  110. class MetricsHandle extends Thread {
  111.  
  112. private ServiceInstance serviceInstanc;
  113.  
  114. public MetricsHandle(ServiceInstance serviceInstance){
  115. serviceInstanc=serviceInstance;
  116. }
  117.  
  118. @Override
  119. public void run() {
  120.  
  121. try {
  122.  
  123. logger.info("获取 {}:{}:{} 应用metrics数据",serviceInstanc.getServiceId(),serviceInstanc.getHost(),serviceInstanc.getPort());
  124.  
  125. @SuppressWarnings("unchecked")
  126. Map<String, Object> mapdata = restTemplate
  127. .getForObject(serviceInstanc.getUri().toString() + pathtail, Map.class);
  128. mapdata.put("instanceId", serviceInstanc.getServiceId() + ":" + serviceInstanc.getHost() + ":"
  129. + serviceInstanc.getPort());
  130. mapdata.put("type", "metrics");
  131. mapdata.put("currentTime", System.currentTimeMillis() * 1000000);
  132. MicServerInstanceInfoHandle.jsonMetrics.add(mapdata);
  133.  
  134. } catch (Exception e) {
  135. logger.error("instanceId:{},host:{},port:{},path:{},exception:{}", serviceInstanc.getServiceId(),
  136. serviceInstanc.getHost(), serviceInstanc.getPort(), serviceInstanc.getUri(),
  137. e.getMessage());
  138. }
  139. }
  140. }
  141.  
  142. }

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

  四、结果展示

  

    

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

  

  1. 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)
  2.  
  3. 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)
  1. 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端口什么的都是可以放到配置文件里面的。

    还有一种想法就是我可不可以像收集性能信息一样直接应用来收集JVM信息让JVM相关信息直接发送到MQ当中然后再插入InfluxDB中

  六、总结

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

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

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

    希望以上对大家有所帮助

spring boot +RabbitMQ +InfluxDB+Grafara监控实践的更多相关文章

  1. 如何做自己的服务监控?spring boot 2.x服务监控揭秘

    Actuator是spring boot项目中非常强大一个功能,有助于对应用程序进行监视和管理,通过 restful api请求来监管.审计.收集应用的运行情况,针对微服务而言它是必不可少的一个环节. ...

  2. Spring boot+RabbitMQ环境

    Spring boot+RabbitMQ环境 消息队列在目前分布式系统下具备非常重要的地位,如下的场景是比较适合消息队列的: 跨系统的调用,异步性质的调用最佳. 高并发问题,利用队列串行特点. 订阅模 ...

  3. spring-boot-plus集成Spring Boot Admin管理和监控应用(十一)

    spring-boot-plus集成Spring Boot Admin管理和监控应用 spring boot admin Spring Boot Admin用来管理和监控Spring Boot应用程序 ...

  4. 【Spring Boot】利用 Spring Boot Admin 进行项目监控管理

    利用 Spring Boot Admin 进行项目监控管理 一.Spring Boot Admin 是什么 Spring Boot Admin (SBA) 是一个社区开源项目,用于管理和监视 Spri ...

  5. Spring Boot开启Druid数据库监控功能

    Druid是一个关系型数据库连接池,它是阿里巴巴的一个开源项目.Druid支持所有JDBC兼容的数据库,包括Oracle.MySQL.Derby.PostgreSQL.SQL Server.H2等.D ...

  6. Spring Boot自动配置原理与实践(二)

    前言 在之前的博文(Spring Boot自动配置原理与实践(一))中,已经介绍了Spring boot的自动配置的相关原理与概念,本篇主要是对自动配置的实践,即自定义Starter,对原理与概念加深 ...

  7. Spring Boot (27) actuator服务监控与管理

    actuaotr是spring boot项目中非常强大的一个功能,有助于对应用程序进行监控和管理,通过restful api请求来监管.审计.收集应用的运行情况,针对微服务而言它是必不可少的一个环节. ...

  8. Spring Boot应用的健康监控

    在之前的系列文章中我们学习了如何进行Spring Boot应用的功能开发,以及如何写单元测试.集成测试等,然而,在实际的软件开发中需要做的不仅如此:还包括对应用程序的监控和管理. 正如飞行员不喜欢盲目 ...

  9. spring boot rabbitmq 多MQ配置 自动 创建 队列 RPC

      源码地址:https://github.com/hutuchong518/RabbitmqStudy 需求:   spring boot 整合 rabbitmq rpc功能, 需要将 请求和响应 ...

随机推荐

  1. python理解描述符(descriptor)

    Descriptor基础 python中的描述符可以用来定义触发自动执行的代码,它像是一个对象属性操作(访问.赋值.删除)的代理类一样.前面介绍过的property是描述符的一种. 大致流程是这样的: ...

  2. 分布式系统监视zabbix讲解六之自定义监控项--技术流ken

    宏 概述 Zabbix支持许多在多种情况下使用宏.宏是一个变量,由如下特殊语法标识: {MACRO} 根据在上下文中, 宏解析为一个特殊的值. 有效地使用宏可以节省时间,并使Zabbix变地更加高效. ...

  3. Java爬虫之下载全世界国家的国旗图片

    介绍   本篇博客将继续上一篇博客:Python爬虫之使用Fiddler+Postman+Python的requests模块爬取各国国旗 的内容,将用Java来实现这个爬虫,下载全世界国家的国旗图片. ...

  4. C++程序实例唯一方案,窗口只打开一次,程序只打开一次

    首先是方法: // IsAlreadyRunning - 是否已经运行 BOOL IsAlreadyRunning() { BOOL bRet = FALSE; HANDLE hMutex = ::C ...

  5. 30.QT-渐变之QLinearGradient、 QConicalGradient、QRadialGradient

    渐变有三种:QLinearGradient.QConicalGradient . QRadialGradient 它们都有一个QGradient父类 QGradient父类的常用公共函数有: void ...

  6. (6)Microsoft office Word 2013版本操作入门_文件封面,页首,页尾

    1插入封面: 1.1光标移动到首段,按住 Ctrl+Enter键可以插入一个新页面. 1.2 插入--->封面 可以在封面插入一个文件封面,里面的图片可以自己修改,文字标题也可以自己修改. 1. ...

  7. python基础学习(九)字典

    字典的定义 dictionary(字典) 是 除列表以外 Python 之中 最灵活 的数据类型(有点类似java中的Map) 字典同样可以用来 存储多个数据 通常用于存储 描述一个 物体 的相关信息 ...

  8. VM扩展磁盘大小

    1.通过扩展磁盘的方法增大磁盘大小 2.然后开启Linux 此时查看磁盘  df -h 并没有增加,使用 fdisk -l 查看发现已经扩展 使用 root 用户,进入到 ~ 家目录下面. 3.使用 ...

  9. Android 常用数据操作封装类案例

    1.DbHelper类 继承自SQLiteOpenHelper类,实现对数据库的基本操作 package com.example.utils; import android.content.Conte ...

  10. webpack安装

    npm install -g webpack webpack-dev-server