ELK 从入门到精通:Spring Boot 实战三部曲(一)—— 基础核心与快速上手

ELK 从入门到精通:Spring Boot 实战三部曲(一)------ 基础核心与快速上手

专题导读:本系列共三篇,从基础到高级,带你系统掌握 ELK(Elasticsearch + Logstash + Kibana)在 Spring Boot 项目中的实战应用。

  • 第一篇:基础核心与快速上手(本文)
  • 第二篇:进阶特性与性能优化
  • 第三篇:高级应用与架构设计

📖 前言

在当今的分布式系统中,日志管理和数据分析已成为运维和开发的核心需求。ELK Stack(Elasticsearch + Logstash + Kibana)作为最流行的日志分析平台,以其强大的搜索能力、灵活的数据处理和直观的可视化界面著称。

本文将从 ELK 的基础概念出发,结合 Spring Boot 项目,带你快速上手 ELK 开发,掌握日志收集、存储和可视化的完整流程。

学完本文你将掌握:

  • ✅ ELK 的核心组件与应用场景
  • ✅ Elasticsearch 基础操作与 DSL 查询
  • ✅ Logstash 日志收集与处理
  • ✅ Kibana 数据可视化
  • ✅ Spring Boot 集成 ELK 的完整配置
  • ✅ 实际业务场景中的日志管理

一、ELK 是什么?为什么需要它?

1.1 ELK Stack 简介

ELK Stack 是三个开源项目的首字母缩写:

  • Elasticsearch:分布式搜索和分析引擎
  • Logstash:服务器端数据处理管道
  • Kibana:数据可视化平台

核心特点:

  • 🔍 强大搜索:全文检索、模糊匹配、聚合分析
  • 📊 实时可视化:丰富的图表类型,实时监控
  • 🔄 灵活处理:支持多种数据源和格式
  • 🌐 分布式架构:水平扩展,高可用
  • 🛠️ 生态丰富:Beats、APM 等组件

1.2 典型应用场景

复制代码
┌─────────────────────────────────────────────┐
│           ELK 应用场景                       │
├──────────────┬──────────────────────────────┤
│ 日志管理     │ 应用日志、系统日志、访问日志    │
│ 实时监控     │ 业务指标、性能监控、告警       │
│ 数据分析     │ 用户行为分析、业务数据统计      │
│ 安全审计     │ 入侵检测、异常行为分析         │
│ APM          │ 应用性能监控、链路追踪         │
│ 搜索引擎     │ 商品搜索、文档检索             │
└──────────────┴──────────────────────────────┘

1.3 与传统方案对比

特性 ELK 传统日志方案
搜索能力 全文检索、毫秒级响应 关键字 grep,慢
可视化 丰富图表、实时更新 无或简单
扩展性 分布式、水平扩展 单机、受限
数据处理 灵活管道、多种格式 固定格式
学习成本 中等

二、环境搭建与快速开始

2.1 Docker Compose 安装(推荐)

docker-compose.yml:

yaml 复制代码
version: '3.8'

services:
  elasticsearch:
    image: elasticsearch:8.11.0
    container_name: elasticsearch
    environment:
      - discovery.type=single-node
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - xpack.security.enabled=false
    ports:
      - "9200:9200"
      - "9300:9300"
    volumes:
      - es-data:/usr/share/elasticsearch/data
    networks:
      - elk-network

  logstash:
    image: logstash:8.11.0
    container_name: logstash
    ports:
      - "5044:5044"
      - "9600:9600"
    volumes:
      - ./logstash/pipeline:/usr/share/logstash/pipeline
      - ./logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml
    environment:
      - LS_JAVA_OPTS=-Xms256m -Xmx256m
    depends_on:
      - elasticsearch
    networks:
      - elk-network

  kibana:
    image: kibana:8.11.0
    container_name: kibana
    ports:
      - "5601:5601"
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    depends_on:
      - elasticsearch
    networks:
      - elk-network

volumes:
  es-data:

networks:
  elk-network:
    driver: bridge

启动命令:

bash 复制代码
# 创建目录
mkdir -p logstash/pipeline logstash/config

# 启动 ELK
docker-compose up -d

# 查看状态
docker-compose ps

# 查看日志
docker-compose logs -f

验证安装:

bash 复制代码
# 测试 Elasticsearch
curl http://localhost:9200

# 测试 Kibana
# 浏览器访问:http://localhost:5601

2.2 核心概念

复制代码
┌──────────────────────────────────────────────┐
│         Elasticsearch 核心概念                 │
├──────────┬───────────────────────────────────┤
│ Index    │ 索引,类似数据库中的表              │
│ Document │ 文档,类似数据库中的行              │
│ Field    │ 字段,类似数据库中的列              │
│ Mapping  │ 映射,定义字段类型                  │
│ Shard    │ 分片,数据的物理分区                │
│ Replica  │ 副本,分片的备份                    │
└──────────┴───────────────────────────────────┘

数据层级:

复制代码
Cluster(集群)
  └─ Node(节点)
      └─ Index(索引)
          └─ Type(类型,7.x后废弃)
              └─ Document(文档)
                  └─ Field(字段)

三、Elasticsearch 基础操作

3.1 RESTful API 基本操作

索引操作
bash 复制代码
# 创建索引
PUT /user_index
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1
  },
  "mappings": {
    "properties": {
      "name": { "type": "text" },
      "age": { "type": "integer" },
      "email": { "type": "keyword" },
      "createTime": { "type": "date" }
    }
  }
}

# 查看索引
GET /user_index

# 删除索引
DELETE /user_index

# 查看所有索引
GET /_cat/indices?v
文档操作
bash 复制代码
# 添加文档(自动生成ID)
POST /user_index/_doc
{
  "name": "张三",
  "age": 25,
  "email": "zhangsan@example.com",
  "createTime": "2024-01-01T10:00:00"
}

# 添加文档(指定ID)
PUT /user_index/_doc/1
{
  "name": "李四",
  "age": 30,
  "email": "lisi@example.com",
  "createTime": "2024-01-01T11:00:00"
}

# 查询文档
GET /user_index/_doc/1

# 更新文档
POST /user_index/_update/1
{
  "doc": {
    "age": 31
  }
}

# 删除文档
DELETE /user_index/_doc/1

# 批量操作
POST /_bulk
{ "index": { "_index": "user_index", "_id": "2" } }
{ "name": "王五", "age": 28, "email": "wangwu@example.com" }
{ "index": { "_index": "user_index", "_id": "3" } }
{ "name": "赵六", "age": 35, "email": "zhaoliu@example.com" }

3.2 DSL 查询语言

基础查询
bash 复制代码
# Match Query(全文检索)
GET /user_index/_search
{
  "query": {
    "match": {
      "name": "张三"
    }
  }
}

# Term Query(精确匹配)
GET /user_index/_search
{
  "query": {
    "term": {
      "email": {
        "value": "zhangsan@example.com"
      }
    }
  }
}

# Range Query(范围查询)
GET /user_index/_search
{
  "query": {
    "range": {
      "age": {
        "gte": 20,
        "lte": 30
      }
    }
  }
}

# Bool Query(组合查询)
GET /user_index/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "name": "张" } }
      ],
      "filter": [
        { "range": { "age": { "gte": 20, "lte": 30 } } }
      ]
    }
  }
}
聚合查询
bash 复制代码
# 统计各年龄段人数
GET /user_index/_search
{
  "size": 0,
  "aggs": {
    "age_groups": {
      "range": {
        "field": "age",
        "ranges": [
          { "to": 25 },
          { "from": 25, "to": 35 },
          { "from": 35 }
        ]
      }
    }
  }
}

# 平均值统计
GET /user_index/_search
{
  "size": 0,
  "aggs": {
    "avg_age": {
      "avg": {
        "field": "age"
      }
    }
  }
}

四、Spring Boot 集成 Elasticsearch

4.1 Maven 依赖

xml 复制代码
<dependencies>
    <!-- Spring Data Elasticsearch -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>
</dependencies>

4.2 application.yml 配置

yaml 复制代码
spring:
  elasticsearch:
    uris: http://localhost:9200
    connection-timeout: 5s
    socket-timeout: 30s

4.3 实体类定义

java 复制代码
@Data
@Document(indexName = "user_index")
public class UserDocument {
    
    @Id
    private String id;
    
    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String name;
    
    @Field(type = FieldType.Integer)
    private Integer age;
    
    @Field(type = FieldType.Keyword)
    private String email;
    
    @Field(type = FieldType.Date, format = DateFormat.date_time)
    private LocalDateTime createTime;
    
    @Field(type = FieldType.Text)
    private String address;
}

4.4 Repository 接口

java 复制代码
@Repository
public interface UserRepository extends ElasticsearchRepository<UserDocument, String> {
    
    /**
     * 根据姓名查询
     */
    List<UserDocument> findByName(String name);
    
    /**
     * 根据年龄范围查询
     */
    List<UserDocument> findByAgeBetween(Integer minAge, Integer maxAge);
    
    /**
     * 根据邮箱查询
     */
    Optional<UserDocument> findByEmail(String email);
    
    /**
     * 复合查询
     */
    List<UserDocument> findByNameAndAgeBetween(String name, Integer minAge, Integer maxAge);
}

4.5 Service 层实现

java 复制代码
@Service
@Slf4j
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private ElasticsearchRestTemplate elasticsearchTemplate;

    /**
     * 保存用户
     */
    public UserDocument saveUser(UserDocument user) {
        if (user.getCreateTime() == null) {
            user.setCreateTime(LocalDateTime.now());
        }
        
        UserDocument saved = userRepository.save(user);
        log.info("用户保存成功: id={}", saved.getId());
        return saved;
    }

    /**
     * 批量保存
     */
    public void batchSaveUsers(List<UserDocument> users) {
        userRepository.saveAll(users);
        log.info("批量保存用户: {} 条", users.size());
    }

    /**
     * 根据ID查询
     */
    public Optional<UserDocument> getUserById(String id) {
        return userRepository.findById(id);
    }

    /**
     * 根据姓名搜索
     */
    public List<UserDocument> searchByName(String name) {
        return userRepository.findByName(name);
    }

    /**
     * 复杂查询
     */
    public List<UserDocument> searchUsers(String keyword, Integer minAge, Integer maxAge) {
        NativeSearchQuery query = new NativeSearchQueryBuilder()
            .withQuery(QueryBuilders.boolQuery()
                .must(QueryBuilders.multiMatchQuery(keyword, "name", "address"))
                .filter(QueryBuilders.rangeQuery("age")
                    .gte(minAge)
                    .lte(maxAge))
            )
            .withSort(SortBuilders.fieldSort("age").order(SortOrder.ASC))
            .withPageable(PageRequest.of(0, 10))
            .build();
        
        SearchHits<UserDocument> hits = elasticsearchTemplate.search(query, UserDocument.class);
        
        return hits.stream()
            .map(SearchHit::getContent)
            .collect(Collectors.toList());
    }

    /**
     * 删除用户
     */
    public void deleteUser(String id) {
        userRepository.deleteById(id);
        log.info("用户删除成功: id={}", id);
    }

    /**
     * 聚合统计
     */
    public Map<String, Object> getUserStats() {
        NativeSearchQuery query = new NativeSearchQueryBuilder()
            .addAggregation(AggregationBuilders.avg("avg_age").field("age"))
            .addAggregation(AggregationBuilders.terms("age_distribution")
                .field("age")
                .size(100))
            .build();
        
        SearchHits<UserDocument> hits = elasticsearchTemplate.search(query, UserDocument.class);
        
        Map<String, Object> stats = new HashMap<>();
        
        // 平均年龄
        Avg avgAge = hits.getAggregations().get("avg_age");
        stats.put("avgAge", avgAge.getValue());
        
        // 年龄分布
        Terms ageDistribution = hits.getAggregations().get("age_distribution");
        Map<String, Long> distribution = new HashMap<>();
        for (Terms.Bucket bucket : ageDistribution.getBuckets()) {
            distribution.put(bucket.getKeyAsString(), bucket.getDocCount());
        }
        stats.put("ageDistribution", distribution);
        
        return stats;
    }
}

4.6 Controller 层

java 复制代码
@RestController
@RequestMapping("/api/users")
@Slf4j
public class UserController {
    
    @Autowired
    private UserService userService;

    /**
     * 创建用户
     */
    @PostMapping
    public ResponseEntity<UserDocument> createUser(@RequestBody UserDocument user) {
        UserDocument saved = userService.saveUser(user);
        return ResponseEntity.ok(saved);
    }

    /**
     * 批量创建
     */
    @PostMapping("/batch")
    public ResponseEntity<Void> batchCreate(@RequestBody List<UserDocument> users) {
        userService.batchSaveUsers(users);
        return ResponseEntity.ok().build();
    }

    /**
     * 查询用户
     */
    @GetMapping("/{id}")
    public ResponseEntity<UserDocument> getUser(@PathVariable String id) {
        return userService.getUserById(id)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }

    /**
     * 搜索用户
     */
    @GetMapping("/search")
    public ResponseEntity<List<UserDocument>> search(
            @RequestParam String keyword,
            @RequestParam(required = false) Integer minAge,
            @RequestParam(required = false) Integer maxAge) {
        
        minAge = minAge != null ? minAge : 0;
        maxAge = maxAge != null ? maxAge : 150;
        
        List<UserDocument> users = userService.searchUsers(keyword, minAge, maxAge);
        return ResponseEntity.ok(users);
    }

    /**
     * 删除用户
     */
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable String id) {
        userService.deleteUser(id);
        return ResponseEntity.ok().build();
    }

    /**
     * 获取统计信息
     */
    @GetMapping("/stats")
    public ResponseEntity<Map<String, Object>> getStats() {
        return ResponseEntity.ok(userService.getUserStats());
    }
}

五、Logstash 日志收集

5.1 Logstash 配置文件

logstash/config/logstash.yml:

yaml 复制代码
http.host: "0.0.0.0"
xpack.monitoring.enabled: false

logstash/pipeline/logstash.conf:

conf 复制代码
input {
  # TCP 输入
  tcp {
    port => 5044
    codec => json_lines
  }
  
  # File 输入(读取日志文件)
  file {
    path => "/var/log/app/*.log"
    start_position => "beginning"
    sincedb_path => "/dev/null"
    codec => json
  }
}

filter {
  # 解析日期
  date {
    match => ["timestamp", "yyyy-MM-dd HH:mm:ss.SSS"]
    target => "@timestamp"
  }
  
  # 添加字段
  mutate {
    add_field => { "environment" => "production" }
  }
  
  # 删除不需要的字段
  mutate {
    remove_field => ["host", "port"]
  }
}

output {
  # 输出到 Elasticsearch
  elasticsearch {
    hosts => ["http://elasticsearch:9200"]
    index => "app-logs-%{+YYYY.MM.dd}"
  }
  
  # 控制台输出(调试用)
  stdout {
    codec => rubydebug
  }
}

5.2 Spring Boot 发送日志到 Logstash

添加依赖:

xml 复制代码
<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>7.4</version>
</dependency>

logback-spring.xml 配置:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    
    <!-- 控制台输出 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    
    <!-- Logstash 输出 -->
    <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <destination>localhost:5044</destination>
        <encoder class="net.logstash.logback.encoder.LogstashEncoder">
            <customFields>{"app_name":"my-application","environment":"production"}</customFields>
        </encoder>
    </appender>
    
    <!-- Root Logger -->
    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="LOGSTASH"/>
    </root>
    
    <!-- 特定包的日志级别 -->
    <logger name="com.example" level="DEBUG"/>
    
</configuration>

5.3 测试日志发送

java 复制代码
@RestController
@Slf4j
public class TestController {
    
    @GetMapping("/test/log")
    public String testLog() {
        log.info("这是一条INFO日志");
        log.warn("这是一条WARN日志");
        log.error("这是一条ERROR日志");
        
        // 结构化日志
        Map<String, Object> data = new HashMap<>();
        data.put("userId", 123);
        data.put("action", "login");
        data.put("ip", "192.168.1.100");
        
        log.info("用户操作: {}", data);
        
        return "日志已发送";
    }
}

六、Kibana 数据可视化

6.1 访问 Kibana

复制代码
URL: http://localhost:5601

6.2 创建索引模式

  1. 进入 Stack ManagementIndex Patterns
  2. 点击 Create index pattern
  3. 输入索引模式:app-logs-*
  4. 选择时间字段:@timestamp
  5. 点击 Create index pattern

6.3 查看日志

  1. 进入 Discover 页面
  2. 选择索引模式:app-logs-*
  3. 设置时间范围
  4. 查看和搜索日志

搜索示例:

复制代码
message: "ERROR"
level: "ERROR"
app_name: "my-application"

6.4 创建可视化图表

柱状图:日志级别分布
  1. 进入 Visualize LibraryCreate visualization
  2. 选择 Vertical Bar
  3. 选择索引模式
  4. 配置:
    • X轴:level.keyword
    • Y轴:Count
折线图:日志量趋势
  1. 选择 Line
  2. 配置:
    • X轴:@timestamp(按小时聚合)
    • Y轴:Count
饼图:错误类型分布
  1. 选择 Pie
  2. 配置:
    • Split slices:error_type.keyword
    • 过滤器:level: "ERROR"

6.5 创建 Dashboard

  1. 进入 DashboardCreate new dashboard
  2. 点击 Add from library
  3. 添加之前创建的可视化图表
  4. 调整布局和大小
  5. 保存 Dashboard

七、实战项目:应用日志管理系统

7.1 项目结构

复制代码
log-management/
├── config/
│   ├── ElasticsearchConfig.java
│   └── LogstashConfig.java
├── document/
│   ├── AppLogDocument.java
│   └── ErrorLogDocument.java
├── repository/
│   ├── AppLogRepository.java
│   └── ErrorLogRepository.java
├── service/
│   ├── LogService.java
│   └── LogAnalysisService.java
└── controller/
    └── LogController.java

7.2 日志文档定义

java 复制代码
@Data
@Document(indexName = "app-logs")
public class AppLogDocument {
    
    @Id
    private String id;
    
    @Field(type = FieldType.Keyword)
    private String appName;
    
    @Field(type = FieldType.Keyword)
    private String level;
    
    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String message;
    
    @Field(type = FieldType.Keyword)
    private String logger;
    
    @Field(type = FieldType.Keyword)
    private String thread;
    
    @Field(type = FieldType.Date, format = DateFormat.date_time)
    private LocalDateTime timestamp;
    
    @Field(type = FieldType.Keyword)
    private String environment;
    
    @Field(type = FieldType.Object)
    private Map<String, Object> additionalData;
}

7.3 日志服务

java 复制代码
@Service
@Slf4j
public class LogService {
    
    @Autowired
    private ElasticsearchRestTemplate elasticsearchTemplate;

    /**
     * 保存日志
     */
    public void saveLog(AppLogDocument logDocument) {
        if (logDocument.getTimestamp() == null) {
            logDocument.setTimestamp(LocalDateTime.now());
        }
        
        IndexQuery indexQuery = new IndexQueryBuilder()
            .withId(logDocument.getId())
            .withObject(logDocument)
            .build();
        
        elasticsearchTemplate.index(indexQuery, IndexCoordinates.of("app-logs"));
    }

    /**
     * 查询日志
     */
    public List<AppLogDocument> searchLogs(String keyword, String level, 
                                           LocalDateTime startTime, LocalDateTime endTime,
                                           int page, int size) {
        
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        
        // 关键字搜索
        if (StringUtils.hasText(keyword)) {
            boolQuery.must(QueryBuilders.multiMatchQuery(keyword, "message", "logger"));
        }
        
        // 日志级别过滤
        if (StringUtils.hasText(level)) {
            boolQuery.filter(QueryBuilders.termQuery("level", level));
        }
        
        // 时间范围过滤
        if (startTime != null && endTime != null) {
            boolQuery.filter(QueryBuilders.rangeQuery("timestamp")
                .gte(startTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME))
                .lte(endTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)));
        }
        
        NativeSearchQuery query = new NativeSearchQueryBuilder()
            .withQuery(boolQuery)
            .withSort(SortBuilders.fieldSort("timestamp").order(SortOrder.DESC))
            .withPageable(PageRequest.of(page, size))
            .build();
        
        SearchHits<AppLogDocument> hits = elasticsearchTemplate.search(
            query, AppLogDocument.class, IndexCoordinates.of("app-logs")
        );
        
        return hits.stream()
            .map(SearchHit::getContent)
            .collect(Collectors.toList());
    }

    /**
     * 统计日志数量
     */
    public Map<String, Long> countLogsByLevel(LocalDateTime startTime, LocalDateTime endTime) {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        
        if (startTime != null && endTime != null) {
            boolQuery.filter(QueryBuilders.rangeQuery("timestamp")
                .gte(startTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME))
                .lte(endTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)));
        }
        
        NativeSearchQuery query = new NativeSearchQueryBuilder()
            .withQuery(boolQuery)
            .addAggregation(AggregationBuilders.terms("level_count")
                .field("level")
                .size(10))
            .build();
        
        SearchHits<AppLogDocument> hits = elasticsearchTemplate.search(
            query, AppLogDocument.class, IndexCoordinates.of("app-logs")
        );
        
        Terms terms = hits.getAggregations().get("level_count");
        Map<String, Long> result = new HashMap<>();
        
        for (Terms.Bucket bucket : terms.getBuckets()) {
            result.put(bucket.getKeyAsString(), bucket.getDocCount());
        }
        
        return result;
    }
}

八、常见问题与解决方案

8.1 Elasticsearch 连接失败

问题: Connection refused

解决方案:

bash 复制代码
# 检查 ES 是否启动
docker ps | grep elasticsearch

# 查看 ES 日志
docker logs elasticsearch

# 检查端口
curl http://localhost:9200

8.2 中文分词问题

问题: 中文搜索不准确

解决方案:安装 IK 分词器

bash 复制代码
# 进入 ES 容器
docker exec -it elasticsearch bash

# 安装 IK 分词器
bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v8.11.0/elasticsearch-analysis-ik-8.11.0.zip

# 重启 ES
exit
docker restart elasticsearch

使用 IK 分词器:

java 复制代码
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
private String content;

8.3 内存不足

问题: OutOfMemoryError

解决方案:

yaml 复制代码
# docker-compose.yml
environment:
  - "ES_JAVA_OPTS=-Xms1g -Xmx1g"

九、总结与展望

9.1 本文要点回顾

ELK 基础概念 :理解三大组件的作用

Elasticsearch 操作 :索引、文档、DSL 查询

Spring Boot 集成 :完整配置与代码实现

Logstash 日志收集 :配置文件与日志发送

Kibana 可视化 :索引模式、图表、Dashboard

实战案例:应用日志管理系统

9.2 下篇预告

在下一篇文章《ELK 从入门到精通:Spring Boot 实战三部曲(二)------ 进阶特性与性能优化》中,我们将深入探讨:

  • 🔍 Elasticsearch 高级查询与聚合
  • ⚡ 性能优化技巧与调优实战
  • 🔄 Logstash 高级过滤与处理
  • 📊 Kibana 高级可视化与告警
  • 🛡️ 安全加固与权限控制
  • 💾 数据备份与恢复

9.3 学习建议

  1. 动手实践:亲自搭建 ELK 环境,运行示例代码
  2. 理解原理:不仅要会用,更要理解底层机制
  3. 关注性能:生产环境必须考虑性能和资源消耗
  4. 善用文档:官方文档是最好的学习资料

📚 参考资料


觉得有用?欢迎点赞、收藏、转发!

下一篇更精彩,敬请期待! 🚀

系列文章:

  • 第一篇 ELK 从入门到精通:Spring Boot 实战三部曲(一)------ 基础核心与快速上手
  • 第二篇 ELK 从入门到精通:Spring Boot 实战三部曲(二)------ 进阶特性与性能优化
  • 第三篇 ELK 从入门到精通:Spring Boot 实战三部曲(三)------ 高级应用与架构设计
相关推荐
土狗TuGou1 小时前
SQL内功笔记 · 第5篇:SQL逻辑执行顺序
数据库·笔记·后端·sql·mysql
MaCa .BaKa1 小时前
56-非遗手工艺品定制平台系统
java·vue.js·spring boot·mysql·maven·非遗手工制作平台系统·非遗制作
为思念酝酿的痛10 小时前
POSIX信号量
linux·运维·服务器·后端
小羊在睡觉10 小时前
力扣84. 柱状图中最大的矩形
后端·算法·leetcode·golang·go
swipe11 小时前
Neo4j + Graph RAG 医疗知识图谱工程实践:患者教育问答真正需要的是“关系可追溯”
后端·langchain·llm
源码宝11 小时前
MES系统源码:Java8 + SpringBoot2.7 + MySQL8 + Redis,后端源码清爽易扩展
java·后端·源码·springboot·mes系统·源码二开·mes源码
金銀銅鐵12 小时前
[Java] 如何理解 class 文件中方法的 descriptor?
java·后端
村口张大爷12 小时前
05 — 分层架构与依赖倒置
后端·架构·系统架构
憧憬成为java架构高手的小白12 小时前
苍穹外卖--day09
java·spring boot·百度