参考《logback官方中文版文档》
-
SocketAppender被设计为通过序列化ILoggingEvent实例把记录输出到远程实体。被序列化的事件的真实类型是LoggingEventVO, 它实现了ILoggingEvent接口。尽管如此, 就记录事件而言, 远程记录仍然是无损的。在接收和反序列化后, 事件像是从本地产生的一样被记录。运行在不同机器上的多个SocketAppender实例可以把各自的记录输出到一个格式固定的中央记录服务器。
-
SocketAppender不关联layout, 因为它把序列化的事件发送到远程服务器。SocketAppender运作在TCP层上, TCP层提供可靠、有序、流量控制的端到端的二进制流。因此, 如果远程服务器可访问, 则记录事件最终会到达那里。否则, 如果远程服务器关机或不可访问, 那么记录事件会被抛弃。当远程服务器恢复可用时, 会透明地继续传输事件。这种透明的重新连接是由一个连接器(connector)线程执行的, 它定时尝试连接服务器。
-
记录事件被本地TCP实现自动地缓冲。这意味着如果服务器连接很慢, 但快于客户端生成事件的速度, 那么客户端不会受网络连接慢的影响。但是如果网络连接慢于生成事件的速度, 那么客户端只能按网络速度执行。特别是在服务器宕机这种极端情况下, 客户端会被阻塞。
-
如果连接器线程仍然存在, 即使SocketAppender不再关联到任何logger, 也不会被垃圾回收。连接器线程只在当与服务器之间没有连接时存在。为避免这个垃圾回收问题, 你应当显式地关闭 SocketAppender。会创建/销毁很多SocketAppender实例的长期运行的程序应当注意这个垃圾回收问题。多数其他程序可以安全地忽略这个问题。如果宿主JVM在SocketAppender关闭之前退出了, 不管 SocketAppender被显式关闭还是交给垃圾回收, 都有可能在管道(pipe)里剩有一些未被传输的数据, 这些数据会丢失。为避免数据丢失, 一般在退出程序之前显式地调用SocketAppender的close()方法或调用LoggerContext的stop()方法就可以了。
-
SocketAppender的属性见下表
-
Logback标准发行包含一个简单的记录服务器程序"ch.qos.logback.classic.net.SimpleSocketServer", 可以支持多个SocketAppender客户端。它等待来自SocketAppender客户端的记录事件, 接收到事件后, 按照本地服务器的记录策略进行记录。
通过SocketAppender传输日志例子
一、服务端(用于接收并处理日志)
1. 编辑MyServer.java
该服务启动后自动监听端口port:9999发送过来的日志
package com.zr.server;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.net.SimpleSocketServer;
public class MyServer {
public static void main(String[] args) {
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
SimpleSocketServer sss = new SimpleSocketServer(lc, 9999);
sss.start();
}
}
集成到spring-boot项目中采用以下方式:
在启动类中启动SimpleSocketServer
import ...
@SpringBootApplication
@...("...")
@....
public class SpringApplication{
public static void main (String[] args){
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
SimpleSocketServer sss = new SimpleSocketServer(lc, 9999); //该端口无法写入spring配置文件,因为启动加载顺序问题,可以添加到环境变量;
SpringApplication.run(SpringApplication.class,args);
sss.start();
}
}
2. logback.xml配置文件
该配置文件就按想要对日志进行处理的操作来配置就行,在第一步的代码运行后,客户端传过来的日志已经被服务端进行记录了,此时服务端的日志打印内容包括服务端本身的日志和客户端传过来的日志,通过配置文件可以选择将日志进行何种处理。
一个服务可以监听多个客户端
二、客户端(主服务的日志。发送给server)
只需通过配置文件完成:
logback.xml中Socket传输相关配置如下
<configuration>
...
<!--将日志传输到服务端进行处理-->
<appender name="socket" class="ch.qos.logback.classic.net.SocketAppender">
<remoteHost>127.0.0.1</remoteHost>
<port>9999</port>
<ReconnectionDelay>10000</ReconnectionDelay>
<IncludeCallerData>false</IncludeCallerData>
</appender>
<!--采用异步的方式-->
<appender name="socket_async" class="ch.qos.logback.classic.AsyncAppender">
<filter class="可以自定义filter,只将特定日志进行该操作"/>
<appender-ref ref="socket"/>
</appender>
<root level="debug">
...
<appender-ref ref="socket_async" />
</root>
</configuration>
自定义Filter
package ...
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;
public class MyDBFilter extends Filter<ILoggingEvent> {
@Override
public FilterReply decide(ILoggingEvent event) {
if (event.getMessage() != null &&
//包含"logsocket"字段的日志才会被操作
event.getFormattedMessage().contains("logsocket")) {
return FilterReply.ACCEPT;
} else {
return FilterReply.DENY;
}
}
}
logback自带的SimpleSocketServer不是很强大不能打印客户端的ip和端口信息,可以自行编写SocketServer。