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. ...
随机推荐
- JAVA项目部署到云服务器
转自:(此处更详细)http://blog.csdn.net/gulu_gulu_jp/article/details/50994003 一.前言 前面我们已经尝过了在云服务器上部署代码的甜头了,现在 ...
- codeforces B. Make Them Odd -C++stl之set的使用
B. Make Them Odd There are nn positive integers a1,a2,…,ana1,a2,…,an. For the one move you can choos ...
- Pivotal Greenplum 6.0 新特性介绍
Pivotal Greenplum 6.0 新特性介绍 在1月12日举办的Greenplum开源有道智数未来技术研讨会上,Pivotal中国研发中心Greenplum 产品经理李阳向大家介绍了Pi ...
- 洛谷P4408 逃学的小孩
题目 求树的直径,因为任意两个居住点之间有且只有一条通路,所以这是一棵树. 根据题意父母先从C去A,再去B,或者反过来. 我们一定是要让A到B最大,也要让C到A和B的最小值最大. AB最大一定就是直径 ...
- mysql find_in_set 函数 使用方法
mysql> select * from user; +------+----------+-----------+ | id | name | address | +------+------ ...
- 【LA 3942】 Remember the word
题意 给定一个字符串和若干个单词,询问能把字符串分解成这些单词的方案数.比如abcd ,有单词a,b,ab,cd:就可以分解成a+b+cd或者ab+cd. 分析 trie树—>DP 代码 (感谢 ...
- Intellij IDEA 自动清除无效 import 和 清除无效 import 的快捷键
可以settings-general-auto import-java项,勾选optimize imports on the fly,在当前项目下会自动清除无效的import,而且这个是随时自动清除的 ...
- px,em和rem
1 px像素(Pixel).相对长度单位.像素px是相对于显示器屏幕分辨率而言的 2 em是相对长度单位.相对于当前对象内文本的字体尺寸.如当前对行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字 ...
- 正向代理 & 反向代理 & 透明代理
正向代理(Forward Proxy) 概述 一般情况下,如果没有特别说明,代理技术默认说的是正向代理技术.关于正向代理的概念如下: 正 向代理(forward)是一个位于客户端[用户A]和原始服务器 ...
- docker 进程管理
详文:理解Docker容器的进程管理:https://yq.aliyun.com/articles/5545 在Docker中,每个Container都是Docker Daemon的子进程. dock ...