Logstash+ Kafka基于AOP 实时同步日志到es
Logstash是一个开源数据收集引擎,具有实时管道功能。Logstash可以动态地将来自不同数据源的数据统一起来,并将数据标准化到你所选择的目的地,logstash丰富的插件(logstash-input-jdbc,logstash-input-kafka,logstash-input-rabbitmq,logstash-input-flie,logstash-input-syslog等,github地址: https://github.com/logstash-plugins)
1.logstash-input-kafka将微服务日志同步到 elasticsearch
1.1 基于AOP+Kafka同步数据原理
原理其实很简单,就是基于JAVA的AOP技术拦截方法收集请求日志和异常日志发送到Kafka,然后通过logstash订阅相应的topic来消费消息(即发布订阅模式)output到es来实现日志收集
1.2 日志收集配置文件
szhuangl_goods_log.conf
input {
kafka {
#kafaka服务地址
bootstrap_servers => "server.natappfree.cc:33402"
topics => ["szhuangl_goods_log"]
}
}
output {
stdout { codec => rubydebug }
elasticsearch {
#es服务地址
hosts => ["127.0.0.1:9200"]
index => "szhuangl_goods_log"
}
}
Kafka消息提供者代码
package com.szhuangl.basic.elk.kafka; import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.SendResult;
import org.springframework.stereotype.Component;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback; /**
* @program: szhunagl-shop-parent
* @author: Brian Huang
* @create: 2019-10-19 16
**/
@Component
@Slf4j
public class KafkaSender<T> { @Value("${szhuangl.log.topic: szhuangl_log}")
private String log_topic; @Autowired
private KafkaTemplate<String, Object> kafkaTemplate; /**
* kafka 发送消息
*
* @param obj
* 消息对象
*/ public void send(T obj) {
String jsonObj = JSON.toJSONString(obj); // 发送消息
ListenableFuture<SendResult<String, Object>> future = kafkaTemplate.send(log_topic, jsonObj);
future.addCallback(new ListenableFutureCallback<SendResult<String, Object>>() { @Override
public void onFailure(Throwable throwable) {
log.info("Produce: The message failed to be sent:" + throwable.getMessage());
} @Override
public void onSuccess(SendResult<String, Object> stringObjectSendResult) {
// TODO 业务处理
log.info("Produce: The message was sent successfully:");
log.info("Produce: >>>>>>>>>>>>>>>>>>> result: " + stringObjectSendResult.toString());
}
});
}
}
AOP切面收集日志代码
package com.szhuangl.basic.elk.aop; import com.alibaba.fastjson.JSONObject;
import com.szhuangl.basic.elk.kafka.KafkaSender;
import com.szhuangl.common.web.util.IpUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays; /**
* @program: kafka日志收集切面类
* @author: Brian Huang
* @create: 2019-10-19 16
**/
@Aspect
@Component
@Slf4j
public class AopLogAspect { @Autowired
private KafkaSender<JSONObject> kafkaSender; // 申明一个切点 里面是 execution表达式
@Pointcut("execution(* com.szhuangl.impl.*.service.*.*(..))")
private void serviceAspect() {
} // 请求method前打印内容
@Before(value = "serviceAspect()")
public void methodBefore(JoinPoint joinPoint) {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest(); String ip = IpUtils.getIpAddress(request);
int localPort = request.getLocalPort();
log.info("---localPort---:" + localPort);
int serverPort = request.getServerPort();
log.info("---serverPort---:" + serverPort);
int remotePort = request.getRemotePort();
log.info("---remotePort---:" + remotePort);
JSONObject jsonObject = new JSONObject(); DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); jsonObject.put("request_time", LocalDateTime.now().format(dateTimeFormatter));
jsonObject.put("request_ip_port", ip);
jsonObject.put("request_url", request.getRequestURL().toString());
jsonObject.put("request_method", request.getMethod());
jsonObject.put("signature", joinPoint.getSignature());
jsonObject.put("request_args", Arrays.toString(joinPoint.getArgs()));
JSONObject requestJsonObject = new JSONObject();
requestJsonObject.put("szhuangl_request", jsonObject);
kafkaSender.send(requestJsonObject);
} // 在方法执行完结后打印返回内容
@AfterReturning(returning = "o", pointcut = "serviceAspect()")
public void methodAfterReturing(Object o) {
JSONObject respJSONObject = new JSONObject();
JSONObject jsonObject = new JSONObject();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
jsonObject.put("response_time", LocalDateTime.now().format(dateTimeFormatter));
jsonObject.put("response_content", JSONObject.toJSONString(o));
respJSONObject.put("szhuangl_response", jsonObject);
kafkaSender.send(respJSONObject);
}
}
异常日志收集代码
package com.szhuangl.basic.elk.aop.error; import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import com.szhuangl.basic.elk.kafka.KafkaSender;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest; /**
*
* @description: 全局捕获异常
*/
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler { @Autowired
private KafkaSender<JSONObject> kafkaSender; @ExceptionHandler(RuntimeException.class)
@ResponseBody
public JSONObject exceptionHandler(Exception e) {
log.info("<<<<<<<<<<<<<<<全局捕获异常>>>>>>>>>>>>>>>>>,error:{}", e);
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest(); // 1.封装异常日志信息
JSONObject errorJson = new JSONObject();
JSONObject logJson = new JSONObject();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
logJson.put("request_time", LocalDateTime.now().format(dateTimeFormatter));
logJson.put("error_info", e);
errorJson.put("szhuangl_request_error", logJson);
kafkaSender.send(errorJson);
// 2. 返回错误信息
JSONObject result = new JSONObject();
result.put("code", 500);
result.put("msg", "系统错误");
return result;
}
}
application.yml kafka配置信息
###服务端口
server:
port: 8700
###eurake
eureka:
client:
service-url:
defaultZone: http://localhost:8100/eureka
spring:
application:
name: szhuangl-server-goods
data:
elasticsearch:
cluster-name: szhuangl_es
cluster-nodes: j1ekxg71oe.52http.tech:51267
repositories:
enable: true
kafka:
#kafka配置信息
bootstrap-servers: server.natappfree.cc:33402 #配置kafka的־topic
szhuangl:
log:
topic: szhuangl_goods_log
Logstash+ Kafka基于AOP 实时同步日志到es的更多相关文章
- spring+mybatis基于 AOP实现业务日志管理
最近在项目上用到了操作日志的相关,之前的解决方案就是自己写一个日志project,然后统一调用日志接口即可,这样方便自定义定制,因为有很多设备控制之类的都是需要确认一下的,但是,对数据的操作,比如,增 ...
- 微服务日志监控与查询logstash + kafka + elasticsearch
使用 logstash + kafka + elasticsearch 实现日志监控 https://blog.csdn.net/github_39939645/article/details/788 ...
- mysql数据实时同步到Elasticsearch
业务需要把mysql的数据实时同步到ES,实现低延迟的检索到ES中的数据或者进行其它数据分析处理.本文给出以同步mysql binlog的方式实时同步数据到ES的思路, 实践并验证该方式的可行性,以供 ...
- lsyncd替代inotify+rsync实现实时同步
因公司业务需要需要实时同步日志文件,刚一开始使用的是inotify+rsync来实现实时同步,但时间久而久之发现同步的速度越来越慢,往往延迟好几个小时.查了一下网上的inotify+rsync方案基本 ...
- 基于Canal和Kafka实现MySQL的Binlog近实时同步
前提 近段时间,业务系统架构基本完备,数据层面的建设比较薄弱,因为笔者目前工作重心在于搭建一个小型的数据平台.优先级比较高的一个任务就是需要近实时同步业务系统的数据(包括保存.更新或者软删除)到一个另 ...
- 基于Flume+Kafka+ Elasticsearch+Storm的海量日志实时分析平台(转)
0背景介绍 随着机器个数的增加.各种服务.各种组件的扩容.开发人员的递增,日志的运维问题是日渐尖锐.通常,日志都是存储在服务运行的本地机器上,使用脚本来管理,一般非压缩日志保留最近三天,压缩保留最近1 ...
- 基于OGG的Oracle与Hadoop集群准实时同步介绍
版权声明:本文由王亮原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/220 来源:腾云阁 https://www.qclou ...
- 和我一起打造个简单搜索之Logstash实时同步建立索引
用过 Solr 的朋友都知道,Solr 可以直接在配置文件中配置数据库连接从而完成索引的同步创建,但是 ElasticSearch 本身并不具备这样的功能,那如何建立索引呢?方法其实很多,可以使用 J ...
- sersync基于rsync+inotify实现数据实时同步
一.环境描述 需求:服务器A与服务器B为主备服务模式,需要保持文件一致性,现采用sersync基于rsync+inotify实现数据实时同步 主服务器A:192.168.1.23 从服务器B:192. ...
随机推荐
- modbus-poll和modbus-slave工具的学习使用——modbus协议功能码2的解析
功能码2的功能是:读从机离散量输入信号的 ON/OFF 状态.可读取1-2000个连续的离散量输入状态,如果离散输入的数量个数不是8的整数倍,则用0填充最后数据字节的剩余位,功能码2的查询信息规定了要 ...
- AtCoder Beginner Contest 127 解题报告
传送门 非常遗憾.当天晚上错过这一场.不过感觉也会掉分的吧.后面两题偏结论题,打了的话应该想不出来. A - Ferris Wheel #include <bits/stdc++.h> u ...
- LeetCode 959. Regions Cut By Slashes
原题链接在这里:https://leetcode.com/problems/regions-cut-by-slashes/ 题目: In a N x N grid composed of 1 x 1 ...
- JavaScript基础04——数组的创建及方法
数组的概念及定义 数组的概念: 一组数据,数据的组和 哪些数据的组和,只要是数据(所有数据),就可以放在数组中 数组的意义: 可以同时操作多个数据 数组 ...
- tensorflow2.0 学习(一)
虽说是按<TensorFlow深度学习>这本书来学习的,但是总会碰到新的问题!记录下这些问题,有利于巩固知新. 之前学过一些tensorflow1.0的知识,到RNN这章节,后面没有再继续 ...
- [RN] React Native 常用命令行
[RN] React Native 常用命令行 1.查看当前版本 react-native --version 或 react-native -v 2.创建指定版本的React Native项目 1) ...
- [RN] React Native 生成 Android APK
在用模拟器或者真机调试完App后,需要将App打包成Apk发布文件. 下面简单记录下打包步骤: 第一:生成签名密钥 这一步的操作主要是生成需要的签名密钥,供android调用,生成的文件待用 在项目根 ...
- 第12组 Alpha事后诸葛亮
Header 组长博客 Postmortem 设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 要解决的是喜欢记录分享旅游生活的人群的行迹记录和分享问题, ...
- Fluent Meshing对称模型形成完整模型
原视频下载地址:https://pan.baidu.com/s/1i4NZnVZ 密码:ts5a
- 【软工实践】Alpha冲刺(4/6)
链接部分 队名:女生都队 组长博客: 博客链接 作业博客:博客链接 小组内容 恩泽(组长) 过去两天完成了哪些任务 描述 学习调用中国天气网API,接近实现天气推送功能 对天气推送的形式进行讨论及重确 ...