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的更多相关文章

  1. spring+mybatis基于 AOP实现业务日志管理

    最近在项目上用到了操作日志的相关,之前的解决方案就是自己写一个日志project,然后统一调用日志接口即可,这样方便自定义定制,因为有很多设备控制之类的都是需要确认一下的,但是,对数据的操作,比如,增 ...

  2. 微服务日志监控与查询logstash + kafka + elasticsearch

    使用 logstash + kafka + elasticsearch 实现日志监控 https://blog.csdn.net/github_39939645/article/details/788 ...

  3. mysql数据实时同步到Elasticsearch

    业务需要把mysql的数据实时同步到ES,实现低延迟的检索到ES中的数据或者进行其它数据分析处理.本文给出以同步mysql binlog的方式实时同步数据到ES的思路, 实践并验证该方式的可行性,以供 ...

  4. lsyncd替代inotify+rsync实现实时同步

    因公司业务需要需要实时同步日志文件,刚一开始使用的是inotify+rsync来实现实时同步,但时间久而久之发现同步的速度越来越慢,往往延迟好几个小时.查了一下网上的inotify+rsync方案基本 ...

  5. 基于Canal和Kafka实现MySQL的Binlog近实时同步

    前提 近段时间,业务系统架构基本完备,数据层面的建设比较薄弱,因为笔者目前工作重心在于搭建一个小型的数据平台.优先级比较高的一个任务就是需要近实时同步业务系统的数据(包括保存.更新或者软删除)到一个另 ...

  6. 基于Flume+Kafka+ Elasticsearch+Storm的海量日志实时分析平台(转)

    0背景介绍 随着机器个数的增加.各种服务.各种组件的扩容.开发人员的递增,日志的运维问题是日渐尖锐.通常,日志都是存储在服务运行的本地机器上,使用脚本来管理,一般非压缩日志保留最近三天,压缩保留最近1 ...

  7. 基于OGG的Oracle与Hadoop集群准实时同步介绍

    版权声明:本文由王亮原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/220 来源:腾云阁 https://www.qclou ...

  8. 和我一起打造个简单搜索之Logstash实时同步建立索引

    用过 Solr 的朋友都知道,Solr 可以直接在配置文件中配置数据库连接从而完成索引的同步创建,但是 ElasticSearch 本身并不具备这样的功能,那如何建立索引呢?方法其实很多,可以使用 J ...

  9. sersync基于rsync+inotify实现数据实时同步

    一.环境描述 需求:服务器A与服务器B为主备服务模式,需要保持文件一致性,现采用sersync基于rsync+inotify实现数据实时同步 主服务器A:192.168.1.23 从服务器B:192. ...

随机推荐

  1. 关于AndroidStudio项目app在手机上运行遇到登录网络问题的解决

    又得提到我熟悉的12月份末尾,依旧想着把自己遇到的问题给大家看看,顺便分享我的解决办法. 看过我第一个发的随笔就知道,我遇到过给项目app打包成apk的问题啊,虽然解决了,但是运行到手机上 就又出现了 ...

  2. C# Base64字符串生成图片

    C# Base64字符串生成图片: //签字图片Base64格式去除开头多余字符data:image/png;base64, strSignImg = strSignImg.Substring(str ...

  3. 按位与(&),或(|),异或(^),取反(~),左移(<<),右移(>>)

    C语言提供的位运算符列表:运算符 含义 描述& 按位与 如果两个相应的二进制位都为1,则该位的结果值为1,否则为0| 按位或 两个相应的二进制位中只要有一个为1,该位的结果值为1^ 按位异或 ...

  4. C++中字符数组和字符指针问题

    环境:vs2010 说明:在阅读这部分内容之前应该先明确C++内存分配问题 ,那一篇文章说的比较清楚. 1.字符数组,初始化: char str1[]="abc"; char st ...

  5. 14-Flutter移动电商实战-ADBanner组件的编写

    拨打电话的功能在app里也很常见,比如一般的外卖app都会有这个才做.其实Flutter本身是没给我们提供拨打电话的能力的,那我们如何来拨打电话那? 1.编写店长电话模块 这个小伙伴们一定轻车熟路了, ...

  6. webpack的loader的原理和实现

    想要实现一个loader,需要首先了解loader的基本原理和用法. 1. 使用 loader是处理模块的解析器. module: { rules: [ { test: /\.css$/, use: ...

  7. webpack提高打包速度

    通过使用插件和配置插件的参数. 1. 打包速度分析 首先通过speed-measure-webpack-plugin分析打包的各个插件和loader的耗时.然后具体问题,具体分析. 按照插件 npm ...

  8. .NET体系结构

    主要内容包括: C#与.NET的关系.公共语言运行库.中间语言.程序集..NET Framework类.名称空间.内层管理... C#与.NET的关系 C#是门高级编程语言,.NET(Framewor ...

  9. 65、Spark Streaming:数据接收原理剖析与源码分析

    一.数据接收原理 二.源码分析 入口包org.apache.spark.streaming.receiver下ReceiverSupervisorImpl类的onStart()方法 ### overr ...

  10. c++ 题解

    43题 #include <random> #include <iostream> int main() { ][] = { {,,,}, {,,,}, {,,,}}; ; n ...