当前位置:首页>自动驾驶>从救火到自动驾驶:海量日志告警与 K8s 自愈系统的工程落地实战

从救火到自动驾驶:海量日志告警与 K8s 自愈系统的工程落地实战

  • 2026-05-10 15:41:32
从救火到自动驾驶:海量日志告警与 K8s 自愈系统的工程落地实战

从救火到自动驾驶:海量日志告警与 K8s 自愈系统的工程落地实战

真正把 AIOps 做进生产,难点从来不是“能不能识别异常”,而是“在高并发、强噪声、复杂依赖和严格风控下,如何让系统稳定地发现问题、压缩告警、判断根因,并只对适合自动处理的故障做安全自愈”。


一、为什么很多团队做了监控,还是只能靠人肉救火

凌晨 3 点,订单服务大面积超时,手机通知一轮接一轮:

  • • “订单服务 ERROR 1 分钟 3000+”
  • • “库存服务超时率 > 20%”
  • • “支付服务下游调用失败”
  • • “网关 5xx 飙升”
  • • “Pod Restart Count 快速上升”

表面上看,系统已经“全量监控”了:

  • • 应用日志进 Elasticsearch
  • • 指标进 Prometheus
  • • Trace 进 SkyWalking 或 Jaeger
  • • K8s 事件也能查

但一旦真正出故障,团队仍然很难在 1 分钟内回答四个关键问题:

  1. 1. 根因到底在哪个服务、哪个版本、哪个节点、哪类错误?
  2. 2. 哪些告警只是级联现象,哪些才是第一因?
  3. 3. 当前故障是代码问题、容量问题、依赖问题,还是基础设施问题?
  4. 4. 这次能不能自动修,应该重启、扩容、回滚还是熔断降级?

这也是很多“监控平台”停留在可视化层、而没有升级成“自动驾驶系统”的核心原因。监控解决的是“看见”,自动驾驶解决的是“判断”和“行动”。

本文基于一套真实可落地的生产思路,系统讲清楚如何构建一条完整闭环:

  • • 日志与事件统一采集
  • • 流式实时分析与告警降噪
  • • 基于拓扑与规则的根因判定
  • • 安全边界清晰的 K8s 自愈编排
  • • 高并发、可扩展、可回放、可审计的工程化实现

目标不是写一个 demo,而是写出一套真正能在大促、峰值流量和线上事故里站得住的工程方案。


二、先定边界:什么故障适合自动化,什么故障必须人工接管

在设计之前,必须先讲一个经常被忽略的原则:

自动化不是“替代值班”,而是把高置信、低风险、强重复的问题机器化。

通常可以把线上故障分成四类:

故障类型
典型现象
是否适合自动化
常见动作
瞬时资源抖动
单 Pod OOM、短时 GC 抖动、节点网络闪断
适合
重启 Pod、驱逐重调度、临时扩容
依赖退化
下游超时、连接池打满、消息积压
部分适合
熔断、限流、旁路降级、扩容消费者
发布引发故障
新版本错误率飙升、启动失败
适合但需严格风控
自动回滚、暂停发布、锁定流量
数据和业务逻辑错误
脏数据、资金对账异常、业务状态机错乱
不适合直接自动化
升级人工、保留证据、限制影响面

所以,成熟自愈系统的设计目标从来不是“100% 自动修复”,而是:

  • • 自动处理 60% 到 80% 的标准化已知故障
  • • 将误操作率压到极低
  • • 将 MTTD 和 MTTR 大幅降低
  • • 为人工接管保留完整上下文和操作证据

这个边界决定了后面的整个架构:系统必须先做可信判断,再做有限动作,最后还能追溯每一次自动决策。


三、总体架构:从日志采集到自愈执行的闭环

3.1 分层设计

我们把整套系统拆成五层,而不是简单的“日志层 + 告警层 + 自愈层”:

  1. 1. 数据接入层
    负责接入日志、指标、Trace、K8s Event、发布事件。
  2. 2. 实时计算层
    负责结构化、聚合、降噪、异常检测、规则匹配。
  3. 3. 决策编排层
    负责根因候选生成、风险评估、动作选择、限流和熔断。
  4. 4. 执行控制层
    负责调用 K8s API、发布平台、网关、配置中心执行修复动作。
  5. 5. 审计与回放层
    负责记录自动决策链路、支持复盘、模型迭代和规则调优。

3.2 全景链路

                       ┌─────────────────────────────────────┐
                       │           数据接入层                │
                       │ Fluent Bit / Filebeat / OTel       │
                       │ Prometheus / Trace / K8s Events    │
                       └────────────────┬────────────────────┘
                                        │
                              Kafka / Pulsar 消息总线
                                        │
         ┌──────────────────────────────▼──────────────────────────────┐
         │                       实时计算层                             │
         │ Flink: 清洗 → 结构化 → 关联 → 聚合 → 异常检测 → 告警候选     │
         │ Broadcast Rule / CEP / Watermark / RocksDB State           │
         └──────────────────────────────┬──────────────────────────────┘
                                        │
         ┌──────────────────────────────▼──────────────────────────────┐
         │                       决策编排层                             │
         │ Alert Correlator / RCA Engine / Risk Guard / Policy Engine │
         │ 规则树 + 拓扑依赖 + 发布事件 + 历史处置结果                  │
         └──────────────────────────────┬──────────────────────────────┘
                                        │
                ┌───────────────────────▼────────────────────────┐
                │                  执行控制层                    │
                │ K8s API / Argo Rollouts / Service Mesh / Nacos│
                │ Pod 重启 / Deployment 回滚 / HPA 调整 / 降级   │
                └───────────────────────┬────────────────────────┘
                                        │
         ┌──────────────────────────────▼──────────────────────────────┐
         │                    审计与回放层                              │
         │ ES / ClickHouse / S3 / Audit DB / Dashboard / Replay Job   │
         └─────────────────────────────────────────────────────────────┘

3.3 为什么是 Kafka + Flink + Policy Engine + K8s API

这套组合不是“流行技术栈堆砌”,而是能力互补:

  • • Kafka 负责削峰填谷、顺序分区、回放和数据总线解耦。
  • • Flink 负责事件时间语义、状态计算、窗口聚合、流批一体回放。
  • • Policy Engine 负责把“识别异常”和“决定动作”分离,避免把复杂规则写死在流作业里。
  • • K8s API 负责统一执行入口,让回滚、扩容、重启、污点驱逐都具备声明式控制能力。

如果直接把“发现问题”和“执行动作”都写进单个消费者服务,短期能跑,长期一定会遇到三个问题:

  • • 规则迭代会变成频繁发版
  • • 审计链路混乱,难以解释系统为何执行某动作
  • • 动作编排和流量放大场景耦合,扩展性差

所以工程上必须把“检测”“决策”“执行”拆开。


四、核心设计原则:系统能跑稳,靠的是约束而不是聪明

在高并发告警系统里,最危险的不是“漏掉一条告警”,而是“系统自己成为事故放大器”。因此需要先确立四条原则。

4.1 先做结构化,再谈智能

没有结构化日志、统一错误码、标准 TraceId 和环境标签,后面所有智能判断都只是在字符串上碰运气。

最低要求:

  • • 日志必须 JSON 化
  • • 每条日志必须包含 timestamp/service/env/cluster/namespace/pod/trace_id/level/error_code
  • • 错误必须可分类,不能只有 message
  • • 发布版本、Git SHA、节点名必须能被补齐

4.2 先降噪,再告警

真正的线上系统不是“异常出现就报警”,而是“异常聚合成可行动事件再报警”。

降噪至少包含四层:

  • • 同类错误聚合
  • • 链路级联压制
  • • 静默窗口
  • • 重复动作抑制

4.3 先限权,再自愈

自愈引擎必须像一个受限机器人,而不是集群管理员:

  • • 只允许操作白名单 namespace 和 workload
  • • 每种动作单独限流
  • • 每次动作都要带变更原因和审计记录
  • • 高风险动作默认双重确认或仅建议不执行

4.4 先回放验证,再放进生产

所有规则和自愈策略都应该支持离线回放:

  • • 用历史事故日志回放验证误报率
  • • 对比规则调整前后的触发差异
  • • 验证动作链路是否会引发二次伤害

这一步决定系统能否从“脚本集合”进化成“平台能力”。


五、数据模型设计:让日志、告警、动作说同一种语言

5.1 日志事件模型

生产上建议统一成如下模型:

{
  "timestamp"
: "2026-05-10T03:12:00.234Z",
  "service"
: "order-service",
  "env"
: "prod",
  "cluster"
: "cn-hz-prod-01",
  "namespace"
: "trade",
  "pod"
: "order-service-7d7f8d9f4d-km6n2",
  "node"
: "10.10.3.24",
  "trace_id"
: "4f4b7e3b5f9349b1",
  "span_id"
: "0af7651916cd43dd",
  "parent_span_id"
: "b9c7d1e0020a918e",
  "level"
: "ERROR",
  "logger"
: "com.company.order.InventoryClient",
  "error_code"
: "INVENTORY_TIMEOUT",
  "error_type"
: "DependencyTimeout",
  "http_path"
: "/api/v1/order/create",
  "duration_ms"
: 2136,
  "release"
: "order-service:2026.05.10-rc3",
  "message"
: "call inventory timeout after 2000ms"
}

5.2 告警事件模型

流计算输出的不能再是“原始日志”,而应该是“告警候选”:

{
  "alert_id"
: "ALERT-20260510-00001921",
  "fingerprint"
: "prod|trade|order-service|INVENTORY_TIMEOUT",
  "service"
: "order-service",
  "error_code"
: "INVENTORY_TIMEOUT",
  "severity"
: "P1",
  "window_start"
: 1746846720000,
  "window_end"
: 1746847020000,
  "count"
: 18342,
  "sample_trace_ids"
: ["4f4b7e3b5f9349b1", "f35ce11d818c2231"],
  "suspect_release"
: "order-service:2026.05.10-rc3",
  "suspect_node_ratio"
: {
    "10.10.3.24"
: 0.61,
    "10.10.3.28"
: 0.18
  }
,
  "upstream_services"
: ["gateway-service"],
  "downstream_services"
: ["inventory-service"],
  "confidence"
: 0.93
}

5.3 自愈动作模型

动作一定要标准化,否则审计和回滚都很难做:

{
  "action_id"
: "ACT-20260510-000331",
  "alert_id"
: "ALERT-20260510-00001921",
  "action_type"
: "ROLLING_RESTART",
  "target_kind"
: "Deployment",
  "target_name"
: "inventory-service",
  "namespace"
: "trade",
  "risk_level"
: "LOW",
  "operator"
: "auto-heal-engine",
  "reason"
: "single-pod-oom-with-high-confidence",
  "cooldown_ms"
: 600000,
  "max_retry"
: 1,
  "status"
: "PENDING"
}

当日志、告警、动作三层模型统一后,系统才能做到:

  • • 上游可扩展
  • • 中间规则可配置
  • • 下游动作可审计、可追责、可回放

六、采集层工程化:高吞吐日志接入不是把 Filebeat 跑起来就够了

6.1 采集层设计目标

采集层不是简单搬运工,它必须完成三件事:

  1. 1. 不丢关键日志
  2. 2. 尽量早地补齐上下文
  3. 3. 在入口处就做好流量控制和字段清洗

6.2 Fluent Bit / Filebeat DaemonSet 关键配置

下面给出一份更贴近生产的 Filebeat 配置。重点不在语法,而在几个工程点:

  • • 多行异常合并
  • • 补充 K8s 元数据
  • • 控制内存队列
  • • 输出 Kafka 做削峰
  • • 对采集失败做有限重试
filebeat.inputs:
  -
 type: container
    enabled:
 true
    paths:

      -
 /var/log/containers/*.log
    stream:
 all
    processors:

      -
 add_kubernetes_metadata:
          host:
 ${NODE_NAME}
          matchers:

            -
 logs_path:
                logs_path:
 /var/log/containers/
      -
 decode_json_fields:
          fields:
 ["message"]
          target:
 ""
          overwrite_keys:
 true
          add_error_key:
 true
    multiline.pattern:
 '^[[:space:]]+(at|\.{3})\b|^Caused by:'
    multiline.negate:
 false
    multiline.match:
 after
    close_inactive:
 5m
    clean_inactive:
 72h
    ignore_older:
 24h

queue.mem:

  events:
 4096
  flush.min_events:
 512
  flush.timeout:
 1s

output.kafka:

  hosts:
 ["kafka-1:9092", "kafka-2:9092", "kafka-3:9092"]
  topic:
 "raw-logs"
  partition.round_robin:

    reachable_only:
 true
  required_acks:
 1
  compression:
 gzip
  max_message_bytes:
 1048576
  channel_buffer_size:
 2048
  backoff.init:
 1s
  backoff.max:
 60s

logging.level:
 info
monitoring.enabled:
 true
http.enabled:
 true
http.host:
 0.0.0.0
http.port:
 5066

6.3 采集层常见坑

最容易被忽略的是下面几类:

  • • 应用把日志写文件,不走 stdout/stderr
  • • 日志不是 JSON,字段只能靠正则抠
  • • 不同团队打的时间戳格式不一致
  • • 多行异常没合并,导致一条错误被拆成几十条
  • • 容器日志轮转和采集器读取 offset 处理不当,产生重复数据

如果这些基础问题不解决,后面的 Flink、规则引擎和自愈系统只是建立在脏数据上的空中楼阁。


七、实时计算层:Flink 如何把海量日志变成可行动告警

7.1 为什么告警分析要用流式而不是定时批处理

核心原因有三个:

  • • 告警响应要求秒级,批处理天然延迟高
  • • 根因压制依赖窗口态和事件序列
  • • 动态规则需要实时生效

Flink 在这里的优势不是“快”,而是它对以下能力的统一支持:

  • • 事件时间
  • • 状态管理
  • • Broadcast State
  • • CEP
  • • Checkpoint
  • • Savepoint 回放

7.2 计算链路拆分

不要把所有逻辑塞进一个算子。更合理的链路是:

  1. 1. RawLog -> StructuredLog
  2. 2. StructuredLog -> EnrichedLog
  3. 3. EnrichedLog -> AggregatedSignal
  4. 4. AggregatedSignal -> CorrelatedAlert
  5. 5. CorrelatedAlert -> ActionSuggestion

这样做的好处:

  • • 每一层职责单一
  • • 方便回放和调试
  • • 中间结果可落盘,支持可观测性
  • • 后续可插入模型或规则,不需要重构整条链路

7.3 生产级 Flink 作业骨架

下面是一份更接近生产的作业骨架,重点体现在:

  • • 开启 checkpoint
  • • 使用事件时间与 watermark
  • • 规则流广播
  • • 主数据流先清洗再聚合
public class AlertPipelineJob {

    public
 static void main(String[] args) throws Exception {
        StreamExecutionEnvironment
 env = StreamExecutionEnvironment.getExecutionEnvironment();

        env.enableCheckpointing(30000L, CheckpointingMode.EXACTLY_ONCE);
        env.getCheckpointConfig().setMinPauseBetweenCheckpoints(10000L);
        env.getCheckpointConfig().setCheckpointTimeout(120000L);
        env.getCheckpointConfig().setTolerableCheckpointFailureNumber(3);
        env.setStateBackend(new EmbeddedRocksDBStateBackend(true));
        env.getConfig().setAutoWatermarkInterval(1000L);

        KafkaSource<String> rawLogSource = KafkaSource.<String>builder()
            .setBootstrapServers("kafka-1:9092,kafka-2:9092,kafka-3:9092")
            .setTopics("raw-logs")
            .setGroupId("alert-pipeline-v1")
            .setStartingOffsets(OffsetsInitializer.latest())
            .build();

        DataStream<StructuredLog> logs = env
            .fromSource(rawLogSource, WatermarkStrategy.noWatermarks(), "raw-log-source")
            .flatMap(new JsonLogParser())
            .name("parse-json-log")
            .assignTimestampsAndWatermarks(
                WatermarkStrategy
                    .<StructuredLog>forBoundedOutOfOrderness(Duration.ofSeconds(30))
                    .withTimestampAssigner((event, ts) -> event.getTimestamp())
            )
            .name("assign-watermark")
            .filter(StructuredLog::isError)
            .name("filter-error-log");

        MapStateDescriptor<String, AlertRule> ruleStateDescriptor =
            new
 MapStateDescriptor<>("alert-rules", Types.STRING, Types.POJO(AlertRule.class));

        DataStream<AlertRule> ruleStream = env
            .fromSource(buildRuleSource(), WatermarkStrategy.noWatermarks(), "rule-source");

        BroadcastStream<AlertRule> broadcastRules = ruleStream.broadcast(ruleStateDescriptor);

        DataStream<AlertCandidate> candidates = logs
            .keyBy(StructuredLog::fingerprint)
            .connect(broadcastRules)
            .process(new AlertEvaluateProcessFunction(ruleStateDescriptor))
            .name("evaluate-alert-candidate");

        DataStream<CorrelatedAlert> alerts = candidates
            .keyBy(AlertCandidate::getFingerprint)
            .process(new RootCauseCorrelator())
            .name("root-cause-correlator");

        alerts.sinkTo(buildAlertSink()).name("alert-sink");

        env.execute("alert-pipeline-job");
    }
}

7.4 关键算子:动态规则 + 静默窗口 + 状态清理

下面这段代码演示告警候选判断的核心思路。它没有把所有复杂逻辑堆进去,但已经体现了生产需要的三个点:

  • • 动态规则广播
  • • Keyed State 记录窗口计数与最近告警时间
  • • TTL 控制状态膨胀
public class AlertEvaluateProcessFunction extends KeyedBroadcastProcessFunction<String, StructuredLog, AlertRule, AlertCandidate> {

    private
 final MapStateDescriptor<String, AlertRule> ruleDescriptor;
    private
 transient ValueState<Integer> hitCountState;
    private
 transient ValueState<Long> lastAlertTsState;

    public
 AlertEvaluateProcessFunction(MapStateDescriptor<String, AlertRule> ruleDescriptor) {
        this
.ruleDescriptor = ruleDescriptor;
    }

    @Override

    public
 void open(Configuration parameters) {
        StateTtlConfig
 ttlConfig = StateTtlConfig
            .newBuilder(org.apache.flink.api.common.time.Time.hours(1))
            .setUpdateType(StateTtlConfig.UpdateType.OnCreateAndWrite)
            .neverReturnExpired()
            .build();

        ValueStateDescriptor<Integer> countDescriptor = new ValueStateDescriptor<>("hit-count", Integer.class);
        countDescriptor.enableTimeToLive(ttlConfig);
        hitCountState = getRuntimeContext().getState(countDescriptor);

        ValueStateDescriptor<Long> lastDescriptor = new ValueStateDescriptor<>("last-alert-ts", Long.class);
        lastDescriptor.enableTimeToLive(ttlConfig);
        lastAlertTsState = getRuntimeContext().getState(lastDescriptor);
    }

    @Override

    public
 void processElement(StructuredLog event, ReadOnlyContext ctx, Collector<AlertCandidate> out) throws Exception {
        ReadOnlyBroadcastState<String, AlertRule> rules = ctx.getBroadcastState(ruleDescriptor);
        AlertRule
 rule = rules.get(event.fingerprint());
        if
 (rule == null || !rule.isEnabled()) {
            return
;
        }

        Integer
 current = Optional.ofNullable(hitCountState.value()).orElse(0);
        current = current + 1;
        hitCountState.update(current);

        Long
 lastAlertTs = Optional.ofNullable(lastAlertTsState.value()).orElse(0L);
        long
 eventTs = event.getTimestamp();

        if
 (current >= rule.getThreshold() && eventTs - lastAlertTs >= rule.getSilenceWindowMs()) {
            AlertCandidate
 candidate = AlertCandidate.builder()
                .service(event.getService())
                .errorCode(event.getErrorCode())
                .fingerprint(event.fingerprint())
                .severity(rule.getSeverity())
                .count(current)
                .sampleTraceId(event.getTraceId())
                .timestamp(eventTs)
                .release(event.getRelease())
                .build();

            out.collect(candidate);
            lastAlertTsState.update(eventTs);
            hitCountState.clear();
        }
    }

    @Override

    public
 void processBroadcastElement(AlertRule rule, Context ctx, Collector<AlertCandidate> out) throws Exception {
        BroadcastState<String, AlertRule> rules = ctx.getBroadcastState(ruleDescriptor);
        rules.put(rule.fingerprint(), rule);
    }
}

7.5 根因压制比阈值告警更重要

生产上最有价值的不是“把错误数算出来”,而是“压制级联噪声”。例如:

  • • inventory-service 出现连接超时
  • • order-service 调库存失败
  • • gateway-service 返回 502

如果三者全部告警,值班同学仍然会被淹没。正确做法是基于调用拓扑和 Trace 关系做抑制:

  • • 下游依赖先报错,且上游错误时序紧随其后
  • • 错误码具备因果映射
  • • 上游错误分布集中在同一依赖路径

那么只保留根告警,其他作为关联告警挂在根告警之下。

这一步可以通过两种方式实现:

  • • 规则型:基于服务依赖拓扑和错误传播规则
  • • 图谱型:基于 Trace、K8s Event、发布事件进行图关联

工程上建议先做规则型,因为可解释性更强、上线成本更低。


八、规则引擎与策略中心:把变化从代码里抽出去

8.1 为什么不能把规则写死在代码里

高峰期和日常期的阈值一定不同,灰度发布和全量发布的策略也一定不同。如果每次调整都要改代码发版,这套系统迟早会拖慢事故处理。

规则中心至少要支持:

  • • 告警阈值动态更新
  • • 静默期动态调整
  • • 白名单与黑名单
  • • 自愈动作开关
  • • 高风险动作审批开关

8.2 规则配置示例

可以把规则存进 Nacos、Apollo 或数据库。下面用 YAML 表达一个典型策略:

alertRules:
  -
 fingerprint: "prod|trade|inventory-service|OOM_KILLED"
    severity:
 "P1"
    threshold:
 3
    windowMs:
 60000
    silenceWindowMs:
 600000
    remediationPolicy:
 "restart-single-pod"
    enabled:
 true

  -
 fingerprint: "prod|trade|order-service|INVENTORY_TIMEOUT"
    severity:
 "P1"
    threshold:
 500
    windowMs:
 300000
    silenceWindowMs:
 300000
    remediationPolicy:
 "circuit-break-and-scale-out"
    enabled:
 true

remediationPolicies:

  restart-single-pod:

    actions:

      -
 type: "ROLLING_RESTART_POD"
        maxRetry:
 1
        cooldownMs:
 600000
        riskLevel:
 "LOW"

  circuit-break-and-scale-out:

    actions:

      -
 type: "ENABLE_DEGRADE_SWITCH"
        maxRetry:
 1
        cooldownMs:
 300000
        riskLevel:
 "MEDIUM"
      -
 type: "PATCH_HPA_MIN_REPLICAS"
        maxRetry:
 1
        cooldownMs:
 600000
        riskLevel:
 "MEDIUM"

8.3 规则和动作要分层

很多系统把“阈值”和“动作”混成一层,最后会越来越难维护。更好的方式是:

  • • AlertRule 只解决“何时形成告警”
  • • RemediationPolicy 只解决“告警后可以做什么”
  • • RiskPolicy 只解决“在什么前提下允许运行”

这能显著降低策略复杂度。


九、自愈系统设计:不是写几个 kubectl 脚本,而是一个受控执行平面

9.1 自愈系统的最小能力集合

一个生产级自愈引擎至少要有以下模块:

  • • Alert Consumer:消费告警事件
  • • Policy Evaluator:匹配动作策略
  • • Risk Guard:判断风险和边界
  • • Executor:调用 K8s、网关、配置中心
  • • Verifier:验证动作后效果
  • • Audit Logger:记录全过程

9.2 自愈决策流程

告警到达
  -> 是否命中白名单策略
  -> 是否超过动作配额 / 熔断阈值
  -> 当前是否处于发布窗口
  -> 是否存在更高优先级根因告警
  -> 选择动作
  -> 执行动作
  -> 冷却观察
  -> 指标回读验证
  -> 成功则关闭 / 失败则升级人工

9.3 责任链式动作编排

下面是一种常见实现方式:把不同动作做成责任链,每个处理器只负责单一动作。

public interface RemediationHandler {
    boolean
 supports(AlertContext context);
    RemediationResult handle(AlertContext context);
}

@Component

public
 class OomRestartHandler implements RemediationHandler {

    private
 final KubernetesRemediationClient kubernetesClient;

    @Override

    public
 boolean supports(AlertContext context) {
        return
 "OOM_KILLED".equals(context.alert().getErrorCode())
            && context.riskDecision().allowAutoAction();
    }

    @Override

    public
 RemediationResult handle(AlertContext context) {
        PodRef
 pod = context.targetPod();
        kubernetesClient.deletePod(pod.namespace(), pod.name(), "auto-heal: oom restart");
        return
 RemediationResult.success("pod deleted for rolling recreation");
    }
}

责任链的价值在于:

  • • 新增动作不需要改核心流程
  • • 不同动作可以独立测试
  • • 每个动作都能有自己的风险控制逻辑

9.4 K8s API 执行层示例

下面示例演示如何安全执行一个 Deployment 级动作。重点不是 SDK 调用,而是动作前后的风控检查和审计。

public class KubernetesRemediationClient {

    private
 final AppsV1Api appsV1Api;
    private
 final CoreV1Api coreV1Api;
    private
 final AuditService auditService;

    public
 void rolloutRestart(String namespace, String deployment, String operator, String reason) throws Exception {
        auditService.recordStart("ROLLING_RESTART", namespace, deployment, operator, reason);

        V1Patch
 patch = new V1Patch("""
            {
              "spec": {
                "template": {
                  "metadata": {
                    "annotations": {
                      "kubectl.kubernetes.io/restartedAt": "%s",
                      "autoheal.operator": "%s",
                      "autoheal.reason": "%s"
                    }
                  }
                }
              }
            }
            """
.formatted(Instant.now(), operator, reason));

        appsV1Api.patchNamespacedDeployment(
            deployment,
            namespace,
            patch,
            null
,
            null
,
            null
,
            null

        );

        auditService.recordSuccess("ROLLING_RESTART", namespace, deployment, operator, reason);
    }

    public
 void rollbackDeployment(String namespace, String deployment, String revision, String operator, String reason) {
        // 这里通常不会直接手写 patch,而是接 Argo Rollouts / 发布平台统一接口。

        // 关键原则是:回滚动作必须经过风险校验和版本可用性校验。

    }
}

9.5 不同故障对应的动作策略

故障模式
观察信号
推荐动作
风险等级
单 Pod OOM
某 Pod restartCount 突增,exitCode=137
删除 Pod 让其重建,必要时调整 requests/limits 建议值
新版本发布后 5xx 飙升
错误率与某 release 强相关
自动暂停灰度并回滚
下游依赖超时
上游大量 timeout,且下游 P99 飙升
开启降级开关,扩容下游,必要时限流
Kafka 消费积压
lag 激增、消费速率下降
扩容消费者、副本重平衡、触发限流
低到中
节点异常
多个 Pod 同节点故障集中
cordon/drain 节点,触发重调度
中到高

这里最关键的一点是:动作是按“故障模式”设计,而不是按“日志关键字”设计。


十、风控体系:自愈系统必须先防止自己作恶

真正成熟的自愈系统,最重要的模块往往不是执行器,而是风控层。

10.1 必须有的四道闸

  1. 1. 动作配额
    同一服务 10 分钟内最多自动处理 3 次。
  2. 2. 冷却窗口
    执行一次动作后,必须等待 60 到 180 秒再允许下一次动作。
  3. 3. 灰度执行
    先处理 1 个 Pod,验证成功后再逐步扩大。
  4. 4. 人工升级
    命中高风险规则、跨服务联动、涉及数据写操作时,自动转人工。

10.2 风险评分示例

可以用一个简单的风险评分模型来辅助判断:

riskScore =
  actionWeight
  + impactedReplicaCountWeight
  + businessPeakWeight
  + releaseWindowWeight
  + recentFailureWeight

例如:

  • • 删除单 Pod:20 分
  • • 回滚 Deployment:50 分
  • • 调整全局限流配置:60 分
  • • 跨多个 namespace 执行动作:80 分

当分值超过阈值时:

  • • 只生成建议,不自动执行
  • • 通知 SRE / 值班负责人确认

10.3 动作后必须验证

没有验证的自愈,不算闭环。验证至少包含:

  • • 错误率是否下降
  • • P95/P99 是否恢复
  • • Pod 是否健康 Ready
  • • Kafka lag 是否回落
  • • 5 分钟内是否再次触发同类告警

如果验证失败,自愈引擎要立刻停止后续动作并升级人工,而不是“再试一次直到彻底把系统打坏”。


十一、高并发与可扩展设计:峰值流量下如何不把自己打爆

这部分是很多文章最容易一笔带过、但在生产中最致命的部分。

11.1 吞吐估算要先做

假设:

  • • 1200 个 Pod
  • • 平均每个 Pod 120 行日志/秒
  • • 高峰期异常日志占比 8%
  • • 单条结构化日志 1.2 KB

那么日志规模大致是:

  • • 总吞吐:144000 行/秒
  • • 峰值数据量:约 170 MB/分钟
  • • 单日数据量:数 TB 级

如果大促、全链路压测或故障风暴下翻 5 到 10 倍,很快就会到百万行/秒量级。

这意味着:

  • • Kafka 分区数要按峰值估算,而不是按平时均值
  • • Flink 并行度不能只按 CPU 配,要按 key 热点和状态体积配
  • • Elasticsearch 不能做所有中间态存储,只适合检索和回查

11.2 Kafka 设计建议

raw-logs 与 alerts 建议拆 topic:

  • • raw-logs:原始日志,按 service 或 namespace hash 分区
  • • structured-logs:结构化中间流,可选
  • • alert-candidates:候选告警
  • • alerts-final:最终根因告警
  • • remediation-actions:动作指令
  • • audit-events:审计事件

核心原则:

  • • 原始流和控制流分离
  • • 大流量 topic 和小流量 topic 分离
  • • 便于单独限流、回放和保留周期管理

11.3 Flink 状态和热点问题

高并发下最常见的两个问题:

  • • 状态太大导致 checkpoint 超时
  • • 热门 key 导致单算子反压

应对方式:

  • • 使用 RocksDB + Incremental Checkpoint
  • • 对告警 key 做合理散列,避免单服务成为极热点
  • • 引入两阶段聚合:先局部聚合,再全局归并
  • • 对长尾低价值日志做采样或旁路处理

11.4 执行层也要限流

很多团队只给 Kafka 和 Flink 做扩展,却忘了执行层也会成为瓶颈。比如:

  • • 1000 条相似告警同时触发
  • • 自愈引擎并发调用 K8s API
  • • API Server QPS 被打满
  • • 控制面反过来影响业务稳定性

因此执行层必须做:

  • • 队列化
  • • 动作去重
  • • 租约锁
  • • 每类动作独立并发池
  • • K8s API QPS 限制

一个简单做法是按目标 workload 做分布式锁,避免同一 Deployment 被多个动作并发操作。


十二、一个完整实战场景:库存服务超时如何从告警走到自愈

下面用一个真实感较强的场景串起整条链路。

12.1 故障背景

大促开始后,inventory-service 某新版本在高并发下连接池泄漏:

  • • P99 从 80ms 飙到 2400ms
  • • INVENTORY_TIMEOUT 错误在 3 分钟内快速放大
  • • order-service 和 payment-service 出现级联超时

12.2 感知层收到的数据

  • • 应用日志中大量 INVENTORY_TIMEOUT
  • • Prometheus 中 inventory-service 的线程池活跃数打满
  • • Trace 中 order -> inventory span 耗时异常集中
  • • 发布平台事件表明 10 分钟前刚发布 inventory-service:2026.05.10-rc3

12.3 实时计算层怎么做

Flink 在 30 秒内完成:

  • • 将原始日志按 service + error_code + release 聚合
  • • 发现 inventory-service 和 rc3 版本高度相关
  • • 压制上游 order-servicepayment-service 的级联告警
  • • 生成一条高置信度根因告警

最终告警可能长这样:

{
  "service"
: "inventory-service",
  "error_code"
: "INVENTORY_TIMEOUT",
  "severity"
: "P1",
  "count"
: 18342,
  "suspect_release"
: "inventory-service:2026.05.10-rc3",
  "confidence"
: 0.96,
  "recommended_action"
: "rollback"
}

12.4 决策层怎么判断动作

策略引擎查询到:

  • • 当前故障强关联新版本
  • • 最近 10 分钟内仅此服务异常
  • • 回滚属于中风险,但该服务在自动回滚白名单
  • • 当前不处于资金结算窗口,可执行

因此给出动作:

  1. 1. 暂停灰度流量
  2. 2. 回滚到上一稳定版本
  3. 3. 冷却观察 2 分钟
  4. 4. 如果错误率仍高,升级人工

12.5 执行层怎么做

  • • 调用发布平台或 Argo Rollouts API 回滚
  • • 写入审计事件
  • • 通知值班群“已自动回滚,观察中”
  • • Verifier 持续拉取 2 分钟错误率

12.6 最终结果

  • • 35 秒内识别根因
  • • 50 秒内触发自动回滚
  • • 90 秒内错误率回落到阈值内
  • • 上游服务级联告警未继续扩散

这就是一条真正有工程价值的闭环:不是多发一条告警,而是把恢复链路缩短到分钟级以内。


十三、代码生产级补全:一个可落地的自愈服务骨架

下面给出一个简化但具备生产思路的 Spring Boot 风格实现骨架。

13.1 告警上下文对象

public record AlertContext(
    CorrelatedAlert alert,
    RemediationPolicy policy,
    RiskDecision riskDecision,
    WorkloadRef workloadRef,
    PodRef targetPod
)
 {
}

13.2 风险决策

public record RiskDecision(
    boolean
 allowAutoAction,
    int
 riskScore,
    String reason
)
 {
    public
 static RiskDecision deny(String reason, int riskScore) {
        return
 new RiskDecision(false, riskScore, reason);
    }

    public
 static RiskDecision allow(String reason, int riskScore) {
        return
 new RiskDecision(true, riskScore, reason);
    }
}

13.3 自愈主流程

@Service
public
 class AutoRemediationService {

    private
 final PolicyService policyService;
    private
 final RiskGuard riskGuard;
    private
 final List<RemediationHandler> handlers;
    private
 final AuditService auditService;
    private
 final VerificationService verificationService;

    public
 void remediate(CorrelatedAlert alert) {
        RemediationPolicy
 policy = policyService.match(alert)
            .orElseThrow(() -> new IllegalStateException("no remediation policy matched"));

        RiskDecision
 riskDecision = riskGuard.evaluate(alert, policy);
        AlertContext
 context = buildContext(alert, policy, riskDecision);

        auditService.recordDecision(context);

        if
 (!riskDecision.allowAutoAction()) {
            auditService.recordSkip(context, "risk denied");
            return
;
        }

        for
 (RemediationHandler handler : handlers) {
            if
 (!handler.supports(context)) {
                continue
;
            }

            RemediationResult
 result = handler.handle(context);
            auditService.recordExecution(context, result);

            VerificationResult
 verification = verificationService.verify(alert, result);
            auditService.recordVerification(context, verification);

            if
 (!verification.success()) {
                auditService.recordEscalation(context, verification.reason());
            }
            return
;
        }

        auditService.recordSkip(context, "no handler accepted");
    }

    private
 AlertContext buildContext(CorrelatedAlert alert, RemediationPolicy policy, RiskDecision riskDecision) {
        // 这里会补充 workload、Pod、发布版本、近期变更窗口等上下文

        return
 new AlertContext(alert, policy, riskDecision, null, null);
    }
}

13.4 风险控制实现骨架

@Service
public
 class RiskGuard {

    private
 final RemediationQuotaService quotaService;
    private
 final ReleaseWindowService releaseWindowService;

    public
 RiskDecision evaluate(CorrelatedAlert alert, RemediationPolicy policy) {
        if
 (!quotaService.tryAcquire(alert.getFingerprint(), policy.getCooldownMs())) {
            return
 RiskDecision.deny("cooldown or quota exceeded", 90);
        }

        if
 (releaseWindowService.isFrozen(alert.getService())) {
            return
 RiskDecision.deny("service in freeze window", 85);
        }

        int
 riskScore = score(alert, policy);
        if
 (riskScore >= 70) {
            return
 RiskDecision.deny("risk score too high", riskScore);
        }
        return
 RiskDecision.allow("risk acceptable", riskScore);
    }

    private
 int score(CorrelatedAlert alert, RemediationPolicy policy) {
        int
 score = switch (policy.getActionType()) {
            case
 "ROLLING_RESTART_POD" -> 20;
            case
 "PATCH_HPA_MIN_REPLICAS" -> 40;
            case
 "ROLLBACK_RELEASE" -> 55;
            case
 "ENABLE_GLOBAL_DEGRADE" -> 65;
            default
 -> 80;
        };

        if
 ("P1".equals(alert.getSeverity())) {
            score += 10;
        }
        if
 (alert.getCount() > 10000) {
            score += 5;
        }
        return
 score;
    }
}

这套代码骨架体现的是生产逻辑顺序:

  • • 先匹配策略
  • • 再做风险评估
  • • 再执行动作
  • • 最后回读验证

很多 demo 会直接在收到告警后 if errorCode == xxx then restart pod,真实系统绝不能这么写。


十四、观测与审计:没有可解释性,就没有可持续自愈

如果系统自动执行了一个动作,团队必须能回答下面几个问题:

  • • 为什么触发?
  • • 根据哪条规则触发?
  • • 当时看到了哪些证据?
  • • 做了什么动作?
  • • 动作后效果怎样?
  • • 如果误操作,怎么追踪和复盘?

建议至少记录以下审计字段:

字段
说明
alert_id
告警 ID
action_id
动作 ID
fingerprint
故障指纹
rule_version
命中规则版本
risk_score
风险评分
operator
auto-heal-engine 或人工
target
目标服务/Pod/Deployment
execution_result
成功/失败/跳过
verification_result
修复有效/无效
raw_evidence
样本日志、指标、Trace、发布事件

审计数据可以进入 ClickHouse 或 Elasticsearch,便于:

  • • 做故障复盘
  • • 做误报分析
  • • 训练下一轮更好的规则或模型

十五、落地过程中最容易踩的坑

15.1 只看日志,不结合指标和发布事件

很多“异常”其实只是业务放量;很多“错误暴增”其实是新版本问题。如果不把 Metrics、Trace 和 Release Event 融合进去,根因判断会非常脆弱。

15.2 所有服务共用一套阈值

核心链路和边缘链路的容忍度完全不同。订单核心链路 100 次错误就可能是 P1,离线任务服务 1000 次也不一定有业务影响。

15.3 把自动重启当成万能药

重启只对部分资源类问题有效。对逻辑 bug、连接池泄漏、数据库锁等待,重启可能只能短暂掩盖问题,甚至放大问题。

15.4 没有动作幂等和并发控制

同一时间多个告警命中同一服务,如果没有锁和去重机制,很容易出现:

  • • 同时回滚和扩容
  • • 重复删除 Pod
  • • 配置开关被来回覆盖

15.5 没有回放机制

规则越改越多之后,如果不能基于历史数据回放验证,很快就会陷入“加一条规则压一个问题,结果引入三个副作用”的局面。


十六、演进路线:从规则驱动到更强的智能化

如果第一阶段已经把规则驱动自愈跑稳,后续可以继续演进,但建议按顺序做。

16.1 阶段一:规则驱动闭环

目标:

  • • 统一日志模型
  • • 建立告警压制和根因规则
  • • 打通低风险自动动作

这是最值得优先投入的阶段,因为 ROI 最高。

16.2 阶段二:基于拓扑的 RCA

把以下数据统一到一张图中:

  • • 服务调用关系
  • • Trace 依赖边
  • • 发布事件
  • • K8s Event
  • • 节点资源事件

这样能从“错误聚合”进化到“根因推断”。

16.3 阶段三:动作效果学习

将“故障模式 -> 动作 -> 验证结果 -> 恢复时间”沉淀成训练样本,逐步优化策略推荐。

但要注意:

  • • 先做建议模式,再做自动执行
  • • 必须保留可解释性
  • • 高风险场景不要轻易交给黑盒模型

16.4 阶段四:混沌工程常态化

把 ChaosBlade、LitmusChaos 这类工具接入验证链路,定期注入:

  • • Pod Kill
  • • 网络延迟
  • • CPU 抢占
  • • 磁盘 IO 抖动

让自愈系统在“演习”中迭代,而不是只在真实事故中学习。


十七、推荐实施路径:三个月做出第一版,半年做成平台

如果团队准备落地,建议按下面节奏推进。

第 1 阶段:2 到 4 周

  • • 统一结构化日志规范
  • • 打通 Kafka 日志总线
  • • 建立基础 Flink 聚合告警
  • • 实现静默、聚合、去重

产出是“可用的高质量告警”,而不是自愈。

第 2 阶段:4 到 8 周

  • • 引入服务拓扑和 Trace 关联
  • • 建立规则中心
  • • 实现根因压制
  • • 接入审计链路

产出是“可行动告警”。

第 3 阶段:8 到 12 周

  • • 接入 K8s API 和发布平台
  • • 上线低风险动作:单 Pod 重启、消费者扩容、灰度暂停
  • • 增加风控、冷却、验证机制

产出是“低风险自动驾驶”。

第 4 阶段:长期建设

  • • 做历史回放平台
  • • 做动作效果分析
  • • 引入图谱 RCA
  • • 引入混沌工程验证

产出是“可持续进化的 AIOps 平台”。


十八、结语:自动驾驶的本质,不是更激进,而是更可控

海量日志告警系统真正难的地方,从来不是把日志采进来,也不是写几条阈值规则,而是把“复杂线上系统的不确定性”压缩成一套可计算、可执行、可审计、可回放的闭环。

一套真正有生产价值的系统,至少要同时满足四件事:

  • • 看得见:日志、指标、Trace、事件统一接入
  • • 判得准:聚合、压制、根因分析、风险评分
  • • 动得稳:动作白名单、冷却、熔断、验证闭环
  • • 说得清:全链路审计、规则版本、证据留痕

当系统具备这些能力后,团队的工作方式会发生根本变化:

  • • 从“人盯告警”变成“机器先收敛问题”
  • • 从“凭经验排障”变成“基于证据决策”
  • • 从“人工执行修复”变成“低风险问题自动闭环”

这才是从“救火”走向“自动驾驶”的真正分水岭。

如果把这条链路做好,凌晨 3 点 的告警不一定会消失,但它很可能已经在你醒来前,被系统自己稳稳处理掉了。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-05-10 20:08:24 HTTP/2.0 GET : https://e.mffb.com.cn/a/503733.html
  2. 运行时间 : 0.147669s [ 吞吐率:6.77req/s ] 内存消耗:4,650.70kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=ab56e55ba8ff283e856fe12e391e83a9
  1. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/runtime/temp/600e51726691ba7063b44bb89d9aaaff.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/e.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000461s ] mysql:host=127.0.0.1;port=3306;dbname=e_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000713s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000963s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.001734s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000754s ]
  6. SELECT * FROM `set` [ RunTime:0.000288s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000781s ]
  8. SELECT * FROM `article` WHERE `id` = 503733 LIMIT 1 [ RunTime:0.023321s ]
  9. UPDATE `article` SET `lasttime` = 1778414904 WHERE `id` = 503733 [ RunTime:0.000691s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.002844s ]
  11. SELECT * FROM `article` WHERE `id` < 503733 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000432s ]
  12. SELECT * FROM `article` WHERE `id` > 503733 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000455s ]
  13. SELECT * FROM `article` WHERE `id` < 503733 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.010233s ]
  14. SELECT * FROM `article` WHERE `id` < 503733 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.009222s ]
  15. SELECT * FROM `article` WHERE `id` < 503733 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.028238s ]
0.149265s