1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 【Syslog】采用Syslog4j发送总线日志

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

时间:2022-01-11 23:08:49

相关推荐

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

文章目录

简介Maven依赖UDP 模式搭建日志接收服务端搭建日志发送客户端 TCP 模式搭建日志接收服务端搭建日志发送客户端 使用注意事项UDP 发送设置报文大小问题乱码问题后续问题会持续录入MaxMessageLength 有限制吗? TCP发送拆分发送 总结

简介

Syslog4j是一个实现Syslog(RFC3164)协议的Java开源类库包括客户端与服务器端。通过 UDP/IP, TCP/IP, TCP/IPover SSL/TLS, Unix Syslog, 和 Unix Socket 等协议进行日志记录。

本文使用UDP协议发送日志给总线(这里说的总线只是我们公司有个平台专门管理这些日志)

Maven依赖

<!-- 具体版本可以自己去Maven中央仓库去寻找 --><dependency><groupId>org.graylog2</groupId><artifactId>syslog4j</artifactId><version>0.9.60</version></dependency>

UDP 模式

搭建日志接收服务端

import org.graylog2.syslog4j.SyslogConstants;import org.graylog2.syslog4j.server.*;import .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() {@Overridepublic Object sessionOpened(SyslogServerIF syslogServerIF, SocketAddress socketAddress) {return null;}@Overridepublic void event(Object o, SyslogServerIF syslogServerIF, SocketAddress socketAddress, SyslogServerEventIF syslogServerEventIF) {System.out.println("receive from:" + socketAddress + "message" + syslogServerEventIF.getMessage());}@Overridepublic void exception(Object o, SyslogServerIF syslogServerIF, SocketAddress socketAddress, Exception e) {}@Overridepublic void sessionClosed(Object o, SyslogServerIF syslogServerIF, SocketAddress socketAddress, boolean b) {}@Overridepublic void initialize(SyslogServerIF syslogServerIF) {}@Overridepublic 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();}}

搭建日志发送客户端

package .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 .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();}}

TCP 模式

搭建日志接收服务端

import org.graylog2.syslog4j.SyslogConstants;import org.graylog2.syslog4j.server.*;import .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.TCP);SyslogServerConfigIF config = server.getConfig();config.setHost(HOST);config.setPort(PORT);config.addEventHandler(new SyslogServerSessionEventHandlerIF() {@Overridepublic Object sessionOpened(SyslogServerIF syslogServerIF, SocketAddress socketAddress) {return null;}@Overridepublic void event(Object o, SyslogServerIF syslogServerIF, SocketAddress socketAddress, SyslogServerEventIF syslogServerEventIF) {System.out.println("receive from:" + socketAddress + "message" + syslogServerEventIF.getMessage());}@Overridepublic void exception(Object o, SyslogServerIF syslogServerIF, SocketAddress socketAddress, Exception e) {}@Overridepublic void sessionClosed(Object o, SyslogServerIF syslogServerIF, SocketAddress socketAddress, boolean b) {}@Overridepublic void initialize(SyslogServerIF syslogServerIF) {}@Overridepublic void destroy(SyslogServerIF syslogServerIF) {}});SyslogServer.getThreadedInstance(SyslogConstants.TCP);Thread.sleep(100000);}public static void main(String[] args) throws InterruptedException {System.out.println("Syslog Server is start.");new MySyslogServer().receiveSyslogMessage();}}

搭建日志发送客户端

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 .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.TCP);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);}// 切记这里要加上,因为TCP协议的长链接(也就是握手特点)Thread.sleep(10000)}public static void main(String[] args) {new MySyslogClient().generate();}}

使用注意事项

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(65507); // 64KB

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

乱码问题

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

URLDecoder.decode(String var)

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

后续问题会持续录入

MaxMessageLength 有限制吗?

有,64KB就是最大限度,这个限制不是Syslog4j做的限制,是底层DatagramPacket.java的限制。超过64KB就会拆包,也就截断报文分多次发送。如果你直接给个50MB的限制,底层就会抛出异常,最恶心的就是Syslog4j捕获了异常,但是没有跑出来,并且出现异常后会重新实例化发送。

正常来说,假设你的内容是70kb,但是你想一次性全部发出去,你把MaxMessageLength设置到大于64KB,底层会出现这个异常

TCP发送拆分发送

这里的报文分行分送,后来发现我发送的文本就是分行的,因此,我们只要对读出字符流String,通过正则替换成整行,就可以直接一个包发过去了,前提也是需要配置MaxMessageLength的属性值大小

// 无论你是读文件,还是JSON序列化对象,只要是字符串就可以了,但是保不齐的来源存在换行符 因此需要借助下面的正则来替换成单行String modelStr = ""; String reg = "\\s+";modelStr = modelStr.replaceAll(reg, " ");

总结

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。