spring boot 中logback日志输出到RabbitMq中

最近在接口项目开始使用微服务设计构架,使用的是现在流行的spring cloud技术栈。

网关做权限,限流,日志记录等前置统一入口。在网关统一记录请求及相应日志,单实例的时候情况下,没有问题,但是想到网关压力比较大,于是决定启动多个实例。但是为了查询日志方便,多实例记录的日志打算不分开,还是记录到同一个文件中(按天分割),看到这里可能有人会问,分布式日志收集,为什么不用ELK呢?我们是有ELK系统的,但是平时感觉用的还是比较少,每个日志文件每天就100M以内,而且在无服务器查询日志也挺方便的。

说说碰到的问题,当多个网关实例共同操作同一个日志文件的时候,奇怪的时候会出现只能有一个实例获取操作权限,导致其他实例的日志文件漏打(但是重启其他实例后就没问题,一天时间过后,就出现了只能记录其中一个实例的,现在还不清楚是什么问题),于是就想要不直接把的logback的日志信息,直接输出到的RabbitMQ中,然后MQ消费消息再输出到文件或者上课。大概的意思是

网关实例1日志输出----> RabbitMq |

网关实例2日志输出----> RabbitMq | ------>文件/ ES    

网关实例3日志输出----> RabbitMq |

这样就不会有多个实例操作同一个日志文件的情况了,只要保证消费MQ消息正确,应该不会出现漏打日志的情况。

首先

1.配置一下RabbitMQ的需要的队里,交换器,绑定。(启动注入豆操作)

@Bean
    public Queue logDirectQueue() {
        return new Queue("logDirectQueue");
    }

    @Bean
    public DirectExchange logDirectExchange() {
        return new DirectExchange("log.exchange.direct", false, false);
    }

    /**
     * 根据路由键绑定队列到交换器上
     *
     * @return
     */
    @Bean
    public Binding logDirectBinding() {
        return BindingBuilder.bind(logDirectQueue()).to(logDirectExchange()).with("logDirectQueue");
    }

2.Spring boot的配置文件

spring:
  rabbitmq:
    host: 127.0.0.1
    username: guest
    password: guest
    port: 5672

log:
  path: D:/logs/rabbitmq

logging:
  config: classpath:logback-spring.xml

3.spring-logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <!--日志存储位置(读取配置文件的路径)-->
    <springProperty scope="context" name="log_dir" source="log.path"/>
    <springProperty name="rabbitmqHost" source="spring.rabbitmq.host"/>
    <springProperty name="rabbitmqPort" source="spring.rabbitmq.port"/>
    <springProperty name="rabbitmqUsername" source="spring.rabbitmq.username"/>
    <springProperty name="rabbitmqPassword" source="spring.rabbitmq.password"/>

    <!-- 控制台日志 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) [%class:%line] %highlight(%-5level) - %cyan(%msg%n)
            </pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <appender name="AMQP" class="org.springframework.amqp.rabbit.logback.AmqpAppender">

        <!--Layout(纯文本)而不是格式化的JSON -->
        <layout>
            <pattern>
                <![CDATA[%d{yyyy-MM-dd HH:mm:ss} [%thread] [%class:%line] %-5level %logger - %msg%n ]]>
            </pattern>
        </layout>
        <host>${rabbitmqHost}</host>
        <port>${rabbitmqPort}</port>
        <username>${rabbitmqUsername}</username>
        <password>${rabbitmqPassword}</password>

        <declareExchange>false</declareExchange>
        <exchangeType>direct</exchangeType>
        <exchangeName>log.exchange.direct</exchangeName>
        <routingKeyPattern>logDirectQueue</routingKeyPattern>
        <generateId>true</generateId>
        <charset>UTF-8</charset>
        <durable>false</durable>
        <deliveryMode>NON_PERSISTENT</deliveryMode>
    </appender>

    <!-- 文件记录只记录指定包的日志 -->
    <logger name="com.example.springbootrabbitmq" level="info" additivity="false">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="AMQP"/>
    </logger>

    <root level="INFO">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

这里主要是使用spring为我们提供的组织工具。

4.创建一个消费者

@Component
public class DirectConsumer {

    @RabbitListener(queues = {"directQueue", "logDirectQueue"})
    public void processMessage(String msg) {
        System.err.println("consumer receive a message:" + msg);
    }
}

5.启动项目后,主要去检查一下的RabbitMQ的管理界面,查看队里,交换器,是否创建成功,根据routingkey绑定是否成功。

如果一切成功,我们可以看到每打一个日志就会发送一个消息到绑定的队列。

猜你喜欢

转载自blog.csdn.net/chen846262292/article/details/85062219