filebeat ->redis -> logstash -> es实践

filebeat ->redis -> logstash -> es实践

基于如下日志架构实践从环境搭建到日志采集输出到ES的全过程:在这里插入图片描述
其中关于ES集群,redis,kibana的环境搭建,在这篇文章中不做任何体现,我在其他文章中有详细的笔记,可以搜索找到。

那么现在需要的是下载filebeat和logstash两个环境包,这里推荐下载.tar.gz后缀的压缩文件包。

另外需要注意的是 filebeat logstash es kibana 版本要求一直,避免出现不兼容的情况。

本篇文章中主要作为一个技术验证,不会有太复杂的动作。

下载filebeat 和 logstash的地址如下:

https://www.elastic.co/cn/beats/filebeat

https://www.elastic.co/cn/logstash/

1.filebeat需要部署在需要采集日志的目标服务器中,比如上传到/opt目录下,在目录/opt/filebeat-7.13.2-linux-x86_64/下创建filebeat_redis.yml文件,用于将采集的目标日志写入到redis消息队列中:

#比如我现在采集的NPM的后端服务运行的日志
filebeat.inputs:
- type: log
  enabled: true
  backoff: "1s"
  tail_files: false
  paths:
    - /app/api/logs/*.log    #日志文件
  fields:
    filetype: log_npmjson    #这里是自定义名称
  fields_under_root: true
output.redis:
  enabled: true
  hosts: ["103.104.202.36:6379"]  #redis
  key: npm                        #redis 键名称
  db: 1                           #写入的db
  datatype: list                  #输出类型 list

启动filebeat:

./filebeat -e -c filebeat_redis.yml

后台启动:
nohup /opt/filebeat-7.13.2-linux-x86_64/filebeat -e -c /opt/filebeat-7.13.2-linux-x86_64/filebeat_redis.yml >/dev/null 2>&1 &

查看运行状态机器相关操作:

systemctl status filebeat
systemctl start filebeat
systemctl stop filebeat
systemctl restart filebeat

2.logstash部署到一台单独的服务器,将.tar.gz文件上传到/opt目录下并解压,在config目录下创建文件logstash_npm_redis.yml,写入内容:

input {
   redis {
        host => "103.104.202.36"   #redis
        port => 6379               #redis 端口
        key => "npm"               #redis 键名称
        data_type => "list"        #数据类型
        db =>1                     #从db1中读
    }
}
filter {
    json {
       source => "message"         #只读取message内容
       remove_field => [""]        #需要从message中过滤的字段,这里是字符串数组,比如:["field1","field2","....."]
    }
    date {
      match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]  #时间戳格式化
      target => "@timestamp"                            #从@timestamp中取时间戳,通过 match 进行格式化
    }
}
output {                                                #将消息队列中的数据输出到ES
       elasticsearch {
          hosts => ["192.168.30.22:9200"]
          index => "redis-npm-%{+YYYY.MM.dd}"           #索引的命名规则
      }
}

启动logstach:

cd /opt/logstash-7.13.2/

bin/logstash -f config/logstash_npm_redis.conf

稍微等30s,启动过程稍慢

查看进程:

ps -ef |grep logstash

结束进程:

kill -9 进程号

3.查看kibana:
日志已经在正常写入:在这里插入图片描述
在这里插入图片描述
查看ES:在这里插入图片描述
后续可以进行java开发 对接ES的日志数据 ,输出到指定的管理平台。

<think> 我们正在处理一个特定的需求:在调用链路a->b->c中,通过分布式事务框架搜索获取b服务日志。 注意:用户提到了“分布式事务框架”,但我们知道分布式链路追踪和分布式事务是两个不同的概念。不过,用户可能是在分布式事务的上下文中需要追踪日志,因此我们需要将两者结合考虑。 分析: 1. 调用链路:a->b->c,这是一个典型的分布式调用链。 2. 目标:获取b服务的日志。 3. 手段:通过分布式事务框架(如Seata)或者结合分布式链路追踪(如SkyWalking, Jaeger)来搜索日志。 思路: 在分布式系统中,要获取特定服务的日志,我们需要一个全局标识(TraceID)来关联整个调用链,然后通过这个TraceID去查询b服务的日志。 步骤: 1. 在调用链中传递TraceID:确保服务a、b、c都使用同一个TraceID。这通常由分布式链路追踪系统自动完成(例如通过OpenTelemetry SDK)。 2. 在服务b中,将日志与TraceID关联:在服务b中记录日志时,将当前Span的TraceID(或SpanID)添加到日志上下文中。这样,每条日志都可以通过TraceID来查询。 3. 使用分布式事务框架:如果用户使用的是分布式事务框架(如Seata),它也会生成一个全局事务ID(XID)。我们可以将XID与TraceID进行关联,或者直接使用XID作为TraceID(需要整合)。 4. 查询日志:通过TraceID(或XID)在日志存储系统中检索服务b的日志。 具体实现方案: 方案1:通过分布式链路追踪系统 - 前提:系统已经集成了分布式链路追踪(如Jaeger、SkyWalking、Zipkin等)。 - 步骤: a. 从链路追踪系统中获取整个调用链的TraceID(例如,用户可以从服务a的入口获取TraceID,并传递下去)。 b. 在服务b中,日志框架(如Logback、Log4j2)通过MDC(Mapped Diagnostic Context)将TraceID添加到每条日志中。 c. 当日志被收集到集中式日志系统(如ELK、Loki)时,可以通过TraceID来过滤日志。 方案2:通过分布式事务框架(如Seata)的全局事务ID(XID) - 步骤: a. 在服务a中开启全局事务,生成XID,并将XID传递到服务b和服务c(通过RPC上下文传递)。 b. 在服务b中,将XID记录到日志中(同样使用MDC)。 c. 通过XID在日志系统中检索服务b的日志。 方案3:整合分布式链路追踪和分布式事务 - 可以将TraceID和XID关联起来,例如在服务a中,将TraceID设置为XID的一部分,或者在日志中同时记录TraceID和XID。 - 这样,无论是通过链路追踪系统还是事务框架,都可以关联到日志。 具体技术实现(以方案1为例,结合Spring Cloud Sleuth和ELK): 1. 日志记录(服务b): 使用Spring Cloud Sleuth,它会自动将TraceID添加到MDC中。在日志配置中,我们可以设置日志格式包含TraceID。 例如在logback-spring.xml中: ```xml <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{traceId},%X{spanId}] %-5level [%thread] %logger{36} - %msg%n</pattern> ``` 2. 日志收集: 使用Filebeat收集日志并发送到Logstash,然后存储到Elasticsearch。 3. 日志查询: 在Kibana中,通过traceId字段搜索即可得到服务b的相关日志。 如果使用分布式事务框架Seata,我们可以类似地将XID放入MDC: 在服务a(事务发起者)中,开启事务后,将XID放入MDC: ```java @GlobalTransactional public void serviceA() { // 获取当前全局事务XID String xid = RootContext.getXID(); MDC.put("XID", xid); // 调用服务b // ... } ``` 在服务b中,我们需要从RPC上下文中获取XID(因为Seata会通过RPC传递XID),然后放入MDC: ```java public void serviceB() { String xid = RootContext.getXID(); MDC.put("XID", xid); // 执行业务逻辑并记录日志 // ... } ``` 这样,在日志中就会包含XID,然后通过XID在日志系统中搜索即可。 注意事项: - 跨服务传递:无论是TraceID还是XID,都需要在服务间传递。对于HTTP服务,可以通过请求头传递;对于RPC框架(如Dubbo),可以通过RpcContext传递。 - 异步场景:在异步调用中,需要手动传递MDC上下文(或使用相应的工具类,如TransmittableThreadLocal)。 结论: - 如果系统已经集成了分布式链路追踪,则优先使用TraceID来检索日志。 - 如果系统主要使用分布式事务框架(如Seata),则使用XID来检索日志。 - 也可以将两者关联,实现更强大的跟踪能力。 相关问题: 1. 如何在分布式系统中实现日志的全局跟踪? 2. 分布式事务框架Seata如何与分布式链路追踪系统集成? 3. 在异步调用链路中如何传递TraceID? 4. 如何配置Logback使日志输出TraceID? 根据用户的问题,我们重点回答了在链路a->b->c中获取b服务日志的方法,结合了分布式链路追踪和分布式事务框架两种方案。 </think> ### 分布式链路中精准获取服务日志的实现方案 基于调用链路 `a->b->c` 的场景,结合分布式事务框架获取 **b 服务日志**的核心方法如下: --- ### 一、技术实现原理 #### 1. 日志与追踪的关联绑定 ```mermaid graph LR TraceID --> LogA[服务A日志] TraceID --> LogB[服务B日志] --> |精准定位| TargetLogs TraceID --> LogC[服务C日志] ``` - **关键绑定机制**: 在服务日志中强制注入 TraceID 标识符,满足关系: `日志记录 = {时间戳, TraceID, SpanID, 日志内容}` 示例日志格式: ```log 2024-01-01 12:00:00 [TRACE:7d3f8a][SPAN:cf2e1b] - 服务B处理请求参数: {...} ``` #### 2. 分布式事务框架集成方案 | **框架** | **日志获取接口** | **实现原理** | |----------------|----------------------------------|----------------------------------| | **Seata** | `GlobalTransactionContext.getXID()` | 通过事务ID反向追溯TraceID[^1] | | **SkyWalking** | `TraceContext.traceId()` | 直接从追踪上下文获取标识符 | | **OpenTelemetry** | `Span.current().getSpanContext()` | 通过SpanContext提取TraceID | --- ### 二、具体实施步骤 #### 1. 日志注入 TraceID(服务 B 实现) 以 Java/SpringBoot 为例: ```java // 使用SLF4J的MDC机制注入追踪标识 @RestController public class ServiceBController { @PostMapping("/b") public Response handleRequest(@RequestBody Request request) { // 从追踪上下文获取TraceID String traceId = Span.current().getSpanContext().getTraceId(); // 注入MDC上下文 MDC.put("traceId", traceId); // 业务逻辑(自动在日志输出携带traceId) log.info("Processing request: {}", request); return bService.process(request); } } ``` *输出日志示例*: `[TRACE:7d3f8a] Processing request: {id: 123}` #### 2. 事务框架中检索日志 通过 **TraceID → 事务ID → 日志检索** 路径实现: ```mermaid sequenceDiagram User->>+TransactionConsole: 提交事务ID查询 TransactionConsole->>+TracingDB: 请求TraceID映射 TracingDB-->>-TransactionConsole: 返回TraceID TransactionConsole->>+LogStorage: 按TraceID检索日志 LogStorage-->>-TransactionConsole: 返回服务B日志 TransactionConsole-->>-User: 展示结果 ``` **关键操作**: ```shell # 使用ELK栈查询示例 curl -XGET 'http://elk:9200/logs-index/_search?q=traceId:7d3f8a&service_name:B' ``` #### 3. 性能优化策略 - **索引优化**:为 TraceID 建立倒排索引,查询复杂度降至 $O(1)$ - **缓存机制**:对高频 TraceID 的日志进行 Redis 缓存,响应时间 < 10ms - **采样策略**:对错误日志进行全采样,满足: $P_{\text{sample}} = \begin{cases} 1 & \text{if } \text{status} \neq 200 \\ 0.2 & \text{otherwise} \end{cases}$ --- ### 三、主流框架对接示例 | **框架组合** | **日志获取方式** | **适用场景** | |--------------------------|-------------------------------------------|-------------------------| | **Seata + SkyWalking** | 通过 `GlobalTransaction` 获取 XID → TraceID | 金融级事务系统[^1] | | **Dubbo + Zipkin** | 从 RpcContext 提取 TraceID | 传统微服务架构 | | **SpringCloud + Jaeger** | 注入 `Tracer` 实例主动获取 | 云原生环境 | > **注**:在服务网格中(如Istio+Envoy),可通过 Wasm 插件自动注入 TraceID 到日志[^2],实现零代码改造。 --- ### 四、故障排查场景 当链路 `a->b->c` 出现异常时: 1. 通过事务控制台定位失败的事务ID 2. 提取关联的 TraceID `7d3f8a` 3. 在日志系统中执行: ```sql SELECT * FROM service_b_logs WHERE traceId = '7d3f8a' AND level = 'ERROR' ``` 4. 获取精准错误信息(如数据库连接超时、参数校验失败等) ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

clarence.wei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值