第28课:统一日志收集、ELK搭建 & 线上问题排查体系

文章目录

适配版本 :Elasticsearch 8.15、Logstash 8.15、Kibana 8.15、Spring Boot 4.0.8、SkyWalking 10.4.0、JDK 21

课程定位:监控追踪阶段收官,从日志规范到ELK搭建,从链路ID联动到线上问题排查,构建完整的可观测性闭环

一、开篇:可观测性的最后一块拼图

第25-27课我们完成了监控体系的两大支柱:指标(Metrics) 和链路追踪(Tracing) 。Prometheus+Grafana告诉你"系统当前状态如何",SkyWalking告诉你"一个请求经过了哪些服务、每段耗时多少"。

但这两者都无法回答最后一类问题:"系统在某个时刻到底发生了什么?"

指标是聚合数据------http_server_requests_seconds的P95延迟是3秒,但你看不到这3秒里究竟哪条SQL执行了、哪个参数导致了慢查询、堆栈里报了什么异常。链路追踪记录了Span的耗时和状态码,但Span的详细异常堆栈、业务上下文信息,只能通过日志获取。

更重要的是,当线上出现问题时,运维人员的第一反应往往是查日志 。错误码是什么?异常堆栈是什么?请求参数是什么?这些问题的答案都在日志里。但如果日志散落在20个服务的20台机器上,排查一个跨服务的问题可能需要登录5台服务器、grep几十个文件------效率极低。

ELK(Elasticsearch + Logstash + Kibana) 正是为解决这个问题而生的。它将所有服务的日志集中收集、统一存储、全文检索,配合SkyWalking的TraceID,实现"一键从链路跳转到该请求在所有服务中的完整日志"的排查体验。

本课将从日志规范讲起,完成ELK的搭建和Logback的集成,实战基于TraceID的全链路日志检索,最后总结线上问题排查的标准流程。

二、日志规范与分级

2.1 日志分级原则

Java生态中广泛使用的SLF4J定义了五个日志级别,每个级别有明确的语义和适用场景:

级别 语义 适用场景 生产环境
ERROR 系统出现错误,需要人工介入 业务异常、系统异常、外部调用失败 ✅ 必须输出
WARN 潜在问题,不影响当前请求 降级触发、重试成功、资源接近阈值 ✅ 建议输出
INFO 关键业务流程节点 请求入口/出口、订单创建、支付回调 ✅ 核心链路输出
DEBUG 调试信息 方法参数、中间变量、SQL语句 ❌ 生产关闭
TRACE 最细粒度追踪 循环内部、框架底层 ❌ 生产关闭

生产环境日志级别配置原则:

  • 根日志级别设为INFO:避免DEBUG/TRACE导致日志量爆炸
  • 核心业务包设为INFO或DEBUG :com.example.microservice包下设为INFO,排查时临时调整为DEBUG
  • 框架包设为WARN :org.springframework、org.apache等框架包设为WARN,减少噪音日志
  • 动态调整 :通过Actuator的/actuator/loggers端点动态修改日志级别,无需重启

2.2 日志内容规范

一条合格的日志应包含以下要素:

要素 说明 示例
时间戳 精确到毫秒 2026-09-13 10:30:15.123
TraceID 链路追踪ID,用于跨服务串联 a1b2c3d4e5f6.1234567890.123456.01
线程名 便于分析并发问题 http-nio-8081-exec-1
日志级别 ERROR/WARN/INFO/DEBUG INFO
类名 精简后的类名 c.e.m.u.c.UserController
日志内容 结构化的业务信息 查询用户: id=1, cost=45ms

Logback配置模板:

xml 复制代码
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} - %msg%n</pattern>

2.3 结构化日志最佳实践

反模式一:字符串拼接 。字符串拼接无论日志级别是否生效,都会执行拼接操作,浪费CPU。应使用占位符写法:

java 复制代码
// ❌ 错误:字符串拼接
log.debug("用户信息: " + JSON.toJSONString(user));

// ✅ 正确:占位符写法(日志级别不生效时,不会执行序列化)
log.debug("用户信息: {}", JSON.toJSONString(user));

反模式二:在循环中打日志。循环中的日志会指数级放大日志量,应改为批量输出或采样输出。

反模式三:异常只打message不打堆栈 。log.error("异常: " + e.getMessage())会丢失异常堆栈,排查时无从下手:

java 复制代码
// ❌ 错误:丢失堆栈
log.error("调用失败: " + e.getMessage());

// ✅ 正确:传入异常对象,SLF4J会自动打印堆栈
log.error("调用用户服务失败: userId={}", userId, e);

2.4 敏感信息脱敏

生产环境的日志绝不能包含以下信息:

敏感类型 示例 脱敏方式
密码 password=123456 password=***
手机号 13812345678 138****5678
身份证 110101199001011234 110101********1234
银行卡 6222021234567890123 6222***********0123
Token Bearer eyJhbGci... Bearer ***

脱敏方案 :通过Logback的MessageConverter或自定义Layout实现全局脱敏,或在业务代码中通过工具类脱敏。

三、ELK架构与部署

3.1 为什么选择ELK

ELK是Elasticsearch + Logstash + Kibana的缩写,后来加入了Filebeat(轻量级日志采集器),架构演进为Filebeat + Logstash + Elasticsearch + Kibana:

组件 职责 部署位置
Filebeat 轻量级日志采集,监听日志文件变化 每台应用服务器
Logstash 日志解析、过滤、格式化 独立服务器或Kafka后
Elasticsearch 日志存储和全文检索 集群部署
Kibana 日志查询和可视化 独立服务器

为什么用Filebeat而非Logstash采集? Logstash基于JVM,资源消耗大(至少1G内存)。Filebeat基于Go,资源消耗极小(几十MB),适合在每台应用服务器上部署。

为什么需要Logstash? Filebeat只能做简单的多行合并和字段添加,复杂的日志解析(如从日志中提取TraceID、业务字段)需要Logstash的Grok过滤器完成。

3.2 Docker Compose部署ELK

创建docker-compose.yml:

yaml 复制代码
version: '3.8'
services:
  elasticsearch:
    image: elasticsearch:8.15.0
    container_name: elasticsearch
    environment:
      - discovery.type=single-node
      - ES_JAVA_OPTS=-Xms2g -Xmx2g
      - xpack.security.enabled=false
    ports:
      - "9200:9200"
    volumes:
      - es-data:/usr/share/elasticsearch/data

  logstash:
    image: logstash:8.15.0
    container_name: logstash
    volumes:
      - ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
    ports:
      - "5044:5044"
    depends_on:
      - elasticsearch

  kibana:
    image: kibana:8.15.0
    container_name: kibana
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    ports:
      - "5601:5601"
    depends_on:
      - elasticsearch

volumes:
  es-data:

3.3 Logstash管道配置

创建logstash.conf:

ruby 复制代码
input {
  beats {
    port => 5044
  }
}

filter {
  # 解析Spring Boot的默认日志格式
  grok {
    match => {
      "message" => "%{TIMESTAMP_ISO8601:timestamp} \[%{DATA:traceId}\] \[%{DATA:thread}\] %{LOGLEVEL:level} %{DATA:logger} - %{GREEDYDATA:msg}"
    }
  }

  # 解析JSON格式的日志(如果日志内容本身是JSON)
  json {
    source => "msg"
    target => "logDetail"
    skip_on_invalid_json => true
  }

  # 提取异常类型
  if [msg] =~ /Exception/ {
    grok {
      match => { "msg" => "%{JAVACLASS:exceptionType}: %{GREEDYDATA:exceptionMessage}" }
    }
  }

  # 移除不需要的字段
  mutate {
    remove_field => ["@version", "agent", "ecs", "host", "input", "log", "tags"]
  }
}

output {
  elasticsearch {
    hosts => ["http://elasticsearch:9200"]
    index => "spring-logs-%{+YYYY.MM.dd}"
  }
}

关键配置解读:

配置 作用
grok 从日志文本中提取结构化字段(时间戳、TraceID、日志级别等)
json 如果日志内容本身是JSON,解析为结构化字段
index 按天创建索引,便于生命周期管理和清理

3.4 Filebeat配置

在每台应用服务器上安装Filebeat,配置filebeat.yml:

yaml 复制代码
filebeat.inputs:
  - type: log
    enabled: true
    paths:
      - /var/log/microservice/*.log
    multiline:
      pattern: '^\d{4}-\d{2}-\d{2}'
      negate: true
      match: after
    fields:
      service: service-user
      env: prod

output.logstash:
  hosts: ["logstash:5044"]

关键配置解读:

配置 作用
multiline 多行合并------以日期开头的行是日志的开始,异常堆栈等不以日期开头的行合并到上一行
fields.service 添加服务名标签,便于在Kibana中按服务筛选

踩坑提示 :如果日志中包含\n的多行异常堆栈,Filebeat会将其拆分为多条独立日志。multiline配置是必须的,否则异常堆栈在Kibana中会显示为多条碎片。

四、Logback集成与TraceID注入

4.1 Spring Boot 4.0的Logback配置

创建logback-spring.xml,放在src/main/resources下:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <springProperty scope="context" name="APP_NAME" source="spring.application.name"/>

    <!-- 控制台输出 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 文件输出(JSON格式,便于ELK解析) -->
    <appender name="FILE_JSON" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/${APP_NAME}.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>logs/${APP_NAME}.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
            <maxFileSize>100MB</maxFileSize>
            <maxHistory>30</maxHistory>
            <totalSizeCap>5GB</totalSizeCap>
        </rollingPolicy>
        <encoder class="net.logstash.logback.encoder.LogstashEncoder">
            <includeMdcKeyName>tid</includeMdcKeyName>
            <customFields>{"service":"${APP_NAME}"}</customFields>
        </encoder>
    </appender>

    <!-- 异步输出,避免日志阻塞业务线程 -->
    <appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
        <queueSize>8192</queueSize>
        <discardingThreshold>0</discardingThreshold>
        <neverBlock>true</neverBlock>
        <appender-ref ref="FILE_JSON"/>
    </appender>

    <!-- 业务包日志级别 -->
    <logger name="com.example.microservice" level="INFO"/>
    <logger name="org.springframework" level="WARN"/>
    <logger name="org.apache" level="WARN"/>

    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="ASYNC_FILE"/>
    </root>
</configuration>

关键配置解读:

配置 作用
%X{tid} 从MDC中读取tid键(SkyWalking注入的TraceID)
LogstashEncoder 输出JSON格式日志,Logstash无需Grok解析
AsyncAppender 异步输出日志,避免日志I/O阻塞业务线程
neverBlock=true 队列满时丢弃日志而非阻塞业务线程
discardingThreshold=0 不丢弃任何日志

依赖引入:

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

4.2 TraceID注入机制

第27课中,SkyWalking Agent会自动将TraceID注入MDC的tid键。但如果没有使用SkyWalking,可以通过MDC + Filter手动实现:

java 复制代码
@Component
public class TraceIdFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        // 从请求头中获取上游传递的TraceID,没有则生成新的
        String traceId = httpRequest.getHeader("X-Trace-Id");
        if (traceId == null || traceId.isEmpty()) {
            traceId = UUID.randomUUID().toString().replace("-", "");
        }

        try {
            MDC.put("tid", traceId);
            // 将TraceID放入响应头,便于前端排查
            ((HttpServletResponse) response).setHeader("X-Trace-Id", traceId);
            chain.doFilter(request, response);
        } finally {
            MDC.remove("tid");  // 必须清理,避免线程池复用导致串号
        }
    }
}

Feign透传TraceID (第14课的RequestInterceptor):

java 复制代码
@Component
public class TraceIdFeignInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate template) {
        String traceId = MDC.get("tid");
        if (traceId != null) {
            template.header("X-Trace-Id", traceId);
        }
    }
}

踩坑提示 :MDC.remove("tid")必须在finally中执行。Tomcat的线程池会复用线程,如果上一个请求的tid没有被清理,下一个请求的日志中会出现错误的tid------这就是"日志串号"问题。

4.3 异步线程中的TraceID传递

MDC基于ThreadLocal,异步线程无法访问父线程的MDC。需要在任务提交时捕获MDC快照,在任务执行时恢复:

java 复制代码
public class MdcTaskDecorator implements TaskDecorator {

    @Override
    public Runnable decorate(Runnable runnable) {
        // 捕获父线程的MDC
        Map<String, String> contextMap = MDC.getCopyOfContextMap();
        return () -> {
            try {
                // 在子线程中恢复MDC
                if (contextMap != null) {
                    MDC.setContextMap(contextMap);
                }
                runnable.run();
            } finally {
                MDC.clear();
            }
        };
    }
}
java 复制代码
@Configuration
public class AsyncConfig implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(50);
        executor.setQueueCapacity(200);
        executor.setTaskDecorator(new MdcTaskDecorator());  // 关键:注入MDC装饰器
        executor.initialize();
        return executor;
    }
}

五、Kibana日志检索实战

5.1 创建索引模式

首次进入Kibana(http://localhost:5601),需要创建索引模式:

  1. Stack Management → Index Patterns → Create index pattern
  2. 输入spring-logs-*,选择@timestamp作为时间字段
  3. 点击"Create index pattern"

创建后,在Discover页面即可查询日志。

5.2 核心检索语法

按服务筛选:

复制代码
service: "service-user"

按日志级别筛选:

复制代码
level: "ERROR"

按TraceID检索完整链路:

复制代码
traceId: "a1b2c3d4e5f6.1234567890.123456.01"

这是最核心的排查手段 。当SkyWalking中定位到某条慢链路时,复制其TraceID,在Kibana中检索,即可看到该请求在所有服务中的完整日志。

组合查询:

复制代码
service: "service-order" AND level: "ERROR" AND message: "库存不足"

时间范围筛选:Kibana顶部的时间选择器支持相对时间(如"最近15分钟")和绝对时间(如"2026-09-13 10:00:00 到 10:30:00")。

全文检索:

复制代码
"Connection refused"

5.3 从SkyWalking跳转到Kibana

SkyWalking UI支持自定义链路追踪的跳转链接。在SkyWalking的UI配置中,可以为TraceID配置Kibana的跳转URL。配置后,在SkyWalking的链路详情页面中,点击TraceID旁的链接即可直接跳转到Kibana的检索页面,自动填入TraceID查询条件。

实现原理 :SkyWalking UI的config.js中配置traceIdLink模板:

javascript 复制代码
traceIdLink: 'http://kibana:5601/app/discover#/?_a=(query:(query_string:(query:\'traceId:"{traceId}"\')))'

5.4 日志可视化仪表盘

在Kibana中创建日志分析仪表盘,包含以下面板:

面板 查询 可视化类型
日志量趋势 Count by @timestamp 折线图
日志级别分布 Count by level 饼图
各服务ERROR数量 level:ERROR by service 柱状图
Top 10异常类型 level:ERROR by exceptionType 数据表格
慢请求日志 cost > 1000 数据表格

六、线上问题排查体系

6.1 标准排查流程

结合Prometheus、SkyWalking和ELK,线上问题的标准排查流程如下:

复制代码
告警触发(Prometheus Alertmanager)
    │  收到"service-order P95延迟超过3秒"告警
    ▼
① 确认影响范围(Grafana)
    │  查看仪表盘,确认是单个服务还是全局问题
    │  判断是QPS突增、错误率上升还是延迟升高
    ▼
② 定位问题服务(SkyWalking拓扑图)
    │  查看拓扑图,确认是哪个服务首先出现延迟
    │  判断是服务自身问题还是下游依赖问题
    ▼
③ 定位问题接口(SkyWalking链路)
    │  查看Trace详情,找到耗时最高的Span
    │  记录TraceID
    ▼
④ 查看详细日志(Kibana)
    │  用TraceID检索该请求的所有日志
    │  查看异常堆栈、SQL语句、请求参数
    ▼
⑤ 定位根因并修复
    │  根据日志中的异常信息和SQL执行计划定位根因
    │  修复后验证

6.2 真实排查案例

场景 :某天下午,监控告警显示service-order的P95延迟从50ms飙升到3秒。

第一步:确认影响范围。 打开Grafana仪表盘,发现service-order的QPS没有明显变化(约200 QPS),但P95延迟从50ms飙升到3秒。同时,service-order的5xx错误率从0.1%上升到2%。

第二步:定位问题服务。 打开SkyWalking拓扑图,发现service-order → service-user的调用边显示红色(延迟高)。而service-order → service-product的调用边显示正常(绿色)。初步判断问题在service-user。

第三步:定位问题接口。 进入SkyWalking的Trace页面,筛选service-order的慢链路。打开一条耗时3.2秒的链路:

复制代码
[Gateway] GET /api/order/1 (3.2s)
├── [service-order] OrderController.getOrder (3.1s)
│   ├── [service-user] UserClient.getUserById (3.0s)  ← 瓶颈
│   │   └── [service-user] UserController.getUserById (2.95s)
│   │       └── [MySQL] SELECT * FROM user WHERE id=1 (2.9s)  ← 慢SQL

第四步:查看详细日志。 复制该链路的TraceID,在Kibana中检索。日志显示:

复制代码
[service-user] [http-nio-8081-exec-5] INFO  c.e.m.u.c.UserController - 查询用户: id=1
[service-user] [http-nio-8081-exec-5] DEBUG c.e.m.u.mapper.UserMapper - 
  ==> Preparing: SELECT * FROM user WHERE id=?
  ==> Parameters: 1(Long)
  <== Total: 1
  Time: 2900ms

第五步:定位根因。 SELECT * FROM user WHERE id=1耗时2.9秒,但user表数据量只有10万行,id是主键,理论上应该在毫秒级返回。进一步排查发现,该SQL被一个全表扫描的联表查询阻塞------数据库连接池中有大量慢查询占用连接,导致主键查询排队等待。

根因 :service-user的另一个接口/api/user/list执行了全表扫描的联表查询,占满了数据库连接池。

修复 :为/api/user/list的查询添加索引,并限制返回条数。

复盘 :整个排查过程不到10分钟。如果没有ELK和SkyWalking,这个排查可能需要数小时。核心效率提升来自:SkyWalking的拓扑图快速定位了问题服务,TraceID在Kibana中一键检索到了完整日志,日志中的SQL耗时直接指向了根因。

6.3 日志生产优化

优化一:异步日志。 Logback的AsyncAppender将日志写入操作异步化,业务线程只需将日志放入队列即可返回,避免日志I/O阻塞业务线程。

优化二:日志采样。 对于高频日志(如每个请求都打印的入口日志),可以配置采样率:

java 复制代码
// 使用计数采样,每100个请求记录1条
if (counter.incrementAndGet() % 100 == 0) {
    log.info("请求采样: path={}", path);
}

优化三:日志文件滚动策略。 按天+按大小滚动,避免单个日志文件过大:

xml 复制代码
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
    <fileNamePattern>logs/${APP_NAME}.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
    <maxFileSize>100MB</maxFileSize>     <!-- 单文件最大100MB -->
    <maxHistory>30</maxHistory>          <!-- 保留30天 -->
    <totalSizeCap>5GB</totalSizeCap>     <!-- 总大小不超过5GB -->
</rollingPolicy>

优化四:Elasticsearch索引生命周期管理(ILM)。 配置ES的ILM策略,自动清理过期索引:

json 复制代码
{
  "policy": {
    "phases": {
      "hot": { "actions": { "rollover": { "max_size": "50GB", "max_age": "1d" } } },
      "warm": { "min_age": "7d", "actions": { "forcemerge": { "max_num_segments": 1 } } },
      "delete": { "min_age": "30d", "actions": { "delete": {} } }
    }
  }
}

优化五:日志量控制。 生产环境的DEBUG日志会导致日志量暴增。通过/actuator/loggers端点动态调整:

bash 复制代码
# 临时将 service-user 的日志级别调整为 DEBUG
curl -X POST http://localhost:8081/actuator/loggers/com.example.microservice \
  -H "Content-Type: application/json" \
  -d '{"configuredLevel": "DEBUG"}'

# 排查结束后恢复为 INFO
curl -X POST http://localhost:8081/actuator/loggers/com.example.microservice \
  -H "Content-Type: application/json" \
  -d '{"configuredLevel": "INFO"}'

七、踩坑指南

坑一:异步Appender丢失日志

现象:应用关闭时,最后几秒的日志丢失。

原因 :AsyncAppender的队列中还有未消费的日志,应用关闭时队列被直接丢弃。

解决 :配置logback-spring.xml的关闭钩子:

xml 复制代码
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook">
    <delay>5 seconds</delay>
</shutdownHook>

坑二:MDC线程池串号

现象:日志中的TraceID与请求不匹配,出现"串号"。

原因:Tomcat线程池复用线程时,上一个请求的MDC未清理。

解决 :在Filter的finally中执行MDC.clear()(如第4.2节所示)。

坑三:多行日志被拆分为多条

现象:Kibana中异常堆栈被拆成多条独立日志。

原因 :Filebeat未配置multiline,每行作为独立日志发送。

解决 :配置Filebeat的multiline.pattern匹配日志起始格式,将堆栈合并到上一条日志。

坑四:Kibana中字段无法识别

现象 :日志中的traceId字段在Kibana中显示为traceId.keyword,无法直接检索。

原因:Logstash未正确解析日志格式,或索引模式未刷新字段映射。

解决 :使用LogstashEncoder输出JSON格式日志,Logstash无需Grok解析;在Kibana中刷新索引模式的字段列表。

坑五:日志文件过大导致磁盘写满

现象:服务器磁盘被日志文件占满,应用无法写入。

原因:未配置日志滚动策略,或滚动策略配置错误。

解决 :配置SizeAndTimeBasedRollingPolicy,设置maxFileSize、maxHistory和totalSizeCap。

坑六:SkyWalking的TraceID与日志中的TraceID不一致

现象:SkyWalking链路详情中的TraceID与Kibana日志中的TraceID不同。

原因 :SkyWalking的TraceID存储在sw8头中,MDC中的tid可能是其他追踪系统注入的(如Micrometer Tracing)。

解决:确保只使用一种追踪系统。如果使用SkyWalking,关闭Micrometer Tracing的TraceID注入;反之亦然。

八、阶段总结与下节预告

至此,微服务监控、链路追踪、日志体系阶段(第25-28课) 全部完成。回顾这一阶段的核心内容:

课程 核心能力 关键产出
第25课 Actuator端点体系 健康检查、探针、自定义端点、安全配置
第26课 Prometheus+Grafana 指标采集、可视化大盘、告警规则
第27课 SkyWalking链路追踪 调用链路分析、拓扑图、性能瓶颈定位
第28课 ELK日志体系 日志收集、TraceID检索、问题排查体系

四课串联的核心逻辑:Actuator暴露指标和健康状态(第25课)→ Prometheus采集指标并告警(第26课)→ SkyWalking追踪请求链路(第27课)→ ELK集中日志并基于TraceID联动排查(第28课)。指标、链路、日志三大支柱结合,构成完整的可观测性闭环。

第29课将进入微服务高阶特性 & 分布式核心能力阶段 ------微服务异步调用、线程池优化 & 事件驱动开发 。内容包括@Async异步调用、线程池自定义配置、线程池参数优化、异步异常处理、Spring事件驱动和业务解耦实战。可观测性解决了"如何发现问题",异步调用和事件驱动将解决"如何提升性能和解耦"------两者结合,让微服务在高并发场景下既能快速响应,又能保持稳定。

🔗《最新版 SpringCloud 2025 从入门到实战》系列课程导航

去订阅

第一部分:微服务前置基础 & 新版环境搭建(第1-5课)

第二部分:注册中心核心(Nacos 最新版)(第6-9课)

第三部分:配置中心核心(Nacos配置中心)(第10-12课)

第四部分:服务通信核心(OpenFeign + LoadBalancer)(第13-16课)

第五部分:网关核心(SpringCloud Gateway 新版)(第17-20课)

第六部分:熔断、限流、降级(Sentinel 新版)(第21-24课)

第七部分:微服务监控、链路追踪、日志体系(第25-28课)

第八部分:微服务高阶特性 & 分布式核心能力(第29-31课)

第九部分:企业级完整项目实战 & 架构复盘(第32-35课)

相关推荐
来福猿1 天前
Nacos 源码解析:服务注册、配置中心与心跳续约机制
spring·spring cloud
Thomas.Sir1 天前
第27课:SkyWalking全链路追踪实战 & 微服务调用链路分析
spring cloud·微服务·skywalking
野生技术架构师1 天前
Dubbo 还是 Spring Cloud?从架构本质到落地选型
spring cloud·架构·dubbo
Wang's Blog1 天前
Java 项目实战: 交友项目 - 前后端分离的工程实践
java·spring cloud·架构
自强的小白2 天前
项目整个架构的构建和演进。(重点!)
spring cloud·微服务·架构
Thomas.Sir2 天前
第25课:Spring Cloud监控体系详解 & Actuator端点全解
spring cloud·actuator
今年下半年2 天前
【Spring Cloud】Spring Cloud Gateway 防 XSS / 防 CSRF 实现
spring cloud·xss·csrf
Wang's Blog2 天前
Java 项目实战: 交友项目 - SpringCloud 整合 Dubbo 的需求分析与模块规划
java·spring cloud·交友
流烟默2 天前
Spring Cloud 微服务 Sentinel 热点参数与授权规则集成指南(附架构建议)
spring cloud·微服务·架构·sentinel