19.docker 安装 RocketMq 并配置log4j2来收集日志

一.安装docker RocketMq

1.创建 nameSrv 数据挂载文件夹

mkdir -p data/rocketMQ/data/namesrv/logs
mkdir -p data/rocketMQ/data/namesrv/store

 

 

 

 

 2.查看RocketMq镜像来源

docker search rocketmq

  

 

 

 3.找个star 最多的,我选择的是rocketmqinc/rocketmq

docker pull rocketmqinc/rocketmq

  

 

 

 4.启动 namesrv 服务

docker run -d -p 9876:9876 -v /data/rocketMQ/data/namesrv/logs:/root/logs -v /data/rocketMQ/data/namesrv/store:/root/store --name rmqnamesrv -e "MAX_POSSIBLE_HEAP=100000000" docker.io/rocketmqinc/rocketmq sh mqnamesrv

 

 5.安装 broker

创建 broker 配置文件挂载文件夹

mkdir -p /data/rocketMQ/data/broker/logs
mkdir -p /data/rocketMQ/data/broker/store
mkdir -p /data/rocketMQ/data/broker/conf/

  

 

 

 6.新增 broker 配置文件,在 /data/rocketMQ/data/broker/conf 目录下创建 broker.conf 文件,内容如下:

brokerClusterName = DefaultCluster
brokerName = broker-a
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
brokerRole = ASYNC_MASTER
flushDiskType = ASYNC_FLUSH
#自己的ip brokerIP1 = 192.168.88.50

  

 

 

 

 

 

 7.运行 broker 容器

docker run -d -p 10911:10911 -p 10909:10909 -v /data/rocketMQ/data/broker/logs:/root/logs -v /data/rocketMQ/data/broker/store:/root/store -v /data/rocketMQ/data/broker/conf/broker.conf:/opt/rocketmq-4.4.0/conf/broker.conf --name rmqbroker --link rmqnamesrv:rmqnamesrv -e "NAMESRV_ADDR=192.168.88.50:9876" -e "MAX_POSSIBLE_HEAP=200000000" rocketmqinc/rocketmq:4.4.0 sh mqbroker -c /opt/rocketmq-4.4.0/conf/broker.conf

  

 

 

 8.安装控制台

docker search rocketmq-console

  同样选择一个,我选择styletang/rocketmq-console-ng 

 

 

 9.获取控制台

docker pull styletang/rocketmq-console-ng

  

 

 

 

10.启动控制台镜像

#注意红色地址采用的是上面nameSrv 配置的
docker run -d -p 8080:8080 -e "JAVA_OPTS=-Drocketmq.config.namesrvAddr=192.168.88.50:9876 -Drocketmq.config.isVIPChannel=false" -t styletang/rocketmq-console-ng

  

 

 

 浏览器登录

http://192.168.88.50:8080

 

 

 

 

 

 

 

二.配置springboot log4j2配置文件

 1.在RocketMq平台新增主题 Log4j2ToRocketMq

 

 2.spring-boot 项目 log4j2.xml 配置

由于log4j2暂时没有支持RocketMq,决定扩展AbstractAppender来实现自己的RocketMqAppender

首先maven部分

      <!--RocketMQ-->
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-spring-boot-starter</artifactId>
            <version>2.0.4</version>
        </dependency>
        <!--log4j2-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>        

  RocketMqAppender 实现,后续优化

package com.company.project.appenders;

import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.appender.AppenderLoggingException;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;

import java.io.Serializable;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;


/**
 * 自定义Appender,继承 AbstractAppender 只需要覆盖自已想要的方法即可<br>
 * 类上面的注解是用来设置配置文件中的标签。
 */
@Plugin(name = "RocketMqAppender", category = "Core", elementType = "appender", printObject = true)
public final class RocketMqAppender extends AbstractAppender implements Serializable {

    private static final long serialVersionUID = -5120699436731845929L;
    private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
    private final Lock readLock = rwLock.readLock();
    private static DefaultMQProducer producer;
    private static String rocketMqNameserver;
    private static String rocketMqProducerGroup;
    private static String rocketMqMsgTopic;
    private static String rocketMqMsgTag;

    //需要实现的构造方法,直接使用父类就行
    private RocketMqAppender(final String name, final Filter filter, final Layout<? extends Serializable> layout, final boolean ignoreExceptions, String server, String group, String topic, String tag) {
        super(name, filter, layout, ignoreExceptions);
        initRocketMq(server, group, topic, tag);
    }

    private void initRocketMq(String server, String group, String topic, String tag) {
        if(this.producer==null){
            this.rocketMqNameserver = server;
            this.rocketMqProducerGroup = group;
            this.rocketMqMsgTopic = topic;
            this.rocketMqMsgTag = tag;
            this.producer = new DefaultMQProducer(this.rocketMqProducerGroup);
            producer.setNamesrvAddr(this.rocketMqNameserver);
            try {
                producer.shutdown();
                producer.start();
            } catch (Exception e) {
                System.out.println(e);
            }
        }
    }

    @Override
    public void append(LogEvent logEvent) {
        readLock.lock();
        try {
            final byte[] bytes = getLayout().toByteArray(logEvent);//日志二进制文件,输出到指定位置就行
            //下面这个是要实现的自定义逻辑
            //String strLog = new String(bytes);
            //System.out.println(strLog);
            if (producer != null) {
                Message msg = new Message(this.rocketMqMsgTopic, this.rocketMqMsgTag, bytes);
                producer.sendOneway(msg);
                msg = null;
            }
        } catch (Exception ex) {
            if (!ignoreExceptions()) {
                throw new AppenderLoggingException(ex);
            }
        } finally {
            readLock.unlock();
        }
    }

    // 下面这个方法可以接收配置文件中的参数信息
    @PluginFactory
    public static RocketMqAppender createAppender(@PluginAttribute("name") String name,
                                                  @PluginAttribute("server") String server,
                                                  @PluginAttribute("group") String group,
                                                  @PluginAttribute("topic") String topic,
                                                  @PluginAttribute("tag") String tag,
                                                  @PluginElement("Filter") final Filter filter,
                                                  @PluginElement("Layout") Layout<? extends Serializable> layout,
                                                  @PluginAttribute("ignoreExceptions") boolean ignoreExceptions) {
        if (name == null || server == null || group == null || topic == null) {
            LOGGER.error("PluginAttribute error");
            return null;
        }
        if (layout == null) {
            layout = PatternLayout.createDefaultLayout();
        }
        return new RocketMqAppender(name, filter, layout, ignoreExceptions, server, group, topic, tag);
    }
}

  log4j2.xml 配置文件

<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--
	自定义命名格式:
	%d:发生时间,%d{yyyy-MM-dd HH:mm:ss,SSS},输出类似:2020-02-20 22:10:28,921
	%F:输出所在的类文件名
	%t:线程名称
	%p:日志级别
	%c:日志消息所在类名
	%m:消息内容
	%M:输出所在函数名
	%x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
	%l:执行的函数名(类名称:行号)com.core.LogHelper.aroundService(LogHelper.java:32)
	%n:换行
	%i:从1开始自增数字
	%-5level:输出日志级别,-5表示左对齐并且固定输出5个字符,如果不足在右边补0
	“${sys:user.home}”是HOME目录 如:C:\Users\heave, 此处指定任意目录如:D:\logs
-->
<!--设置log4j2自身log级别为warn,每间隔30秒数自动检测配置是否发生修改,并重新配置-->
<configuration status="warn" monitorInterval="30">
    <Properties>
        <!-- 日志显示模板,显示内容的格式如下 -->
        <!-- [21:55:33:047] [INFO] - org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:173) - Initializing Spring embedded WebApplicationContext -->
        <Property name="log_pattern" value="[%d{yyyy-MM-dd HH:mm:ss:SSS}] [%p][%t] - %l - %m%n"/>
        <!-- 保存日志文件目录 -->
        <!--<Property name="file_path" value="${sys:user.home}/logs"/>-->
        <Property name="file_path" value="/tmp/spring-boot-web"/>
        <!-- 日志文件的最大容量,超过该值就进行备份 -->
        <Property name="file_max_size" value="30MB"/>
        <!-- 备份的文件夹名称 如下为:2020-02 -->
        <Property name="backup_folder" value="$${date:yyyy-MM}"/>
        <!-- 备份文件的后缀,日志文件超过file_max_size会备份到filePattern指定的目录下 -->
        <Property name="backup_file_suffix" value="-%d{yyyy-MM-dd}-%i.log"/>
    </Properties>
    <!--定义appender-->
    <appenders>
        <!--控制台的输出配置-->
        <console name="Console" target="SYSTEM_OUT">
            <!-- 设置控制台只输出INFO及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
            <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
            <!--输出日志的格式-->
            <PatternLayout pattern="${log_pattern}"/>
        </console>

        <!-- 所有的日志信息会打印到此文件中,append=false每次启动程序会自动清空 -->
        <!-- <File name="all" fileName="${file_path}/all.log" append="true">
            <PatternLayout pattern="${log_pattern}"/>
        </File>-->

        <!--
        该RollingFile存储INFO级别的日志,
        默认存储到 fileName 文件中
        超过SizeBasedTriggeringPolicy的设定值,则存储到 filePattern 文件中
        -->
        <RollingFile name="RollingFileInfo" fileName="${file_path}/info.log"
                     filePattern="${file_path}/${backup_folder}/info${backup_file_suffix}">
            <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
            <!-- 写入日志文件的模板 -->
            <PatternLayout pattern="${log_pattern}"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="${file_max_size}"/>
            </Policies>
            <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,超过该数量,会滚动删除前面的记录 -->
            <DefaultRolloverStrategy max="20"/>
        </RollingFile>
        <RollingFile name="RollingFileWarn" fileName="${file_path}/warn.log"
                     filePattern="${file_path}/${backup_folder}/warn${backup_file_suffix}">
            <ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="${log_pattern}"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="${file_max_size}"/>
            </Policies>
        </RollingFile>
        <RollingFile name="RollingFileError" fileName="${file_path}/error.log"
                     filePattern="${file_path}/${backup_folder}/error${backup_file_suffix}">
            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="${log_pattern}"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="${file_max_size}"/>
            </Policies>
        </RollingFile>

        <!-- 这个就是自定义的Appender -->
        <RocketMqAppender
                name="RocketMqInfo"
                server="192.168.88.50:9876"
                group="SpringBootWeb-ProducerGroup"
                topic="Log4j2ToRocketMq"
                tag="spring-boot-web">
            <PatternLayout pattern="${log_pattern}" />
        </RocketMqAppender>
    </appenders>
    <!-- 只有定义了logger并使用appender-ref,appender才会生效 -->
    <loggers>
        <!--过滤掉spring和hibernate的一些无用的debug信息-->
        <logger name="org.springframework" level="INFO"/>
        <logger name="org.mybatis" level="INFO">
            <!-- 添加如下设置,控制台会再打印一次 -->
            <AppenderRef ref="Console"/>
        </logger>
        <root level="INFO">
            <appender-ref ref="Console"/>
            <appender-ref ref="RollingFileInfo"/>
            <appender-ref ref="RollingFileWarn"/>
            <appender-ref ref="RollingFileError"/>
            <appender-ref ref="RocketMqInfo"/>
        </root>
    </loggers>
</configuration>

  

 

三.消费MQ队列消息

 

package com.company.project.mq;

import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Service;

@Service
@RocketMQMessageListener(consumerGroup = "SpringBootWeb-ConsumerGroup", topic = "Log4j2ToRocketMq")
public class RocketConsumer implements RocketMQListener<String> {

    @Override
    public void onMessage(String message) {
        //System.err.println("接收到消息:" + message);
        //System.err.println("接收到消息一条" );
    }
}

  

 

参考:

https://www.cnblogs.com/moxiaodan/p/13800016.html

 

posted @ 2021-08-30 16:07  疯癫大圣  阅读(1290)  评论(0编辑  收藏  举报