1、新增功能探针联动处置、心跳在线检测
2、syslog-consumer模块拆分 syslog-consumer-rule模块实现日志数据消费、解析、泛化入库。
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
package com.netty;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Syslog 消息实体类
|
||||
*/
|
||||
public class SyslogMessage {
|
||||
private Integer facility;
|
||||
private Integer severity;
|
||||
private Date timestamp;
|
||||
private String hostname;
|
||||
private String message;
|
||||
|
||||
// 构造函数
|
||||
public SyslogMessage() {}
|
||||
|
||||
// Getter 和 Setter 方法
|
||||
public Integer getFacility() {
|
||||
return facility;
|
||||
}
|
||||
|
||||
public void setFacility(Integer facility) {
|
||||
this.facility = facility;
|
||||
}
|
||||
|
||||
public Integer getSeverity() {
|
||||
return severity;
|
||||
}
|
||||
|
||||
public void setSeverity(Integer severity) {
|
||||
this.severity = severity;
|
||||
}
|
||||
|
||||
public Date getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(String timestamp) {
|
||||
// 这里可以添加时间戳解析逻辑
|
||||
// 简化实现,直接使用当前时间
|
||||
this.timestamp = new Date();
|
||||
}
|
||||
|
||||
public void setTimestamp(Date timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public String getHostname() {
|
||||
return hostname;
|
||||
}
|
||||
|
||||
public void setHostname(String hostname) {
|
||||
this.hostname = hostname;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SyslogMessage{" +
|
||||
"facility=" + facility +
|
||||
", severity=" + severity +
|
||||
", timestamp=" + timestamp +
|
||||
", hostname='" + hostname + '\'' +
|
||||
", message='" + message + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
package com.netty;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.channel.socket.DatagramPacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import com.kafka.kafkaProducer;
|
||||
import com.Modules.Device.DeviceProcess;
|
||||
import com.haobang.util.Sm4Util;
|
||||
import com.haobang.config.AppConfig;
|
||||
/**
|
||||
* Syslog 消息处理器
|
||||
*/
|
||||
public class SyslogMessageHandler extends SimpleChannelInboundHandler<Object> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SyslogMessageHandler.class);
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
String message;
|
||||
String source;
|
||||
String source_ip;
|
||||
String networkProtocol;
|
||||
int source_port;
|
||||
if (msg instanceof DatagramPacket) {
|
||||
// UDP 消息处理
|
||||
DatagramPacket packet = (DatagramPacket) msg;
|
||||
message = packet.content().toString(io.netty.util.CharsetUtil.UTF_8);
|
||||
source_ip=packet.sender().getAddress().getHostAddress();
|
||||
source_port=packet.sender().getPort();
|
||||
source = packet.sender().getAddress().getHostAddress() + ":" + packet.sender().getPort();
|
||||
networkProtocol="UDP";
|
||||
logger.info("Received syslog from {}: {}", source, message);
|
||||
} else if (msg instanceof String) {
|
||||
// TCP 消息处理
|
||||
message = (String) msg;
|
||||
InetSocketAddress remoteAddress = (InetSocketAddress) ctx.channel().remoteAddress();
|
||||
source = remoteAddress.getAddress().getHostAddress() + ":" + remoteAddress.getPort();
|
||||
source_ip=remoteAddress.getAddress().getHostAddress();
|
||||
source_port=remoteAddress.getPort();
|
||||
networkProtocol="TCP";
|
||||
logger.info("Received syslog from {}: {}", source, message);
|
||||
} else {
|
||||
logger.warn("Received unknown message type: {}", msg.getClass().getName());
|
||||
return;
|
||||
}
|
||||
DeviceProcess deviceProcess = new DeviceProcess(source_ip);
|
||||
try {
|
||||
//日志推送的设备信息进行鉴权处理
|
||||
int deviceId = deviceProcess.getDeviceID(source_ip);
|
||||
if (deviceId < 0) {
|
||||
logger.info("syslog message 的请求设备IP:{}非系统注册,暂不做处理!",source_ip);
|
||||
//创建未知设备
|
||||
deviceProcess.saveDeviceUnknow(networkProtocol);
|
||||
return;
|
||||
}
|
||||
if (!deviceProcess.IsBelongDeviceCollectTask()) {
|
||||
logger.info("syslog message 的请求设备IP:{}不归属当前采集探针,暂不做处理!",source_ip);
|
||||
return;
|
||||
}
|
||||
//插入PG库接收记录
|
||||
deviceProcess.saveDeviceReceiveLog(message,true);
|
||||
kafkaProducer.messagePush(deviceProcess.getDeviceDevice(), message, deviceProcess.getDeviceReceiveLog().getReceiveTimeStr());
|
||||
|
||||
} catch (Exception e) {
|
||||
//记录日志推送失败
|
||||
deviceProcess.saveDeviceReceiveLog(message,false);
|
||||
logger.warn("Failed to Push syslog message", e);
|
||||
|
||||
}
|
||||
// 处理 Syslog 消息
|
||||
//processSyslogMessage(message.trim(), source);
|
||||
}
|
||||
|
||||
private void processSyslogMessage(String message, String source) {
|
||||
// 这里可以添加 Syslog 消息解析逻辑
|
||||
// 根据 RFC 3164 或 RFC 5424 解析消息
|
||||
System.out.println("Received syslog from "+ source +", msg:"+ message);
|
||||
logger.info("Received syslog from {}: {}", source, message);
|
||||
|
||||
|
||||
try {
|
||||
SyslogMessage syslogMsg = parseSyslogMessage(message);
|
||||
logger.info("Parsed syslog - Facility: {}, Severity: {}, Timestamp: {}, Host: {}, Message: {}",
|
||||
syslogMsg.getFacility(),
|
||||
syslogMsg.getSeverity(),
|
||||
syslogMsg.getTimestamp(),
|
||||
syslogMsg.getHostname(),
|
||||
syslogMsg.getMessage());
|
||||
|
||||
// 这里可以添加消息存储或其他处理逻辑
|
||||
// storeToDatabase(syslogMsg);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.warn("Failed to parse syslog message: {}", message, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 简单的 Syslog 消息解析(RFC 3164 格式)
|
||||
*/
|
||||
private SyslogMessage parseSyslogMessage(String message) {
|
||||
SyslogMessage syslogMsg = new SyslogMessage();
|
||||
|
||||
// 尝试解析 PRI 部分
|
||||
if (message.startsWith("<")) {
|
||||
int priEnd = message.indexOf(">");
|
||||
if (priEnd > 0) {
|
||||
String priStr = message.substring(1, priEnd);
|
||||
try {
|
||||
int pri = Integer.parseInt(priStr);
|
||||
int facility = pri >> 3;
|
||||
int severity = pri & 0x07;
|
||||
|
||||
syslogMsg.setFacility(facility);
|
||||
syslogMsg.setSeverity(severity);
|
||||
|
||||
message = message.substring(priEnd + 1).trim();
|
||||
} catch (NumberFormatException e) {
|
||||
// 忽略 PRI 解析错误
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试解析时间戳和主机名
|
||||
// 这是一个简化的解析,实际实现可能需要更复杂的逻辑
|
||||
String[] parts = message.split(" ", 5);
|
||||
if (parts.length >= 4) {
|
||||
// 假设前三个部分是时间戳,第四个部分是主机名
|
||||
String timestamp = parts[0] + " " + parts[1] + " " + parts[2];
|
||||
syslogMsg.setTimestamp(timestamp);
|
||||
syslogMsg.setHostname(parts[3]);
|
||||
|
||||
if (parts.length == 5) {
|
||||
syslogMsg.setMessage(parts[4]);
|
||||
}
|
||||
} else {
|
||||
syslogMsg.setMessage(message);
|
||||
}
|
||||
|
||||
return syslogMsg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
logger.error("Exception in channel handler", cause);
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.netty;
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioDatagramChannel;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Syslog 服务器主类,支持 TCP 和 UDP 协议
|
||||
*/
|
||||
public class SyslogServer {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SyslogServer.class);
|
||||
|
||||
private final int tcpPort;
|
||||
private final int udpPort;
|
||||
|
||||
public SyslogServer(int tcpPort, int udpPort) {
|
||||
this.tcpPort = tcpPort;
|
||||
this.udpPort = udpPort;
|
||||
}
|
||||
|
||||
public void start() throws InterruptedException {
|
||||
|
||||
// 启动 TCP 服务器
|
||||
startTcpServer();
|
||||
// 启动 UDP 服务器
|
||||
startUdpServer();
|
||||
}
|
||||
|
||||
private void startTcpServer() throws InterruptedException {
|
||||
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
|
||||
EventLoopGroup workerGroup = new NioEventLoopGroup();
|
||||
|
||||
try {
|
||||
ServerBootstrap b = new ServerBootstrap();
|
||||
b.group(bossGroup, workerGroup)
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.childHandler(new SyslogTcpChannelInitializer())
|
||||
.option(ChannelOption.SO_BACKLOG, 128)
|
||||
.childOption(ChannelOption.SO_KEEPALIVE, true);
|
||||
|
||||
ChannelFuture f = b.bind(tcpPort).sync();
|
||||
logger.info("TCP Syslog server started on port {}", tcpPort);
|
||||
|
||||
f.channel().closeFuture().sync();
|
||||
} finally {
|
||||
workerGroup.shutdownGracefully();
|
||||
bossGroup.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
private void startUdpServer() throws InterruptedException {
|
||||
EventLoopGroup group = new NioEventLoopGroup();
|
||||
|
||||
try {
|
||||
Bootstrap b = new Bootstrap();
|
||||
b.group(group)
|
||||
.channel(NioDatagramChannel.class)
|
||||
.handler(new SyslogUdpChannelInitializer())
|
||||
.option(ChannelOption.SO_BROADCAST, true);
|
||||
|
||||
ChannelFuture f = b.bind(udpPort).sync();
|
||||
logger.info("UDP Syslog server started on port {}", udpPort);
|
||||
|
||||
f.channel().closeFuture().sync();
|
||||
} finally {
|
||||
group.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int tcpPort = args.length > 0 ? Integer.parseInt(args[0]) : 514;
|
||||
int udpPort = args.length > 1 ? Integer.parseInt(args[1]) : 514;
|
||||
|
||||
SyslogServer server = new SyslogServer(tcpPort, udpPort);
|
||||
server.start();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
package com.netty;
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioDatagramChannel;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Syslog 服务器主类,支持 TCP 和 UDP 协议
|
||||
*/
|
||||
public class SyslogServerBoth {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SyslogServer.class);
|
||||
|
||||
private final int tcpPort;
|
||||
private final int udpPort;
|
||||
|
||||
// 共享的EventLoopGroup以优化资源使用
|
||||
private EventLoopGroup bossGroup;
|
||||
private EventLoopGroup workerGroup;
|
||||
private EventLoopGroup udpGroup;
|
||||
|
||||
private ChannelFuture tcpChannelFuture;
|
||||
private ChannelFuture udpChannelFuture;
|
||||
|
||||
private final ExecutorService serverExecutor = Executors.newFixedThreadPool(2);
|
||||
|
||||
public SyslogServerBoth(int tcpPort, int udpPort) {
|
||||
this.tcpPort = tcpPort;
|
||||
this.udpPort = udpPort;
|
||||
}
|
||||
|
||||
public void start() throws InterruptedException {
|
||||
logger.info("Starting Syslog server with TCP port {} and UDP port {}", tcpPort, udpPort);
|
||||
|
||||
// 创建共享的EventLoopGroup
|
||||
bossGroup = new NioEventLoopGroup(1);
|
||||
workerGroup = new NioEventLoopGroup();
|
||||
udpGroup = new NioEventLoopGroup();
|
||||
|
||||
final CountDownLatch latch = new CountDownLatch(2);
|
||||
|
||||
try {
|
||||
// 启动UDP服务器(使用独立的线程)
|
||||
serverExecutor.submit(() -> {
|
||||
try {
|
||||
startUdpServer();
|
||||
latch.countDown();
|
||||
} catch (Exception e) {
|
||||
logger.error("UDP server failed to start", e);
|
||||
latch.countDown();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
// 启动TCP服务器(使用独立的线程)
|
||||
serverExecutor.submit(() -> {
|
||||
try {
|
||||
startTcpServer();
|
||||
latch.countDown();
|
||||
} catch (Exception e) {
|
||||
logger.error("TCP server failed to start", e);
|
||||
latch.countDown();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
// 等待两个服务器都启动完成
|
||||
latch.await();
|
||||
logger.info("Both TCP and UDP Syslog servers are running");
|
||||
|
||||
// 注册关闭钩子
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown));
|
||||
|
||||
// 保持主线程运行
|
||||
Thread.currentThread().join();
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to start servers", e);
|
||||
shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private void startTcpServer() throws InterruptedException {
|
||||
ServerBootstrap b = new ServerBootstrap();
|
||||
b.group(bossGroup, workerGroup)
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.childHandler(new SyslogTcpChannelInitializer())
|
||||
.option(ChannelOption.SO_BACKLOG, 128)
|
||||
.childOption(ChannelOption.SO_KEEPALIVE, true);
|
||||
|
||||
tcpChannelFuture = b.bind(tcpPort).sync();
|
||||
logger.info("TCP Syslog server started on port {}", tcpPort);
|
||||
|
||||
// 添加关闭监听器
|
||||
tcpChannelFuture.channel().closeFuture().addListener(future -> {
|
||||
if (future.isSuccess()) {
|
||||
logger.info("TCP server channel closed");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void startUdpServer() throws InterruptedException {
|
||||
Bootstrap b = new Bootstrap();
|
||||
b.group(udpGroup)
|
||||
.channel(NioDatagramChannel.class)
|
||||
.handler(new SyslogUdpChannelInitializer())
|
||||
.option(ChannelOption.SO_BROADCAST, true);
|
||||
|
||||
udpChannelFuture = b.bind(udpPort).sync();
|
||||
logger.info("UDP Syslog server started on port {}", udpPort);
|
||||
|
||||
// 添加关闭监听器
|
||||
udpChannelFuture.channel().closeFuture().addListener(future -> {
|
||||
if (future.isSuccess()) {
|
||||
logger.info("UDP server channel closed");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 优雅关闭服务器
|
||||
*/
|
||||
public void shutdown() {
|
||||
logger.info("Shutting down Syslog servers...");
|
||||
|
||||
try {
|
||||
// 关闭TCP服务器
|
||||
if (tcpChannelFuture != null) {
|
||||
tcpChannelFuture.channel().close().sync();
|
||||
}
|
||||
|
||||
// 关闭UDP服务器
|
||||
if (udpChannelFuture != null) {
|
||||
udpChannelFuture.channel().close().sync();
|
||||
}
|
||||
|
||||
// 关闭EventLoopGroup
|
||||
if (bossGroup != null) {
|
||||
bossGroup.shutdownGracefully().sync();
|
||||
}
|
||||
if (workerGroup != null) {
|
||||
workerGroup.shutdownGracefully().sync();
|
||||
}
|
||||
if (udpGroup != null) {
|
||||
udpGroup.shutdownGracefully().sync();
|
||||
}
|
||||
|
||||
// 关闭线程池
|
||||
serverExecutor.shutdown();
|
||||
|
||||
logger.info("Syslog servers shutdown complete");
|
||||
} catch (Exception e) {
|
||||
logger.error("Error during shutdown", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查服务器是否在运行
|
||||
*/
|
||||
public boolean isRunning() {
|
||||
return (tcpChannelFuture != null && tcpChannelFuture.channel().isActive()) ||
|
||||
(udpChannelFuture != null && udpChannelFuture.channel().isActive());
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int tcpPort = 514;
|
||||
int udpPort = 514;
|
||||
|
||||
// 解析命令行参数
|
||||
if (args.length >= 1) {
|
||||
tcpPort = Integer.parseInt(args[0]);
|
||||
}
|
||||
if (args.length >= 2) {
|
||||
udpPort = Integer.parseInt(args[1]);
|
||||
}
|
||||
|
||||
// 如果两个端口相同,UDP端口自动+1避免冲突
|
||||
if (tcpPort == udpPort) {
|
||||
udpPort = tcpPort + 1;
|
||||
logger.warn("TCP and UDP ports cannot be the same. UDP port changed to {}", udpPort);
|
||||
}
|
||||
|
||||
SyslogServerBoth server = new SyslogServerBoth(tcpPort, udpPort);
|
||||
|
||||
// 注册全局异常处理器
|
||||
Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
|
||||
logger.error("Uncaught exception in thread {}", t.getName(), e);
|
||||
});
|
||||
|
||||
server.start();
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.netty;
|
||||
|
||||
|
||||
import com.haobang.config.AppConfig;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
|
||||
import io.netty.handler.codec.Delimiters;
|
||||
import io.netty.handler.codec.string.StringDecoder;
|
||||
import io.netty.handler.codec.string.StringEncoder;
|
||||
import io.netty.util.CharsetUtil;
|
||||
|
||||
/**
|
||||
* TCP 通道初始化器
|
||||
*/
|
||||
public class SyslogTcpChannelInitializer extends ChannelInitializer<SocketChannel> {
|
||||
private static final int MAX_FRAME_LENGTH = AppConfig.getSyslogMaxFrameLength();
|
||||
|
||||
@Override
|
||||
protected void initChannel(SocketChannel ch) throws Exception {
|
||||
ChannelPipeline pipeline = ch.pipeline();
|
||||
|
||||
// 添加基于分隔符的帧解码器,处理以换行符结尾的 Syslog 消息
|
||||
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(
|
||||
MAX_FRAME_LENGTH,
|
||||
Delimiters.lineDelimiter()));
|
||||
|
||||
// 添加字符串解码器和编码器
|
||||
pipeline.addLast("decoder", new StringDecoder(CharsetUtil.UTF_8));
|
||||
pipeline.addLast("encoder", new StringEncoder(CharsetUtil.UTF_8));
|
||||
|
||||
// 添加业务处理器
|
||||
pipeline.addLast("handler", new SyslogMessageHandler());
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package com.netty;
|
||||
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.socket.DatagramChannel;
|
||||
import io.netty.handler.codec.string.StringDecoder;
|
||||
import io.netty.handler.codec.string.StringEncoder;
|
||||
import io.netty.util.CharsetUtil;
|
||||
|
||||
/**
|
||||
* UDP 通道初始化器
|
||||
*/
|
||||
public class SyslogUdpChannelInitializer extends ChannelInitializer<DatagramChannel> {
|
||||
@Override
|
||||
protected void initChannel(DatagramChannel ch) throws Exception {
|
||||
ChannelPipeline pipeline = ch.pipeline();
|
||||
|
||||
// 添加字符串解码器和编码器
|
||||
pipeline.addLast("decoder", new StringDecoder(CharsetUtil.UTF_8));
|
||||
pipeline.addLast("encoder", new StringEncoder(CharsetUtil.UTF_8));
|
||||
|
||||
// 添加业务处理器
|
||||
pipeline.addLast("handler", new SyslogMessageHandler());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user