中间件--ClickHouse-12--案例-1-日志分析和监控

news2025/4/23 23:55:48

1、案例背景

一家互联网公司需要实时分析其服务器日志、应用日志和用户行为日志,以快速发现潜在问题并优化系统性能。

2、需求分析

  • 目标:实时分析日志数据,快速发现问题并优化系统性能。
  • 数据来源:
    • 服务器日志:如 Nginx、Tomcat、Docker等日志。
    • 应用日志:业务系统的运行日志。
    • 用户行为日志:用户操作记录(如点击、浏览、下单等)。
  • 输出:
    • 错误率、请求延迟、用户行为路径等关键指标。
    • 实时监控仪表盘。

3、解决思路

  • 日志采集:使用工具(如Filebeat或Fluentd)将日志数据写入Kafka。
  • 数据存储与分析:Kafka中的数据被导入到ClickHouse,利用其高效的压缩和查询性能进行日志分析。
  • 可视化:通过 Grafana 或 Redash 构建仪表盘,展示关键指标(如错误率、请求延迟等)。

4、技术选型

  • 日志采集:Filebeat 或 Fluentd。
  • 消息队列:Kafka(用于缓冲和传输日志数据)。
  • 存储与分析:ClickHouse(高性能 OLAP 数据库)。
  • 可视化:Grafana 或 Redash。

5、ClickHouse的作用

  • 高效存储:日志数据量通常非常庞大,ClickHouse的列式存储和高压缩比显著降低了存储成本。
  • 实时分析:支持毫秒级响应的复杂查询,适合对海量日志进行实时分析。
  • 灵活扩展:支持分布式部署,能够处理PB级别的日志数据。

6、基本实现步骤

(1)、日志采集

1. 安装 Filebeat:

bash示例:

sudo apt-get install filebeat
2. 配置 Filebeat:

编辑 filebeat.yml 文件,指定日志文件路径和 Kafka 输出:
yaml示例:

  filebeat.inputs:
   - type: log
     paths:
       - /var/log/nginx/*.log
       - /var/log/application/*.log

   output.kafka:
     hosts: ["kafka-broker:9092"]
     topic: "logs" 

解释:
Input为采集日志相关配置,如nginx的log日志文件,应用程序的log日志文件,output指定输出到kafka。

3. 启动 Filebeat:

bash示例:

sudo service filebeat start

(2)、消息队列(Kafka)

1. 安装 Kafka:

bash示例:

wget https://downloads.apache.org/kafka/3.0.0/kafka_2.13-3.0.0.tgz
tar -xzf kafka_2.13-3.0.0.tgz
cd kafka_2.13-3.0.0
2. 启动 Kafka:

bash示例:

bin/zookeeper-server-start.sh config/zookeeper.properties
bin/kafka-server-start.sh config/server.properties

(3)、数据消费与写入ClickHouse

1. 创建 ClickHouse 表:

sql示例:

   CREATE TABLE logs (
       timestamp DateTime,
       level String,
       message String,
       source String
   ) ENGINE = MergeTree()
   ORDER BY (timestamp);

(4)、可视化

1. 安装 Grafana:

bash示例:

sudo apt-get install grafana
sudo service grafana-server start
2. 配置 ClickHouse 数据源:

在 Grafana 中添加 ClickHouse 数据源,配置连接信息。

3. 构建仪表盘:

创建图表展示日志的关键指标,如错误率、请求延迟等。

7、Spring Boot代码示例

使用Spring Boot消费Kafka数据并写入 ClickHouse。

(1)、添加依赖

<dependencies>
    <!-- Spring Boot Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <!-- Kafka -->
    <dependency>
        <groupId>org.springframework.kafka</groupId>
        <artifactId>spring-kafka</artifactId>
    </dependency>

    <!-- ClickHouse JDBC -->
    <dependency>
        <groupId>com.clickhouse</groupId>
        <artifactId>clickhouse-jdbc</artifactId>
        <version>0.3.2</version>
    </dependency>

    <!-- Jackson for JSON Parsing -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>
</dependencies>

(2)、配置 Kafka 和 ClickHouse

在 application.yml 中配置 Kafka 和 ClickHouse:

spring:
  kafka:
    bootstrap-servers: kafka-broker:9092
    consumer:
      group-id: clickhouse-group
      auto-offset-reset: earliest
  datasource:
    url: jdbc:clickhouse://clickhouse-server:8123/default
    driver-class-name: com.clickhouse.jdbc.ClickHouseDriver
    username: default
    password: 

(3)、Kafka 消费者

import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Service;

@Service
public class LogConsumer {

    private final LogRepository logRepository;

    public LogConsumer(LogRepository logRepository) {
        this.logRepository = logRepository;
    }

    @KafkaListener(topics = "logs", groupId = "clickhouse-group")
    public void consume(String message) {
        // 解析日志消息
        Log log = parseLog(message);

        // 写入 ClickHouse
        logRepository.save(log);
    }

    private Log parseLog(String message) {
        // 假设日志是 JSON 格式
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            return objectMapper.readValue(message, Log.class);
        } catch (Exception e) {
            throw new RuntimeException("Failed to parse log message", e);
        }
    }
}

(4)、ClickHouse 数据访问层

创建Repository类。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class LogRepository {

    private final JdbcTemplate jdbcTemplate;

    @Autowired
    public LogRepository(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public void save(Log log) {
        String sql = "INSERT INTO logs (timestamp, level, message, source) VALUES (?, ?, ?, ?)";
        jdbcTemplate.update(sql, log.getTimestamp(), log.getLevel(), log.getMessage(), log.getSource());
    }
}

(5)、日志实体类

import java.time.LocalDateTime;

public class Log {
    private LocalDateTime timestamp;
    private String level;
    private String message;
    private String source;

    // Getters and Setters
}

(6)、 Service 层(LogService.java)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;

@Service
public class LogService {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    // 查询最近5分钟的错误率
    public List<Map<String, Object>> getErrorRate() {
        String sql = "SELECT program, error_count * 100.0 / total_requests AS error_percent " +
                     "FROM log_errors_mv " +
                     "WHERE minute >= now() - interval 5 minute " +
                     "GROUP BY program";
        return jdbcTemplate.queryForList(sql);
    }

    // 查询指定时间段的响应时间分布
    public List<Map<String, Object>> getResponseTimeStats(String startTime, String endTime) {
        String sql = "SELECT percentileState(upstream_response_time, 0.95) AS p95 " +
                     "FROM log_main " +
                     "WHERE timestamp BETWEEN ? AND ?";
        return jdbcTemplate.queryForList(sql, startTime, endTime);
    }
}

(7)、Controller 层(LogController.java)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;

@RestController
public class LogController {
    @Autowired
    private LogService logService;

    @GetMapping("/error-rate")
    public List<Map<String, Object>> getErrorRate() {
        return logService.getErrorRate();
    }

    @GetMapping("/response-time")
    public List<Map<String, Object>> getResponseTime(
            @RequestParam String startTime,
            @RequestParam String endTime
    ) {
        return logService.getResponseTimeStats(startTime, endTime);
    }
}

8、关键优化与注意事项

以上仅为简单的示例,实际生产中每一步都会比较复杂,需要结合实际需求在做详细的数据库设计以及接口设计等。这里我们主要是理解做的思路。

(1)、表设计优化

  • 分区策略:按 toYYYYMMDD(timestamp) 分区,便于按天清理旧数据。
  • 物化视图:预聚合高频查询指标(如错误率、响应时间),避免重复计算。
  • 索引与排序:在 program 和 timestamp 字段上建立索引,加速过滤查询。

(2)、ClickHouse 配置优化

  • 资源分配:增大 max_threads 和 max_memory_usage,提升并发处理能力。
  • 日志压缩:使用 gzip 或 lz4 压缩日志数据,减少存储开销。

(3)、Spring Boot 性能调优

  • 连接池配置:使用 HikariCP 管理数据库连接(通过 spring.datasource.hikari.* 配置)。
  • 缓存机制:对高频查询结果使用 Redis 缓存(如错误率统计)。

逆风成长,Dare To Be!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2341104.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入理解React中的Props与State:核心区别与最佳实践

在React开发中&#xff0c;props和state是构建交互式UI的两大基石。许多React初学者常常混淆这两者的概念&#xff0c;导致组件设计出现反模式。本文将全面剖析props与state的本质区别&#xff0c;通过实际场景说明它们的适用边界&#xff0c;并分享高效管理组件数据的实践经验…

STM32单片机入门学习——第46节: [14-1] WDG看门狗

写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难&#xff0c;但我还是想去做&#xff01; 本文写于&#xff1a;2025.04.23 STM32开发板学习——第46节: [14-1] WDG看门狗 前言开发板说明引用解答和科普一、…

n8n 中文系列教程_05.如何在本机部署/安装 n8n(详细图文教程)

n8n 是一款强大的开源工作流自动化工具&#xff0c;可帮助你连接各类应用与服务&#xff0c;实现自动化任务。如果你想快速体验 n8n 的功能&#xff0c;本机部署是最简单的方式。本教程将手把手指导你在 Windows 或 MacOS 上通过 Docker 轻松安装和运行 n8n&#xff0c;无需服务…

2025第十六届蓝桥杯python B组满分题解(详细)

目录 前言 A: 攻击次数 解题思路&#xff1a; 代码&#xff1a; B: 最长字符串 解题思路&#xff1a; 代码&#xff1a; C: LQ图形 解题思路&#xff1a; 代码&#xff1a; D: 最多次数 解题思路&#xff1a; 代码&#xff1a; E: A * B Problem 解题思路&…

Kafka 面试,java实战贴

面试问题列表 Kafka的ISR机制是什么&#xff1f;如何保证数据一致性&#xff1f; 如何实现Kafka的Exactly-Once语义&#xff1f; Kafka的Rebalance机制可能引发什么问题&#xff1f;如何优化&#xff1f; Kafka的Topic分区数如何合理设置&#xff1f; 如何设计Kafka的高可用跨…

linux多线(进)程编程——(9)信号量(一)

前言 在找到了共享内存存在的问题后&#xff0c;进程君父子着手开始解决这些问题。他们发明了一个新的神通——信号量。 信号量 信号量是一个计数器&#xff0c;用于管理对共享资源的访问权限。主要特点包括&#xff1a; &#xff08;1&#xff09;是一个非负整数 &#xff…

PFLM: Privacy-preserving federated learning with membership proof证明阅读

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 例如&#xff1a;第一章 Python 机器学习入门之pandas的使用 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目…

图片转base64 - 加菲工具 - 在线转换

图片转base64 - 加菲工具 先进入“加菲工具” 网 打开 https://www.orcc.top&#xff0c; 选择 “图片转base64”功能 选择需要转换的图片 复制 点击“复制”按钮&#xff0c;即可复制转换好的base64编码数据&#xff0c;可以直接用于img标签。

opencv 对图片的操作

对图片的操作 1.图片镜像旋转&#xff08;cv2.flip()&#xff09;2 图像的矫正 1.图片镜像旋转&#xff08;cv2.flip()&#xff09; 图像的旋转是围绕一个特定点进行的&#xff0c;而图像的镜像旋转则是围绕坐标轴进行的。图像的镜像旋转分为水平翻转、垂直翻转、水平垂直翻转…

LabVIEW数据采集与传感系统

开发了一个基于LabVIEW的智能数据采集系统&#xff0c;该系统主要通过单片机与LabVIEW软件协同工作&#xff0c;实现对多通道低频传感器信号的有效采集、处理与显示。系统的设计旨在提高数据采集的准确性和效率&#xff0c;适用于各种需要高精度和低成本解决方案的工业场合。 项…

【Easylive】​​Gateway模块 bootstrap.yml 解析

【Easylive】项目常见问题解答&#xff08;自用&持续更新中…&#xff09; 汇总版 Gateway模块 bootstrap.yml 常规解析 该配置文件定义了 Spring Cloud Gateway 的核心配置&#xff0c;包括 环境配置、服务注册、动态路由规则 等。以下是逐项解析&#xff1a; 1. 基础配…

matlab 环形单层柱状图

matlab 环形单层柱状图 matlab 环形单层柱状图 matlab 环形单层柱状图 图片 图片 【图片来源粉丝】 我给他的思路是&#xff1a;直接使用风玫瑰图可以画出。 rose_bar 本次我的更新和这个有些不同&#xff01;是环形柱状图&#xff0c;可调节细节多&#xff1b; 只需要函数…

文献×汽车 | 基于 ANSYS 的多级抛物线板簧系统分析

板簧系统是用于减弱或吸收动态系统中发生的应力、应变、偏转和变形等破坏性因素的机械结构。板簧系统可能对外力产生不同的响应&#xff0c;具体取决于其几何结构和材料特性。板簧系统的计算机辅助分析对于高精度确定系统的变形特性和结构特性至关重要。 在这项工作中&#xff…

RHCE 练习二:通过 ssh 实现两台主机免密登录以及 nginx 服务通过多 IP 区分多网站

一、题目要求 1.配置ssh实现A&#xff0c;B主机互相免密登录 2.配置nginx服务&#xff0c;通过多ip区分多网站 二、实验 实验开始前需准备两台 linux 主机便于充当服务端以及客户端&#xff0c;两台主机 IP 如下图&#xff1a; 实验1&#xff1a;配置 ssh 实现 A&#xff0…

瑞吉外卖-分页功能开发中的两个问题

1.分页功能-前端页面展示显示500 原因&#xff1a;项目启动失败 解决&#xff1a;发现是Category实体类中&#xff0c;多定义了一个删除字段&#xff0c;但是我数据库里面没有is_deleted字段&#xff0c;导致查询数据库失败&#xff0c;所以会导致500错误。因为类是从网上其他帖…

工业物联网安全网关 —— 安全OTA升级签名验证

这里写目录标题 工业物联网安全网关 —— 安全OTA升级签名验证一、项目背景与简介1.1 背景介绍1.2 OTA升级的安全挑战1.3 项目目标二、理论基础与关键技术2.1 数字签名基础2.2 OTA升级签名验证原理2.3 关键技术与安全算法三、系统架构设计3.1 系统模块划分3.2 系统架构图(Merm…

探索 Flowable 后端表达式:简化流程自动化

什么是后端表达式&#xff1f; 在 Flowable 中&#xff0c;后端表达式是一种强大的工具&#xff0c;用于在流程、案例或决策表执行期间动态获取或设置变量。它还能实现自定义逻辑&#xff0c;或将复杂逻辑委托…… 后端表达式在 Flowable 的后端运行&#xff0c;无法访问前端…

HDFS入门】HDFS安全与权限管理解析:从认证到加密的完整指南

目录 引言 1 认证与授权机制 1.1 Kerberos认证集成 1.2 HDFS ACL细粒度控制 2 数据加密保护 2.1 传输层加密(SSL/TLS) 2.2 静态数据加密 3 审计与监控体系 3.1 操作审计流程 3.2 安全监控指标 4 权限模型详解 4.1 用户/组权限模型 4.2 umask配置原理 5 安全最佳实…

性能比拼: Go vs Java

本内容是对知名性能评测博主 Anton Putra Go (Golang) vs Java: Performance Benchmark 内容的翻译与整理, 有适当删减, 相关指标和结论以原作为准 在本视频中&#xff0c;我们将比较 Go 和 Java。 我们将基于 Golang 的 Fiber 框架和 Java 的 Spring Boot 创建几个简单的应用…

ElMessageBox消息弹框(vue3总结)

一 展示各种内容 const checkCheckbox (check: any, formEl: any) > {ElMessageBox({title: "服务协议及隐私权政策",message: h("p", null, [h("span", null, "我已阅读并同意 "),h("span",{style: "color: #477F…