基于docker容器,搭建可视化监控系统,容器资源监控 & 业务数据监控,cAdvisor + InfluxDB + docker + Grafana 20190901

基于jsoup框架的爬虫系统,包括接口爬、定时爬、多线程爬
GitHub地址:https://github.com/HappyWjl/easy-monitor
如果该项目对您有帮助,您可以点右上角 “Star” 支持一下 谢谢!
或者您可以 “follow” 一下,该项目将持续更新,不断完善功能。
转载还请注明出处,谢谢了
博主QQ:820155406

一、容器监控

由于网上已有非常优秀的博文,所以博主就不再重新写了,详情见:https://blog.csdn.net/u012888052/article/details/99744554

  • docker 请自行安装,不会的百度

二、业务监控

  • 实现业务监控时,请务必完成上方的“容器监控”步骤,因为环境相同
  • 业务监控的范围非常广泛,比如:登录的用户数量、指定短信的发送数量、微信消息的发送数量等,接下来我们通过简单的程序,模拟用户登录事件,进行数据监控

1、创建数据库

  • 在容器监控中,我们已经搭建了InfluxDB数据库,所以我们现在可以根据具体业务,创建对应的业务数据库,这里我的业务是用户登录,属于用户系统下的事件,所以起名为 user
  • 按照下图所示,创建数据库,将上方的sql语句中数据库名改为 user ,敲回车。


    在这里插入图片描述
  • 当成功时,会返回success


    在这里插入图片描述
  • 接下来,我们查看现有数据库,可以看到user库已经创建完成


    在这里插入图片描述

2、创建模拟用户登录的项目

  • 具体怎么建项目这里就不说明了,简单讲一下里面的核心文件,实际企业中也不会像这个demo这么简单,挑有用的复制过去就可以
  • 项目采用IDEA开发,使用JDK11,这里环境自行搭建,不会的还请动手百度下
  • 项目结构


    在这里插入图片描述
  • pom.xml 构建包,需要引入需要的包,核心包只有一个,当然引入InfluxDB还有其他的包可以引入,比如spring中集成的包,在这里我们引入官方的原生包
        <!-- influxdb -->
        <dependency>
            <groupId>org.influxdb</groupId>
            <artifactId>influxdb-java</artifactId>
            <version>2.15</version>
        </dependency>
  • 配置文件application.yml,里面定义了项目端口8081,以及数据库的连接配置。为什么要指定8081呢,实际上我们的8080端口在前面已经被cAdvisor占用了,而项目是在博主的同一台机器运行的。
server:
  port: 8081

influxdb:
  username: root
  password: 123456
  openurl: http://localhost:8086
  database: user
  • InfluxDB工具类,这个文件封装了大量常用的InfluxDB api,方便我们使用,博主是在网上找到的这个文件,并非原创,后来进行了代码优化,增加了一些注释。
package com.ilearn1234.monitor.util;

import lombok.extern.slf4j.Slf4j;
import org.influxdb.InfluxDB;
import org.influxdb.InfluxDBFactory;
import org.influxdb.dto.*;

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

/**
 * InfluxDB数据库连接操作类
 *
 * @author Happy王子乐
 */
@Slf4j
public class InfluxDBUtil {

    // 用户名
    private String username;
    // 密码
    private String password;
    // 连接地址
    private String openurl;
    // 数据库
    private String database;
    // 保留策略
    private String retentionPolicy;
    // InfluxDB对象
    private InfluxDB influxDB;

    public InfluxDBUtil(String username, String password, String openurl, String database,
                        String retentionPolicy) {
        this.username = username;
        this.password = password;
        this.openurl = openurl;
        this.database = database;
        this.retentionPolicy = retentionPolicy == null || retentionPolicy.equals("") ? "autogen" : retentionPolicy;
        influxDbBuild();
    }

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

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

    /**
     * 测试连接是否正常
     *
     * @return true 正常
     */
    public boolean ping() {
        boolean isConnected = false;
        Pong pong;
        try {
            pong = influxDB.ping();
            if (pong != null) {
                isConnected = true;
            }
        } catch (Exception e) {
            log.error("InfluxDBUtil ping is error", e);
        }
        return isConnected;
    }

    /**
     * 连接时序数据库 ,若不存在则创建
     *
     * @return 数据库实例
     */
    public InfluxDB influxDbBuild() {
        if (influxDB == null) {
            influxDB = InfluxDBFactory.connect(openurl, username, password);
            influxDB.setDatabase(database);
        }
        influxDB.setLogLevel(InfluxDB.LogLevel.NONE);
        return influxDB;
    }

    /**
     * 创建自定义保留策略
     *
     * @param policyName  策略名
     * @param duration    保存天数
     * @param replication 保存副本数量
     * @param isDefault   是否设为默认保留策略
     */
    public void createRetentionPolicy(String policyName, String duration, int replication, Boolean isDefault) {
        String sql = String.format("CREATE RETENTION POLICY \"%s\" ON \"%s\" DURATION %s REPLICATION %s ", policyName,
                database, duration, replication);
        if (isDefault) {
            sql = sql + " DEFAULT";
        }
        this.query(sql);
    }

    /**
     * 创建默认的保留策略
     *
     * @param 策略名:default,保存天数:30天,保存副本数量:1,设为默认保留策略
     */
    public void createDefaultRetentionPolicy() {
        String command = String.format("CREATE RETENTION POLICY \"%s\" ON \"%s\" DURATION %s REPLICATION %s DEFAULT",
                "default", 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, long time,
                       TimeUnit timeUnit) {
        Point.Builder builder = Point.measurement(measurement);
        builder.tag(tags);
        builder.fields(fields);
        if (0 != time) {
            builder.time(time, timeUnit);
        }
        influxDB.write(database, retentionPolicy, builder.build());
    }

    /**
     * 写入测点
     *
     * @param point 单个数据点
     */
    public void insert(Point point) {
        influxDB.write(point);
    }

    /**
     * 批量写入测点
     *
     * @param batchPoints 批量数据点
     */
    public void batchInsert(BatchPoints batchPoints) {
        influxDB.write(batchPoints);
    }

    /**
     * 批量写入数据
     *
     * @param database        数据库
     * @param retentionPolicy 保存策略
     * @param consistency     一致性
     * @param records         要保存的数据(调用BatchPoints.lineProtocol()可得到一条record)
     */
    public void batchInsert(final String database, final String retentionPolicy,
                            final InfluxDB.ConsistencyLevel consistency, final List<String> records) {
        influxDB.write(database, retentionPolicy, consistency, records);
    }

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

    /**
     * 关闭数据库
     */
    public void close() {
        influxDB.close();
    }

    /**
     * 构建Point
     *
     * @param measurement 表
     * @param time        打点时间
     * @param tags        标签
     * @param fields      字段
     * @return 点数据对象
     */
    public Point pointBuilder(String measurement, long time, Map<String, String> tags, Map<String, Object> fields) {
        return Point.measurement(measurement).time(time, TimeUnit.MILLISECONDS).tag(tags).fields(fields).build();
    }
}
  • 数据源配置类,由于我们需要在项目启动时,连接好InfluxDB数据库,所以通过这个类,注入Bean
package com.ilearn1234.monitor.bean;

import com.ilearn1234.monitor.util.InfluxDBUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class InfluxDBConfig {

    @Value("${influxdb.username}")
    String username;

    @Value("${influxdb.password}")
    String password;

    @Value("${influxdb.openurl}")
    String openurl;

    @Value("${influxdb.database}")
    String database;

    @Bean
    public InfluxDBUtil initInfluxDB() {
        return new InfluxDBUtil(username, password, openurl, database, "");
    }
}
  • 对外接口,通过接口我们可以传入需要记录的参数,进行数据模拟
package com.ilearn1234.monitor.controller;

import com.ilearn1234.monitor.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class TestController {

    @Autowired
    TestService testService;

    @GetMapping("/login")
    public void test(Integer num) {
        testService.test(num);
    }
}
  • 业务具体实现类,这里我们通过自定义 表(measurement)自定义时间(time)自定义标签(tags)自定义字段(fields)构建成业务的数据点,进而存放到InfluxDB中
package com.ilearn1234.monitor.service.impl;

import com.ilearn1234.monitor.service.TestService;
import com.ilearn1234.monitor.util.InfluxDBUtil;
import org.influxdb.dto.Point;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Calendar;
import java.util.Map;

@Service("testService")
public class TestServiceImpl implements TestService {

    @Autowired
    InfluxDBUtil influxDBConnection;

    @Override
    public void test(Integer num) {
        Point point = influxDBConnection.pointBuilder(
                "user_login",
                Calendar.getInstance().getTimeInMillis(),
                Map.of("user", "login"),
                Map.of("login-number", num));
        influxDBConnection.insert(point);
    }
}

3、项目启动,进行数据模拟

  • 打开启动文件,点击左侧的小三角(如果环境有问题,或者maven构建不对,左侧的图标是不会出来的,请自行检查),再选择debug 或者 run启动
  • 控制台没有报错,端口也已经启动,即为正常


    在这里插入图片描述
  • 因为对外接口是get请求,所以我们通过浏览器访问“http://localhost:8081/api/login?num=1”,进行数据模拟
  • 刚刚只有1个用户登录了,接下来我们通过浏览器访问“http://localhost:8081/api/login?num=3”,模拟3个用户同时登录
  • 此时我们已经将数据存入到数据库中,接下来配置数据看板

4、配置Grafana数据看版

  • 打开Grafana的控制台,按照下图,创建指定数据库


    在这里插入图片描述
  • 选择InfluxDB数据库


    在这里插入图片描述
  • 填写数据库的配置,一定要注意名字的拼写,博主就因为少个字母,耽误很久配不成功,配置完成点击下方的保存按钮


    在这里插入图片描述
  • 开始配置数据可视化面板,按照下图进行操作


    在这里插入图片描述

    在这里插入图片描述
  • 我们指定数据库 InfluxDB-user,指定数据表user-login,筛选过滤标签user=login,查询login-number,可以看出基本的图形页面已经形成
  • 右侧可以指定筛选数据的时间段,并且点击下方的“画笔”按钮,可以直接写sql查询


    在这里插入图片描述
  • 接下来,我们访问浏览器“http://localhost:8081/api/login?num=20”,模拟20个用户同时登录,查看下数据看版
  • 在这里博主将时间段改成了15分钟,因为边弄程序,边写博客不容易,很花时间的。。。


    在这里插入图片描述
  • 如果我们像统计这段时间一共的登录用户是多少,我们可以这样操作,打开total选项,可以看到图表下方显示出了总数量24(1 + 3 + 20)


    在这里插入图片描述
  • 如果我们监控看版很多,那么我们每一个都需要起个名字


    在这里插入图片描述
  • 最后记得保存,这个很重要,切记。


    在这里插入图片描述
  • 至此,监控系统入门的大致讲解到这里,入门项目简单,可根据自身需求研究

基于jsoup框架的爬虫系统,包括接口爬、定时爬、多线程爬
GitHub地址:https://github.com/HappyWjl/easy-monitor
如果该项目对您有帮助,您可以点右上角 “Star” 支持一下 谢谢!
或者您可以 “follow” 一下,该项目将持续更新,不断完善功能。
转载还请注明出处,谢谢了
博主QQ:820155406

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

推荐阅读更多精彩内容