• 【Syslog】采用Syslog4j发送总线日志


    简介

    Syslog4j是一个实现Syslog(RFC3164)协议的Java开源类库包括客户端与服务器端。通过 UDP/IP, TCP/IP, TCP/IPover SSL/TLS, Unix Syslog, 和 Unix Socket 等协议进行日志记录。
    本文使用UDP协议发送日志给总线(这里说的总线只是我们公司有个平台专门管理这些日志)

    Maven依赖

    		
     		<dependency>
                <groupId>org.graylog2groupId>
                <artifactId>syslog4jartifactId>
                <version>0.9.60version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    搭建日志接收服务端

    import org.graylog2.syslog4j.SyslogConstants;
    import org.graylog2.syslog4j.server.*;
    
    import java.net.SocketAddress;
    
    public class MySyslogServer {
        private static final String HOST = "127.0.0.1";
        private static final int PORT = 32376;
    
        private void receiveSyslogMessage() throws InterruptedException {
            SyslogServerIF server = SyslogServer.getInstance(SyslogConstants.UDP);
            SyslogServerConfigIF config = server.getConfig();
            config.setHost(HOST);
            config.setPort(PORT);
            config.addEventHandler(new SyslogServerSessionEventHandlerIF() {
                @Override
                public Object sessionOpened(SyslogServerIF syslogServerIF, SocketAddress socketAddress) {
                    return null;
                }
    
                @Override
                public void event(Object o, SyslogServerIF syslogServerIF, SocketAddress socketAddress, SyslogServerEventIF syslogServerEventIF) {
                    System.out.println("receive from:" + socketAddress + "message" + syslogServerEventIF.getMessage());
                }
    
                @Override
                public void exception(Object o, SyslogServerIF syslogServerIF, SocketAddress socketAddress, Exception e) {
                }
    
                @Override
                public void sessionClosed(Object o, SyslogServerIF syslogServerIF, SocketAddress socketAddress, boolean b) {
                }
    
                @Override
                public void initialize(SyslogServerIF syslogServerIF) {
                }
    
                @Override
                public void destroy(SyslogServerIF syslogServerIF) {
                }
            });
            SyslogServer.getThreadedInstance(SyslogConstants.UDP);
            Thread.sleep(100000);
        }
    
        public static void main(String[] args) throws InterruptedException {
            System.out.println("Syslog Server is start.");
            new MySyslogServer().receiveSyslogMessage();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    搭建日志发送客户端

    package cn.com.mcd.data.syslog;
    
    import com.alibaba.fastjson.JSONObject;
    import org.graylog2.syslog4j.Syslog;
    import org.graylog2.syslog4j.SyslogConstants;
    import org.graylog2.syslog4j.SyslogIF;
    
    import java.io.UnsupportedEncodingException;
    import java.net.URLDecoder;
    
    public class MySyslogClient {
        private static final String HOST = "127.0.0.1";
        private static final int PORT = 32376;
    
        public void generate() {
            SyslogIF syslog = Syslog.getInstance(SyslogConstants.UDP);
            syslog.getConfig().setHost(HOST);
            syslog.getConfig().setPort(PORT);
            try {
            	// 这里就是发送日志,当前它的API接口有很多种,都可以尝试一样
            	// 参数: 10  ----> 表示日志等级  当一个单体应用中,存在多个任务发送日志,这时候级别的作用就体现出现了
            	// 		   URLDecoder.decode("测试发送"+ System.currentTimeMillis(), "UTF-8")  表示发送内容以及编码格式
                syslog.log(10, URLDecoder.decode("测试发送"+ System.currentTimeMillis(), "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                System.out.println("generate log get exception " + e);
            }
        }
    
        public static void main(String[] args) {
            new MySyslogClient().generate();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    在这里插入图片描述

    使用注意事项

    UDP 发送设置报文大小问题

    UDP发送信息,默认数据体不能超过1k,不然就会被默认拆包,因为本公司业务场景中会把特定时间的哪些用户执行哪些SQL(SQL估摸着至少4000个字符串)发送给总线,这时候就会出现以下情况:
    在这里插入图片描述
    4kb的数据被拆分为了5个包,会导致接收端出现拼接符号…
    在这里插入图片描述
    这里给出的解决方案设置报文大小

    // 实例化Syslog的时候
    SyslogIF syslog = Syslog.getInstance(SyslogConstants.UDP);
    syslog.getConfig().setHost(HOST);
    syslog.getConfig().setPort(PORT);
    syslog.getConfig().setMaxMessageLength(52428800); // 50MB
    
    • 1
    • 2
    • 3
    • 4
    • 5

    因为安全规则以及职业道德,这里就不展示修改为50MB发送日志的成功场景,大家可以依据自己的业务范围设置大小发送。

    乱码问题

    第一玩着这个功能的时候,没有设置编码格式,导致中文字符(GBK)到服务器端接收日志的时候,出现乱码

    URLDecoder.decode(String var)
    
    • 1

    使用以上方法可以规避这些问题

    后续问题会持续录入

    总结

    建议大家在使用这个工具的时候,下载一个WireShark这一类抓包软件,可以进行本地抓包,用来判断是否发送出去了,以及发送的时候出现的问题,例如UDP报文大小,我一开始也是不知道,后来总线那边的同事提醒我了,我也观察到了那些省略号分布很规律,就意识到大事不妙了,但是控制台打印的日志是完整的,也就说在传输的过程中肯定是出了什么问题,无论是TCP还是UDP都已经在计算机的传输层了,我们是看不到它们的流程的,这时候抓包工具就至关重要了。

  • 相关阅读:
    ATF(TF-A) fvp_r 平台威胁模型-安全检测与评估
    仿上海学校网站学生网页设计作品 dreamweaver作业静态HTML网页设计模板 旅游景点网页作业制作
    CSS 实现动态显示隐藏(:checked 和 :target 的妙用)
    基于SqlSugar的开发框架循序渐进介绍(13)-- 基于ElementPlus的上传组件进行封装,便于项目使用
    试剂盒和示踪剂—艾美捷FLIVO探针活体凋亡检测分析
    Kubernetes 1.25.4数据平面自带nginx负载均衡实现高可用
    拓扑结构+差分约束+SLF最长路+扩欧
    web立体相册
    MySQL数据库技术笔记(5)
    抓取手机端变体组合思路设想
  • 原文地址:https://blog.csdn.net/weixin_44922964/article/details/126359301