基于jsoup框架的爬蟲系統(tǒng)泛领,包括接口爬、定時(shí)爬敛惊、多線程爬
GitHub地址:https://github.com/HappyWjl/easy-monitor
如果該項(xiàng)目對(duì)您有幫助渊鞋,您可以點(diǎn)右上角 “Star” 支持一下 謝謝!
或者您可以 “follow” 一下,該項(xiàng)目將持續(xù)更新锡宋,不斷完善功能儡湾。
轉(zhuǎn)載還請(qǐng)注明出處,謝謝了
博主QQ:820155406
一执俩、容器監(jiān)控
由于網(wǎng)上已有非常優(yōu)秀的博文徐钠,所以博主就不再重新寫了,詳情見:https://blog.csdn.net/u012888052/article/details/99744554
- docker 請(qǐng)自行安裝奠滑,不會(huì)的百度
二丹皱、業(yè)務(wù)監(jiān)控
- 實(shí)現(xiàn)業(yè)務(wù)監(jiān)控時(shí),請(qǐng)務(wù)必完成上方的“容器監(jiān)控”步驟宋税,因?yàn)榄h(huán)境相同
- 業(yè)務(wù)監(jiān)控的范圍非常廣泛摊崭,比如:登錄的用戶數(shù)量、指定短信的發(fā)送數(shù)量杰赛、微信消息的發(fā)送數(shù)量等呢簸,接下來(lái)我們通過(guò)簡(jiǎn)單的程序,模擬用戶登錄事件乏屯,進(jìn)行數(shù)據(jù)監(jiān)控
1根时、創(chuàng)建數(shù)據(jù)庫(kù)
- 在容器監(jiān)控中,我們已經(jīng)搭建了InfluxDB數(shù)據(jù)庫(kù)辰晕,所以我們現(xiàn)在可以根據(jù)具體業(yè)務(wù)蛤迎,創(chuàng)建對(duì)應(yīng)的業(yè)務(wù)數(shù)據(jù)庫(kù),這里我的業(yè)務(wù)是用戶登錄含友,屬于用戶系統(tǒng)下的事件替裆,所以起名為 user
-
按照下圖所示,創(chuàng)建數(shù)據(jù)庫(kù)窘问,將上方的sql語(yǔ)句中數(shù)據(jù)庫(kù)名改為 user 辆童,敲回車。
-
當(dāng)成功時(shí)惠赫,會(huì)返回success
-
接下來(lái)把鉴,我們查看現(xiàn)有數(shù)據(jù)庫(kù),可以看到user庫(kù)已經(jīng)創(chuàng)建完成
2儿咱、創(chuàng)建模擬用戶登錄的項(xiàng)目
- 具體怎么建項(xiàng)目這里就不說(shuō)明了庭砍,簡(jiǎn)單講一下里面的核心文件,實(shí)際企業(yè)中也不會(huì)像這個(gè)demo這么簡(jiǎn)單概疆,挑有用的復(fù)制過(guò)去就可以
- 項(xiàng)目采用IDEA開發(fā)逗威,使用JDK11,這里環(huán)境自行搭建岔冀,不會(huì)的還請(qǐng)動(dòng)手百度下
-
項(xiàng)目結(jié)構(gòu)
- pom.xml 構(gòu)建包,需要引入需要的包,核心包只有一個(gè)使套,當(dāng)然引入InfluxDB還有其他的包可以引入,比如spring中集成的包侦高,在這里我們引入官方的原生包
<!-- influxdb -->
<dependency>
<groupId>org.influxdb</groupId>
<artifactId>influxdb-java</artifactId>
<version>2.15</version>
</dependency>
- 配置文件application.yml嫉柴,里面定義了項(xiàng)目端口8081,以及數(shù)據(jù)庫(kù)的連接配置奉呛。為什么要指定8081呢计螺,實(shí)際上我們的8080端口在前面已經(jīng)被cAdvisor占用了,而項(xiàng)目是在博主的同一臺(tái)機(jī)器運(yùn)行的瞧壮。
server:
port: 8081
influxdb:
username: root
password: 123456
openurl: http://localhost:8086
database: user
- InfluxDB工具類登馒,這個(gè)文件封裝了大量常用的InfluxDB api,方便我們使用咆槽,博主是在網(wǎng)上找到的這個(gè)文件陈轿,并非原創(chuàng),后來(lái)進(jìn)行了代碼優(yōu)化秦忿,增加了一些注釋麦射。
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數(shù)據(jù)庫(kù)連接操作類
*
* @author Happy王子樂(lè)
*/
@Slf4j
public class InfluxDBUtil {
// 用戶名
private String username;
// 密碼
private String password;
// 連接地址
private String openurl;
// 數(shù)據(jù)庫(kù)
private String database;
// 保留策略
private String retentionPolicy;
// InfluxDB對(duì)象
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();
}
/**
* 創(chuàng)建數(shù)據(jù)庫(kù)
*
* @param dbName 數(shù)據(jù)庫(kù)名
*/
@SuppressWarnings("deprecation")
public void createDB(String dbName) {
influxDB.createDatabase(dbName);
}
/**
* 刪除數(shù)據(jù)庫(kù)
*
* @param dbName 數(shù)據(jù)庫(kù)名
*/
@SuppressWarnings("deprecation")
public void deleteDB(String dbName) {
influxDB.deleteDatabase(dbName);
}
/**
* 測(cè)試連接是否正常
*
* @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;
}
/**
* 連接時(shí)序數(shù)據(jù)庫(kù) ,若不存在則創(chuàng)建
*
* @return 數(shù)據(jù)庫(kù)實(shí)例
*/
public InfluxDB influxDbBuild() {
if (influxDB == null) {
influxDB = InfluxDBFactory.connect(openurl, username, password);
influxDB.setDatabase(database);
}
influxDB.setLogLevel(InfluxDB.LogLevel.NONE);
return influxDB;
}
/**
* 創(chuàng)建自定義保留策略
*
* @param policyName 策略名
* @param duration 保存天數(shù)
* @param replication 保存副本數(shù)量
* @param isDefault 是否設(shè)為默認(rèn)保留策略
*/
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);
}
/**
* 創(chuàng)建默認(rèn)的保留策略
*
* @param 策略名:default灯谣,保存天數(shù):30天潜秋,保存副本數(shù)量:1,設(shè)為默認(rèn)保留策略
*/
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 查詢語(yǔ)句
* @return 查詢結(jié)果
*/
public QueryResult query(String command) {
return influxDB.query(new Query(command, database));
}
/**
* 插入
*
* @param measurement 表
* @param tags 標(biāo)簽
* @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());
}
/**
* 寫入測(cè)點(diǎn)
*
* @param point 單個(gè)數(shù)據(jù)點(diǎn)
*/
public void insert(Point point) {
influxDB.write(point);
}
/**
* 批量寫入測(cè)點(diǎn)
*
* @param batchPoints 批量數(shù)據(jù)點(diǎn)
*/
public void batchInsert(BatchPoints batchPoints) {
influxDB.write(batchPoints);
}
/**
* 批量寫入數(shù)據(jù)
*
* @param database 數(shù)據(jù)庫(kù)
* @param retentionPolicy 保存策略
* @param consistency 一致性
* @param records 要保存的數(shù)據(jù)(調(diào)用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 刪除語(yǔ)句
* @return 返回錯(cuò)誤信息
*/
public String deleteMeasurementData(String command) {
QueryResult result = influxDB.query(new Query(command, database));
return result.getError();
}
/**
* 關(guān)閉數(shù)據(jù)庫(kù)
*/
public void close() {
influxDB.close();
}
/**
* 構(gòu)建Point
*
* @param measurement 表
* @param time 打點(diǎn)時(shí)間
* @param tags 標(biāo)簽
* @param fields 字段
* @return 點(diǎn)數(shù)據(jù)對(duì)象
*/
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();
}
}
- 數(shù)據(jù)源配置類胎许,由于我們需要在項(xiàng)目啟動(dòng)時(shí)峻呛,連接好InfluxDB數(shù)據(jù)庫(kù),所以通過(guò)這個(gè)類呐萨,注入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, "");
}
}
- 對(duì)外接口杀饵,通過(guò)接口我們可以傳入需要記錄的參數(shù),進(jìn)行數(shù)據(jù)模擬
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);
}
}
- 業(yè)務(wù)具體實(shí)現(xiàn)類谬擦,這里我們通過(guò)自定義 表(measurement)自定義時(shí)間(time)自定義標(biāo)簽(tags)自定義字段(fields)構(gòu)建成業(yè)務(wù)的數(shù)據(jù)點(diǎn)切距,進(jìn)而存放到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、項(xiàng)目啟動(dòng)惨远,進(jìn)行數(shù)據(jù)模擬
- 打開啟動(dòng)文件谜悟,點(diǎn)擊左側(cè)的小三角(如果環(huán)境有問(wèn)題,或者maven構(gòu)建不對(duì)北秽,左側(cè)的圖標(biāo)是不會(huì)出來(lái)的葡幸,請(qǐng)自行檢查),再選擇debug 或者 run啟動(dòng)
-
控制臺(tái)沒(méi)有報(bào)錯(cuò)贺氓,端口也已經(jīng)啟動(dòng)蔚叨,即為正常
- 因?yàn)閷?duì)外接口是get請(qǐng)求,所以我們通過(guò)瀏覽器訪問(wèn)“http://localhost:8081/api/login?num=1”,進(jìn)行數(shù)據(jù)模擬
- 剛剛只有1個(gè)用戶登錄了蔑水,接下來(lái)我們通過(guò)瀏覽器訪問(wèn)“http://localhost:8081/api/login?num=3”邢锯,模擬3個(gè)用戶同時(shí)登錄
- 此時(shí)我們已經(jīng)將數(shù)據(jù)存入到數(shù)據(jù)庫(kù)中,接下來(lái)配置數(shù)據(jù)看板
4搀别、配置Grafana數(shù)據(jù)看版
-
打開Grafana的控制臺(tái)丹擎,按照下圖壶愤,創(chuàng)建指定數(shù)據(jù)庫(kù)
-
選擇InfluxDB數(shù)據(jù)庫(kù)
-
填寫數(shù)據(jù)庫(kù)的配置纺非,一定要注意名字的拼寫,博主就因?yàn)樯賯€(gè)字母奠伪,耽誤很久配不成功榜苫,配置完成點(diǎn)擊下方的保存按鈕
-
開始配置數(shù)據(jù)可視化面板护戳,按照下圖進(jìn)行操作
- 我們指定數(shù)據(jù)庫(kù) InfluxDB-user,指定數(shù)據(jù)表user-login单刁,篩選過(guò)濾標(biāo)簽user=login灸异,查詢login-number,可以看出基本的圖形頁(yè)面已經(jīng)形成
-
右側(cè)可以指定篩選數(shù)據(jù)的時(shí)間段羔飞,并且點(diǎn)擊下方的“畫筆”按鈕肺樟,可以直接寫sql查詢
- 接下來(lái),我們?cè)L問(wèn)瀏覽器“http://localhost:8081/api/login?num=20”逻淌,模擬20個(gè)用戶同時(shí)登錄么伯,查看下數(shù)據(jù)看版
-
在這里博主將時(shí)間段改成了15分鐘,因?yàn)檫吪绦蚩ㄈ澹厡懖┛筒蝗菀滋锶幔芑〞r(shí)間的。骨望。硬爆。
-
如果我們像統(tǒng)計(jì)這段時(shí)間一共的登錄用戶是多少,我們可以這樣操作擎鸠,打開total選項(xiàng)缀磕,可以看到圖表下方顯示出了總數(shù)量24(1 + 3 + 20)
-
如果我們監(jiān)控看版很多,那么我們每一個(gè)都需要起個(gè)名字
-
最后記得保存劣光,這個(gè)很重要袜蚕,切記。
- 至此绢涡,監(jiān)控系統(tǒng)入門的大致講解到這里牲剃,入門項(xiàng)目簡(jiǎn)單,可根據(jù)自身需求研究
基于jsoup框架的爬蟲系統(tǒng)雄可,包括接口爬凿傅、定時(shí)爬缠犀、多線程爬
GitHub地址:https://github.com/HappyWjl/easy-monitor
如果該項(xiàng)目對(duì)您有幫助,您可以點(diǎn)右上角 “Star” 支持一下 謝謝狭归!
或者您可以 “follow” 一下夭坪,該項(xiàng)目將持續(xù)更新文判,不斷完善功能过椎。
轉(zhuǎn)載還請(qǐng)注明出處,謝謝了
博主QQ:820155406