微服务使用logback+打成tar包方式

hello,all

为推行微服务统一部署管理,需要将所有微服务项目打成tar包的形式。

同时,承祝强力推荐logback,因此也同时去掉了log4j,集成logback(性能好呀)。

下面简要介绍一下要点,注意摆正姿势:

参考项目:revolver,分支:assembly_new

1.打tar包

  • 在pom.xml里引入maven-assembly-plugin插件
<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>3.0.0</version>
    <configuration>
        <descriptors>
            <descriptor>src/main/assembly.xml</descriptor>
        </descriptors>
    </configuration>
    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>
  • 在src/main目录里添加assembly.xml(assembly的配置文件),内容如下:
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
   <id>assembly</id>
   <formats>
      <format>tar.gz</format>
   </formats>
   <includeBaseDirectory>true</includeBaseDirectory>

   <fileSets>
      <fileSet>
         <directory>bin</directory>
         <outputDirectory>bin</outputDirectory>
         <fileMode>0755</fileMode>
         <filtered>false</filtered>
      </fileSet>
      <fileSet>
         <directory>src/main/resources</directory>
         <outputDirectory>conf</outputDirectory>
         <fileMode>0644</fileMode>
         <filtered>false</filtered>
      </fileSet>
      <fileSet>
         <directory>${resource.path}</directory>
         <outputDirectory>conf</outputDirectory>
         <fileMode>0644</fileMode>
         <filtered>false</filtered>
      </fileSet>
   </fileSets>
   <dependencySets>
      <dependencySet>
         <outputDirectory>lib</outputDirectory>
      </dependencySet>
   </dependencySets>
</assembly>
  • 在项目的根目录(与src平级)添加bin目录,里面放四个脚本:dump.shserver.shstart.shstop.sh。脚本太多,这里就不粘贴出来了,可以到参考项目里取。拷贝脚本到自己项目之后需要修改start.sh里的
START_CLASS=启动类全限定名

启动类如下:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.text.SimpleDateFormat;
import java.util.Date;

public class Main {
    private static Logger logger = LoggerFactory.getLogger(Main.class);

    private static final String CONFIG_FILE_SPRING = "spring.xml";
    private static volatile boolean running = true;
    private static ClassPathXmlApplicationContext context = null;

    public static void main(String[] args) {
        try {
            long before = System.currentTimeMillis();
            start();
            long time=System.currentTimeMillis()-before;
            String logLine = new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss]").format(new Date()) + " dubbox server started! it takes "+time+" ms.";
            System.out.println(logLine);
            logger.info(logLine);
        } catch (RuntimeException e) {
            e.printStackTrace();
            logger.error(e.getMessage(), e);
            System.exit(1);
        }

        if(!"false".equals(System.getProperty("dubbo.shutdown.hook"))) {
            Runtime.getRuntime().addShutdownHook(new Thread() {
                public void run() {
                    context.stop();
                    Class t = Main.class;
                    synchronized(Main.class) {
                        running = false;
                        Main.class.notify();
                    }
                }
            });
        }

        synchronized (Main.class) {
            while (true) {
                try {
                    Main.class.wait();
                } catch (Throwable e) {
                }
            }
        }
    }

    private static void start() {
        context = new ClassPathXmlApplicationContext(new String[] { CONFIG_FILE_SPRING });
        context.start();
    }
}

注:脚本取自中间件组新项目里的bin目录下的脚本,然后加以修改。并且摒弃了原来deploy目录里的脚本。注意不要混合使用

  • 打了tar包之后,在线下jenkins部署的脚本如下
#!/bin/bash
echo "kill PID!!"
BUILD_ID=DONTKILLME
cd $WORKSPACE/target
echo "kill PID!"
ps -ef|grep $JOB_NAME|awk {'print $2'}|xargs kill -9
sleep 2
tar -zxvf $JOB_NAME-assembly.tar.gz
cd $JOB_NAME/bin
sh ./start.sh
sleep 2

2.引入logback

  • 在pom文件里引入logback依赖,1.2.3为logback目前最新版本。
<logback.version>1.2.3</logback.version>

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>${logback.version}</version>
</dependency>
  • 引入log4j-over-slf4j,并且在dubbo依赖里排除log4j。原因是dubbo默认使用lo4fj打印日志,而使用logback之后还想dubbo打印日志,需要如此配置。(SLF4J ship with a module called log4j-over-slf4j. It allows log4j users to migrate existing applications to SLF4J without changing a single line of code but simply by replacing the log4j.jar file with log4j-over-slf4j.jar, as described below.)
<slf4j.version>1.7.25</slf4j.version>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>log4j-over-slf4j</artifactId>
    <version>${slf4j.version}</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>dubbo</artifactId>
    <version>2.8.3</version>
    <exclusions>
        <exclusion>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </exclusion>
    </exclusions>
</dependency>
  • 在resources_xxx里引入logback.xml,并且修改logDir的值为日志根目录,程序启动后会在日志根目录下创建四个文件夹debug、info、warn、error。不同级别的日志打到不同的文件夹里,并且按天滚动。
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 定义日志文件 输出位置 -->
    <property name="logDir" value="/data/var/log/application/Revolver" />

    <property name="maxHistory" value="30" />

    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} %p [USER_ID:%X{USER_ID}][%t][%L][%c.%M]%m%n</pattern>
        </encoder>
    </appender>

    <!-- ERROR级别日志 -->
    <appender name="errorFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${logDir}/error/error.log</file>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${logDir}/error/error.log.%d{yyyy-MM-dd}</fileNamePattern>
            <maxHistory>${maxHistory}</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} %p [USER_ID:%X{USER_ID}][%t][%L][%c.%M]%m%n</pattern>
        </encoder>
    </appender>

    <!-- WARN级别日志 appender -->
    <appender name="warnFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${logDir}/warn/warn.log</file>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${logDir}/warn/warn.log.%d{yyyy-MM-dd}</fileNamePattern>
            <maxHistory>${maxHistory}</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} %p [USER_ID:%X{USER_ID}][%t][%L][%c.%M]%m%n</pattern>
        </encoder>
    </appender>

    <!-- INFO级别日志 appender -->
    <appender name="infoFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${logDir}/info/info.log</file>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${logDir}/info/info.log.%d{yyyy-MM-dd}</fileNamePattern>
            <maxHistory>${maxHistory}</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} %p [USER_ID:%X{USER_ID}][%t][%L][%c.%M]%m%n</pattern>
        </encoder>
    </appender>

    <!-- DEBUG级别日志 appender -->
    <appender name="debugFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${logDir}/debug/debug.log</file>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${logDir}/debug/debug.log.%d{yyyy-MM-dd}</fileNamePattern>
            <maxHistory>${maxHistory}</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} %p [USER_ID:%X{USER_ID}][%t][%L][%c.%M]%m%n</pattern>
        </encoder>
    </appender>

    <root>
        <level value="info"/>
        <!-- 控制台输出 -->
        <appender-ref ref="console"/>
        <!-- 文件输出 -->
        <appender-ref ref="errorFile"/>
        <appender-ref ref="warnFile"/>
        <appender-ref ref="infoFile"/>
        <appender-ref ref="debugFile"/>
    </root>
</configuration>

以上

by the way:markdown写起来真的很舒服

《微服务使用logback+打成tar包方式》有4个想法

  1. 以上内容全部配好后如果还出现

    java.lang.NoClassDefFoundError: org/apache/log4j/Level的异常;

    注意删除`Zookeeper`下的`slf4j-log4j12`的依赖


    org.slf4j
    slf4j-log4j12

  2. 配置日志级别位置:logback.xml中root标签下 (日志级别为info);
    日志级别排序为:TRACE < DEBUG < INFO < WARN < ERROR;

    上线规范中要求不允许打印debug级别日志,所以resources_production目录下logback.xml,日志级别最低可配置为info。

  3. 配置日志级别位置:logback.xml中root标签下 level value=”info”(日志级别为info);
    日志级别排序为:TRACE < DEBUG < INFO < WARN < ERROR;

    上线规范中要求不允许打印debug级别日志,所以resources_production目录下logback.xml,日志级别最低可配置为info。

发表评论

电子邮件地址不会被公开。 必填项已用*标注