一,Influxdb安装与启动

1,创建yum仓库

cat <<EOF | sudo tee /etc/yum.repos.d/influxdb.repo  
[influxdb]  
name = InfluxDB Repository - RHEL $releasever  
baseurl = https://repos.influxdata.com/rhel/$releasever/$basearch/stable  
enabled = 1  
gpgcheck = 1  
gpgkey = https://repos.influxdata.com/influxdb.key  
EO

2,安装启动influxdb

## 安装influxdb  
sudo yum install influxdb
## 启动服务  
sudo systemctl start influxdb

3,influxdb客户端使用

## 进入命令行客户端  
influx  
Connected to http://localhost:8086 version 1.8.1  
InfluxDB shell version: 1.8.1

二,Influxdb基本概念与操作

1,Database

数据库,可以创建多个,不同数据库中的数据文件,存放在磁盘上的不同目录。

# 查看数据库  
show databases  
# 创建数据库  
create database mydb  
# 使用数据库  
use mydb  
# 删除数据库  
drop database mydb

2,Measurement

相当于数据库中的表名,时间数据 timeTagField 组合成了 MeasurementInfluxDB 没有创建表一说,直接 insert 就可以将数据插入 Measurement,可以理解为自动创建表。InfluxDB 没有对 measurement 的修改操作。

-- 创建一个cpu的measurement,tags为host和regin,其中值为0.64  
insert cpu,host=serverA,region=china\_shanghai value=0.64

-- 查询 measurement  
> select * from cpu  
name: cpu  
time                host    region         value  
----                ----    ------         -----  
1596695999229393499 serverA china\_shanghai 0.64

3,Point

表里的一行数据,由时间戳(timestamp)、标签(tag)、数据(field)组成。timestamp 相当于 point 的时间戳,field 相当于point的值,tags 相当于 point 的属性。

4,Timestamp

数据的时间戳,相当于主键。不赋值时,默认为系统时间。

5,Tag

相当于索引。采用key=value形式,多个 tag 之间用 ',' 分隔。

> show tag keys from cpu  
name: cpu  
tagKey  
------  
host  
region

6,Field

相当于实际记录的数据值,也是采用key=value形式,多个 tag 之间用 ',' 分隔

> show field keys  
name: cpu  
fieldKey fieldType  
-------- ---------  
value    float

7,Retention Policy

存储策略,InfluxDB 会自动清理数据,可以设置数据保留的时间,默认会创建存储策略 autogen (保留时间为永久),之后用户可以自己设置,例如保留最近 30 天的数据。

-- 查看默认策略  
> show retention policies on mydb  
name    duration shardGroupDuration replicaN default  
----    -------- ------------------ -------- -------  
 0s       168h0m0s           1        true  
-- 创建新的策略  
create retention policy "rp\_day\_30" on "mydb" duration 30d replication 1 default  
-- 修改策略  
alter retention policy "rp\_day\_30" on "mydb" duration 20d replication 1 default

三,Influxdb api使用

1,首先配置influxdb的properties配置,如下:

# influxDB  
spring.influx.url\=http://192.168.60.201:8086  
spring.influx.user\=admin  
spring.influx.password\=admin  
spring.influx.database\=mydb

2,添加influx java config

@Configuration
@Slf4j
public class InfluxConfig {
    @Value("${spring.influx.url}")
    private String influxDBUrl;

    @Value("${spring.influx.user}")
    private String userName;

    @Value("${spring.influx.password}")
    private String password;

    @Value("${spring.influx.database}")
    private String database;

    /**
     * 异步插入:
     * enableBatch这里第一个是point的个数,第二个是时间,单位毫秒
     * point的个数和时间是联合使用的,如果满100条或者60 * 1000毫秒
     * 满足任何一个条件就会发送一次写的请求。
     */
    @Bean(name = "influxDB")
    public InfluxDB influxdb() {
        InfluxDB influxDB = InfluxDBFactory.connect(influxDBUrl, userName, password);
        try {
            influxDB.setDatabase(database).enableBatch(100, 1000 * 60, TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            log.error("fail enableBatch:", e);
        } finally {
            //设置默认策略
            influxDB.setRetentionPolicy("autogen");
        }
        //设置日志输出级别
        influxDB.setLogLevel(InfluxDB.LogLevel.BASIC);
        return influxDB;
    }
}

3,抽象influxdb api接口,提供埋点事件接口

@Component
@Slf4j
public class InfluxMonitor {

    private ConcurrentLinkedDeque<Point> eventDeque = new ConcurrentLinkedDeque<>();

    private static final String measurement = "Event";

    private static final String eventName = "EventName";

    private static final String eventCount = "EventCount";

    private static AtomicInteger eventSize = new AtomicInteger();

    private static ExecutorService executor = Executors.newFixedThreadPool(16);

    @Value("${spring.influx.database}")
    private String database;

    @Autowired
    private InfluxDB influxDB;

    /**
     * 多线程异步处理
     */
    public InfluxMonitor() {
        for (int i = 0; i < 8; i++) {
            executor.submit((Runnable) () -> {
                while (true) {
                    try {
                        Thread.sleep(100);
                        int size = 2000;
                        Point point;
                        BatchPoints batchPoints = BatchPoints.database(database).build();
                        while ((point = eventDeque.pollLast()) != null && size-- > 0) {
                            eventSize.getAndDecrement();
                            batchPoints.point(point);
                        }
                        if (batchPoints.getPoints().size() > 0) {
                            influxDB.write(batchPoints);
                        }
                    } catch (Exception e) {
                        log.error("influxDB:", e);
                    }
                }
            });
        }
    }


    /**
     * 多线程处理件
     */
    public void produce(Point point) {
        if (eventSize.getAndIncrement() < 5000) {
            eventDeque.offerFirst(point);
        }
    }

    /**
     * 创建订单事件
     */
    public void createOrderEvent(String messageCode, CreateOrderDTO order) {
        Map<String, String> tags = new HashMap<>();
        tags.put("messageCode", messageCode);
        tags.put("channel", order.getChannel());
        this.logEvent("createOrder", new HashMap<>(), tags);
    }

    /**
     * 发送数据
     *
     * @param logEventName 事件类型 如:创建订单
     * @param fields       influx field 指标如: 下单次数
     * @param tags         influx tags 查询索引
     */
    public void logEvent(String logEventName, Map<String, Object> fields, Map<String, String> tags) {
        try {
            tags.put(eventName, logEventName);
            fields.put(eventCount, 1);

            Point point = Point.measurement(measurement)
                    .tag(tags)
                    .fields(fields)
                    .build();
            this.produce(point);
        } catch (Exception e) {
            log.error("influx log event:", e);
        }
    }
}

4,添加controller模拟下单接口

@RestController  
@RequestMapping(value = "/influx")  
@Slf4j  
public class InfluxController {  
​  
 @Autowired  
 private InfluxMonitor influxMonitor;  
​  
 @PostMapping("/createOrder")  
 public Object createOrder(@RequestBody CreateOrderDTO createOrder) {  
 log.info("订单业务处理..............");  
 String messageCode = "200";  
 influxMonitor.createOrderEvent(messageCode, createOrder);  
 return Boolean.TRUE;  
 }  
}

5,使用postman测试,下一节我们使用可视化页面展示
image

四,可视化工具Grafana介绍

Grafana 是以纯 Javascript 开发的前端工具,用于访问 InfluxDB,自定义报表、显示图表等,Grafana下载地址

安装

wget https://dl.grafana.com/oss/release/grafana-7.1.2-1.x86\_64.rpm   
sudo yum install grafana-7.1.2-1.x86\_64.rpm 

修改配置 : vim /etc/grafana/grafana.ini

[server]  
# Protocol (http, https, h2, socket)  
;protocol = http  
​  
# The ip address to bind to, empty will bind to all interfaces  
http_addr = 192.168.60.201  
​  
# The http port  to use  
http_port = 3000

启动检查

systemctl start grafana-server ## 启动grafana服务  
systemctl status grafana-server ## 检查启动状态

image

在浏览器中访问我们配置的ip及端口,本文配置的为:http://192.168.60.201:3000,默认的用户名和密码是admin/admin,首次登陆提醒你修改密码即可

image

配置数据源(官网地址)Grafana支持多种数据源如:MySQL,Graphite,InfluxDB,Elasticsearch等,本文说的是influxDB,当然使用的就是InfluxDB了,我们看到有很多可选的数据源如下:

image

下面是本地基于InfluxDB的配置,主要是url,database等一些基本配置

image

Grafana像写sql一样统计展示不同的面板,非常方便,下面就是以下单次数及各渠道下单分布创建不同的面板来展示Grafana的强大!
image

  • FROM 指定目标

    autogen:我们代码中指定的存储策略

    Event :我们代码中指定的measurement

    EventName:指定的tags中的一个,本文中就是创建订单事件 createOrder

  • SELECT 查询指标

    field(EventCount) : 指定的fields中的一个,也是我们需要监控的指标,本文中就是下单次数,我默认指定了一次接口调用存储了一次EventCount=1

    sum():这个就不多说了相当于mysql中的求和,计算的就是前面指定的field

  • GROUP BY 分组

    time($_interval):面板上指定的时间

  • ALIAS BY 查询结果别名,本文中就是下单成功次数

Grafana支持很多复杂的查询,这里就不一一演示了,最后看下我们做的面板效果图,InfluxDB的性能是非常好的近实时的,我们通过选择不同的时间来查看业务埋点监控看板
image


Gent
209 声望18 粉丝

今天不走,明天要跑!!!