4. 日志采集与存储:选对工具,事半功倍
采集合适,存储到位——OCSP 审计日志的性能分析,第一步其实就靠这两件事。我见过太多团队刚起步就扎进算法调优,结果发现日志根本收不上来,或者查个几天的记录就要等半天。
说白了,日志链路的前两公里要是没铺好,后面再怎么跑也快不起来。今天就聊聊我这些年用过、踩过、也优化过的采集和存储方案。
4.1 采集工具:rsyslog 与 Fluentd
采集工具的选择,直接影响你能否稳定拿到每一笔 OCSP 响应日志。我个人偏好从两个维度来评估:吞吐能力和灵活性。
4.1.1 rsyslog:轻量、可靠、原生
rsyslog 是 Linux 系统自带的日志守护进程,升级版 syslog。对 OCSP 场景来说,它的优势很直接——零依赖,配置简单,单机吞吐轻松撑到每秒数万条。
我曾经在一个日均处理 2000 万次 OCSP 查询的项目里,就用 rsyslog 把审计日志直接转发到远程服务器。配置大概长这样:
# /etc/rsyslog.d/ocsp-audit.conf
# 接收 OCSP 审计日志(本地 UDP 514 或自定义端口)
module(load="imudp")
input(type="imudp" port="514")
# 格式化输出为 JSON,方便下游解析
template(name="ocsp_json" type="list") {
constant(value="{")
constant(value="\"timestamp\":\"") property(name="timereported" dateformat="rfc3339")
constant(value="\",\"host\":\"") property(name="hostname")
constant(value="\",\"message\":\"") property(name="msg" jsonr="on")
constant(value="\"}")
}
# 转发到远程日志中心(TCP)
action(type="omfwd"
target="10.0.1.100"
port="6514"
protocol="tcp"
template="ocsp_json"
queue.size="50000"
queue.type="linkedlist"
action.resumeRetryCount="-1")
这里有个坑——UDP 丢包。OCSP 响应频率很高,如果网络打满,UDP 可能扔掉 1%~3% 的日志。我曾经在高峰期发现丢了一条关键撤销记录,排查了两天才意识到是 rsyslog 默认用 UDP 转发的问题。
我曾经在高峰期发现 UDP 丢包导致关键撤销记录丢失。解决方案:改用 TCP 协议,并调大队列大小(queue.size)。高压场景下再配合磁盘辅助队列(queue.filename),确保不丢一条。
4.1.2 Fluentd:管道灵活、生态丰富
如果环境比较复杂——比如需要解析不同格式的 OCSP 日志、做字段过滤、或同时向多个存储目标分发日志,我建议用 Fluentd。
它的核心是一个插件架构,输入、解析、过滤、输出都能通过配置文件串联。下面是我在另一个项目中的典型配置:
# /etc/fluentd/fluent.conf
<source>
@type tail
path /var/log/ocsp-audit.log
pos_file /var/log/fluentd-ocsp.pos
tag ocsp.audit
<parse>
@type json
time_key timestamp
</parse>
</source>
<filter ocsp.audit>
@type grep
<regexp>
key status
pattern good|revoked|unknown
</regexp>
</filter>
<match ocsp.audit>
@type copy
<store>
@type elasticsearch
host localhost
port 9200
index_name ocsp-audit-%Y%m%d
</store>
<store>
@type file
path /backup/ocsp-audit
<buffer>
chunk_limit_size 16m
flush_interval 30s
</buffer>
</store>
</match>
看到没?用 copy 插件可以同时写入 Elasticsearch 和文件,既保证实时查询,又保留冷备份。我习惯把 buffer 开到 16MB,避免频繁写入磁盘造成 IO 争抢。
Fluentd 的 buffer 设置很关键。我曾经因为 flush_interval 太短(5s),导致小文件频繁刷盘,磁盘 IO 飙到 90%+。后来改成 30s 配合 16MB chunk,压力立刻下来。
4.1.3 工具对比表
| 维度 | rsyslog | Fluentd |
|---|---|---|
| 部署复杂度 | 极低(系统自带) | 中等(需安装 Ruby/td-agent) |
| 单机吞吐 | ≥10 万条/秒 | 约 3~5 万条/秒 |
| 数据可靠性 | 需显式配置 TCP + 队列 | 内置 buffer + 重试机制 |
| 解析灵活性 | 模板语法有限 | 丰富(正则、JSON、多种格式) |
| 生态插件 | 较少 | 丰富(200+ 输出插件) |
| 内存占用 | 低(约 50MB) | 中等(约 200~500MB) |
你想想看,如果你的 OCSP 服务部署在裸金属上,日志量特别大,我倾向先选 rsyslog。如果有多重处理需求、或要对接多个存储系统,Fluentd 更灵活。
4.2 存储方案:Elasticsearch vs ClickHouse
采集完的日志要存到哪?这是另一个关键选择。我主要用过 Elasticsearch 和 ClickHouse,两者定位完全不同。
4.2.1 Elasticsearch:全文搜索利器
Elasticsearch 的优势是全文搜索和聚合分析。OCSP 审计日志里常有 certificate_serial、issuer_dn 等文本字段,ES 的倒排索引能秒级找到特定证书的历史记录。
但它也有代价——索引膨胀。每一条日志都要建倒排索引,存储开销高。我在一个项目里存了 30 天的 OCSP 日志(日均约 800 万条),光 ES 数据就占了 2TB 磁盘,而且写入吞吐很难超过 5 万条/秒。
如果查询场景以“按证书序列号搜索”“按时间范围聚合”为主,ES 很合适。但要注意:
- 按天创建索引(manage rolling index),方便删除过期数据。
- 对不需要全文搜索的字段设为
"index": false,减少存储。 - 控制
refresh_interval为 30s~60s,提升写入性能。
4.2.2 ClickHouse:列式存储,极致分析
ClickHouse 是真正的分析型数据库。它的列式存储让宽表聚合快得惊人。我做过测试:10 亿条 OCSP 日志,按响应状态(good/revoked)分组统计,ES 需要 8 秒,ClickHouse 只要 0.3 秒。
它的建表语句也很有特色:
CREATE TABLE ocsp_audit_local
(
timestamp DateTime,
host String,
cert_hash String,
status Enum8('good'=1, 'revoked'=2, 'unknown'=3),
issuer_dn String,
response_time_us UInt32
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(timestamp)
ORDER BY (timestamp, status, cert_hash)
TTL timestamp + INTERVAL 90 DAY DELETE;
-- 然后建分布式表
CREATE TABLE ocsp_audit AS ocsp_audit_local
ENGINE = Distributed('cluster_name', 'default', 'ocsp_audit_local', rand());
看到 TTL 了吧?自动清理过期数据,不用自己写定时脚本。而且 ORDER BY 的字段顺序直接影响查询性能。我习惯把时间戳+状态放在前面,因为大部分分析都按日/时聚合、再按状态分组。
ClickHouse 不适合文本模糊搜索。如果要查“issuer_dn 包含某个词”,用 ES 更合适。另外,ClickHouse 对高并发小查询不太友好——单机 QPS 超过 300 时,连接池容易爆。建议前端加一层代理如
chproxy。
4.2.3 选型对比
| 维度 | Elasticsearch | ClickHouse |
|---|---|---|
| 查询类型 | 全文搜索、聚合 | 大规模聚合、分析 |
| 写入性能 | 3~5万条/秒(单节点) | 20~50万条/秒(单节点) |
| 存储压缩比 | 1:1~1:2 | 1:5~1:10(列式) |
| 实时性 | 准实时(秒级) | 准实时(秒级,但需优化合并) |
| 运维复杂度 | 较高(需调 JVM、分片) | 中等(无 JVM,但需理解合并树) |
| 适用场景 | 日志检索、告警溯源 | 性能分析、大屏报表、长期存储 |
4.3 知识体系总览
我把这一章的核心逻辑画成了一张图,方便你理解采集和存储的上下游关系:
嗯,这张图把四个关键组件串起来了。从日志产生端到存储端,中间经过采集工具和缓冲。你可以在实际项目里根据需求搭配组合,比如我常用“rsyslog + ClickHouse”做高性能管道,或者“Fluentd + Elasticsearch”做多源汇聚。
- 日志量 > 5万条/秒,且以分析为主 → rsyslog + ClickHouse
- 需要复杂过滤、多目标输出、全文搜索 → Fluentd + Elasticsearch
- 混合场景:采集用 rsyslog(稳定高吞吐),同时复制一份到 ClickHouse 做分析,另一份到 ES 做检索