开发环境
名称 | 版本 |
---|---|
操作系统 | Windows 10 X64 |
JDK | 1.8(jdk-8u151-windows-x64) |
IntelliJ IDEA | ULTIMATE 2018.3 |
Maven | 3.6.0 |
VMware® Workstation 12 Pro | 12.0.0 build-2985596 |
CentOS7 | CentOS Linux release 7.8.2003 (Core) |
Linux | 3.10.0-1127.el7.x86_64 |
对应项目部署在虚拟机 Linux 下,IP 是 192.168.114.128
参考
相关内容
项目结构
Eureka 项目代码
1.enta-parent.pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- <parent>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-dependencies</artifactId>-->
<!-- <version>2.1.9.RELEASE</version>-->
<!-- </parent>-->
<groupId>com.demo.enta</groupId>
<artifactId>enta-parent</artifactId>
<version>1.0.3.RELEASE</version>
<name>enta-parent</name>
<packaging>pom</packaging>
<description>
enta基本库,负责引入公共开源lib库版本定义、maven发布配置、环境配置等职责
-----这个版本主要解决以下问题------
漏洞描述:
VMware Tanzu发布安全公告,在Spring Framework版本5.2.0-5.2.8、5.1.0-5.1.17、5.0.0-5.0.18、4.3.0-4.3.28和较旧的不受支持的版本中,公布了一个存在于Spring Framework中的反射型文件下载(Reflected File Download,RFD)漏洞CVE-2020-5421。
CVE-2020-5421 可通过jsessionid路径参数,绕过防御RFD攻击的保护。攻击者通过向用户发送带有批处理脚本扩展名的URL,使用户下载并执行文件,从而危害用户系统。VMware Tanzu官方已发布修复漏洞的新版本。
Spring Framework是 Java 平台的一个开源全栈应用程序框架和控制反转容器实现,一般被直接称为 Spring。
漏洞等级:高危
受影响的版本:
Spring Framework
5.2.0 - 5.2.8
5.1.0 - 5.1.17
5.0.0 - 5.0.18
4.3.0 - 4.3.28
及更早期的版本
安全版本:
Spring Framework
5.2.9
5.1.18
5.0.19
4.3.29
下载链接:
https://github.com/spring-projects/spring-framework/releases
fastJson : 1.2.67 -> 1.2.69 版本
xstream: 1.4.10 -> 1.4.11 版本
</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.repofastjsonrting.outputEncoding>UTF-8</project.repofastjsonrting.outputEncoding>
<java.version>1.8</java.version>
<resource.delimiter>@</resource.delimiter>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven.compiler.compilerVersion>${java.version}</maven.compiler.compilerVersion>
<spring.boot.version>2.1.9.RELEASE</spring.boot.version>
<spring.cloud.version>Greenwich.RELEASE</spring.cloud.version>
<mybatis-plus-spring-boot-starter.version>3.1.0</mybatis-plus-spring-boot-starter.version>
<mybatisplus.version>3.1.0</mybatisplus.version>
<fastjson.version>1.2.69</fastjson.version>
<swagger.version>2.7.0</swagger.version>
<swagger-ui.version>2.7.0</swagger-ui.version>
<swagger-bootstrap-ui.version>1.9.2</swagger-bootstrap-ui.version>
<commons-codec.version>1.10</commons-codec.version>
<commons-lang3.version>3.6</commons-lang3.version>
<commons-io.version>2.5</commons-io.version>
<commons-text.version>1.7</commons-text.version>
<commons-httpclient.version>3.1</commons-httpclient.version>
<HikariCP.version>3.3.1</HikariCP.version>
<velocity.version>1.7</velocity.version>
<jjwt.version>0.8.0</jjwt.version>
<jjwt.version2>3.4.1</jjwt.version2>
<hutool.version>4.5.1</hutool.version>
<lombok.version>1.18.8</lombok.version>
<gson.version>2.8.5</gson.version>
<guava.version>23.0</guava.version>
<security-oauth2.version>2.3.6.RELEASE</security-oauth2.version>
<p6spy.version>3.8.5</p6spy.version>
<druid.version>1.1.20</druid.version>
<druid.starter.version>1.1.20</druid.starter.version>
<feign-okhttp.version>10.5.1</feign-okhttp.version>
<spring.boot.admin.server.version>2.1.6</spring.boot.admin.server.version>
<dec.version>0.1.2</dec.version>
<spring.version>5.1.18.RELEASE</spring.version>
<spring-framework.version>${spring.version}</spring-framework.version>
<xstream.version>1.4.11</xstream.version>
</properties>
<!--Spring Cloud 版本序列配置-->
<dependencyManagement>
<dependencies>
<!-- Override springframework release train provided by Spring Boot -->
<!--https://www.cnblogs.com/zhangjianbin/p/10076427.html-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-framework.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>${spring-framework.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>${xstream.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
<exclusions>
<exclusion>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 用于日志切面中,以 json 格式打印出入参(本来使用阿里的 FASTJSON, 但是对于文件上传的接口,打印参数会报错,换为 Gson) -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
</dependency>
<!--lombok start-->
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<!--lombok end-->
<!--fastJson start-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!--fastJson end-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.starter.version}</version>
</dependency>
<!--swagger start-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger-ui.version}</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>${swagger-bootstrap-ui.version}</version>
</dependency>
<!--swagger end-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<!--jwt start-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jjwt.version}</version>
</dependency>
<!--jwt end-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>${jjwt.version2}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>${commons-text.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>${security-oauth2.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus-spring-boot-starter.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>${mybatisplus.version}</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
<version>${feign-okhttp.version}</version>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>${spring.boot.admin.server.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.brotli/dec -->
<dependency>
<groupId>org.brotli</groupId>
<artifactId>dec</artifactId>
<version>${dec.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<!--注意:这里必须要添加,否则各种依赖有问题-->
<!--<repositories>-->
<!--<repository>-->
<!--<id>spring-milestones</id>-->
<!--<name>Spring Milestones</name>-->
<!--<url>https://repo.spring.io/libs-milestone</url>-->
<!--<snapshots>-->
<!--<enabled>false</enabled>-->
<!--</snapshots>-->
<!--</repository>-->
<!--</repositories>-->
<distributionManagement>
<!--<repository>-->
<!--<id>internal.releases</id>-->
<!--<name>internal repository for releases</name>-->
<!--<url>http://maven.oa.com/nexus/content/repositories/thirdparty/</url>-->
<!--</repository>-->
<!--<snapshotRepository>-->
<!--<id>internal.snapshots</id>-->
<!--<name>internal repository for snapshots</name>-->
<!--<url>http://maven.oa.com/nexus/content/repositories/thirdparty-snapshots/</url>-->
<!--</snapshotRepository>-->
</distributionManagement>
</project>
2.pom.xml【demo-framework】
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>enta-parent</artifactId>
<groupId>com.demo.enta</groupId>
<version>1.0.3.RELEASE</version>
<relativePath>enta-parent.pom.xml</relativePath>
</parent>
<name>demo-framework</name>
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo.framework</groupId>
<artifactId>demo.framework</artifactId>
<version>1.0-SNAPSHOT</version>
<!--在父级项目中的 pom.xml 文件使用的 packaging 配置一定为 pom。-->
<!--父级的 pom 文件只作项目的子模块的整合-->
<!--在 maven install 时不会生成 jar/war 压缩包-->
<packaging>pom</packaging>
<modules>
<module>demo-eureka</module>
</modules>
<!--基础配置-->
<properties>
<java.version>1.8</java.version>
<!--项目统一字符集编码-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<!--Spring Boot 执行器组件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--Spring Cloud 基础-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<!--Spring Cloud 服务注册组件-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<!--此处的依赖是SpringBoot2.0以后专用的,如果您使用的SpringBoot版本低于2.0请使用spring-cloud-starter-eureka-server-->
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!--Spring Boot Web组件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 参数校验信息 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>2.1.9.RELEASE</version>
</dependency>
<!-- spring aop start -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- spring aop end -->
<!--Spring Boot 测试组件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20200518</version>
</dependency>
</dependencies>
</project>
3.pom.xml【demo-eureka】
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>demo.framework</artifactId>
<groupId>com.demo.framework</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<name>demo-eureka</name>
<modelVersion>4.0.0</modelVersion>
<artifactId>demo-eureka</artifactId>
<!--使用 jar 方式打包-->
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- 引入此jar会有版本冲突问题
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-eureka-server</artifactId>
<version>2.1.0.RC2</version>
</dependency>-->
<!--虽然 enta-parent.pom.xml 引用了这个组件,但是这里不引用,程序还是会报错"程序包 lombok.extern.slf4j不存在"-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<!--如果要访问info接口想获取maven中的属性内容请记得添加如下内容-->
<goal>build-info</goal>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<!-- 构建不包含lib的jar包-->
<configuration>
<layout>ZIP</layout>
<includes>
<include>
<groupId>non-exists</groupId>
<artifactId>non-exists</artifactId>
</include>
</includes>
</configuration>
</plugin>
<plugin>
<!-- 指定maven编译的jdk版本,如果不指定,maven3默认用jdk 1.5 maven2默认用jdk1.3 -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<!-- 一般而言,target与source是保持一致的,但是,有时候为了让程序能在其他版本的jdk中运行(对于低版本目标jdk,源代码中不能使用低版本jdk中不支持的语法),会存在target不同于source的情况 -->
<source>1.8</source> <!-- 源代码使用的JDK版本 -->
<target>1.8</target> <!-- 需要生成的目标class文件的编译版本 -->
<encoding>UTF-8</encoding><!-- 字符集编码 -->
</configuration>
</plugin>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.5.0.1254</version>
</plugin>
<!-- 打包跳过TEST -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<!--true跳过测试 -->
<skipTests>true</skipTests>
</configuration>
</plugin>
<!-- 打jar包不包含yml文件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<!-- 排除配置文件 -->
<excludes>
<exclude>*.yml</exclude>
<exclude>*.xml</exclude>
</excludes>
</configuration>
</plugin>
<!-- 配置文件打包到conf目录下 -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-sources</id>
<phase>process-sources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/conf</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>*.yml</include>
<include>*.xml</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<!-- 依赖包到lib目录下 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<useBaseVersion>true</useBaseVersion>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
4.application.yml
spring:
application:
name: demo-eureka
server:
port: 8771
# 配置Eureka Server 信息
eureka:
client:
# 不进行注册(当服务注册中心是单点而非高可用时的配置方式)
registerWithEureka: false
# 不获取注册信息(当服务注册中心是单点而非高可用时的配置方式)
fetchRegistry: false
service-url:
defaultZone: http://localhost:${server.port}/eureka/
# 自定义实例编号
instance:
# 优先使用IP地址方式进行注册服务
prefer-ip-address: true
# 配置使用指定IP
ip-address: 127.0.0.1
instance-id: ${eureka.instance.ip-address}:${server.port}
# 配置使用主机名注册服务
#hostname: peer1
logging:
config: classpath:logback-dev.xml
#path: /data/DATA_DIR/logs/demo/demo-eureka
5.bootstrap.properties
#由于 logback-spring.xml 的加载在 application.properties之前,所以之前的配置 logback-spring.xml无法获取到 spring.application.name属性,因此这里将该属性移动到最先加载的 bootstrap.properties配置文件中。
#https://cloud.tencent.com/developer/article/1067431
spring.application.name=eureka-ha
6.logback-dev.xml
<!-- Logback configuration. See http://logback.qos.ch/manual/index.html -->
<configuration scan="true" scanPeriod="10 seconds">
<!--继承spring boot提供的logback配置-->
<!--<include resource="org/springframework/boot/logging/logback/base.xml" />-->
<!--设置系统日志目录-->
<property name="APP_DIR" value="demo-eureka" />
<!-- 彩色日志 -->
<!-- 彩色日志依赖的渲染类 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!-- 控制台输出 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>info</level>
</filter>
</appender>
<!-- 时间滚动输出 level为 DEBUG 日志 -->
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_debug.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--
归档的日志文件的路径,例如今天是2017-04-26日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
而2017-04-26的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引
-->
<fileNamePattern>${LOG_PATH}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--
除按日志记录之外,还配置了日志文件不能超过500M,若超过500M,日志文件会以索引0开始,
命名日志文件,例如log-error-2017-04-26.0.log
-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>500MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>30</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录debug级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>debug</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 INFO 日志 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_info.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--
归档的日志文件的路径,例如今天是2017-04-26日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
而2017-04-26的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引
-->
<fileNamePattern>${LOG_PATH}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--
除按日志记录之外,还配置了日志文件不能超过500M,若超过500M,日志文件会以索引0开始,
命名日志文件,例如log-error-2017-04-26.0.log
-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>500MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>30</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 WARN 日志 -->
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_warn.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--
归档的日志文件的路径,例如今天是2017-04-26日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
而2017-04-26的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引
-->
<fileNamePattern>${LOG_PATH}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--
除按日志记录之外,还配置了日志文件不能超过500M,若超过500M,日志文件会以索引0开始,
命名日志文件,例如log-error-2017-04-26.0.log
-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>500MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>30</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录warn级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 ERROR 日志 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_error.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--
归档的日志文件的路径,例如今天是2017-04-26日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
而2017-04-26的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引
-->
<fileNamePattern>${LOG_PATH}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--
除按日志记录之外,还配置了日志文件不能超过500M,若超过500M,日志文件会以索引0开始,
命名日志文件,例如log-error-2017-04-26.0.log
-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>500MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>30</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录ERROR级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>error</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<logger name="org.springframework.web" level="info"/>
<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>
<!--name的属性值一定要是当前工程的java代码的完整目录,因为mybatis打印的日志级别是debug级别的,因此需要配置debug级别日志扫描的目录-->
<logger name="com.demo.eureka" level="debug"/>
<!--开发环境:打印控制台-->
<!--<springProfile name="dev">-->
<root level="info">
<appender-ref ref="CONSOLE" />
<appender-ref ref="DEBUG_FILE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="WARN_FILE" />
<appender-ref ref="ERROR_FILE" />
</root>
<!--</springProfile>-->
<!--测试环境:打印控制台和输出到文件-->
<springProfile name="test">
<root level="info">
<appender-ref ref="CONSOLE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="WARN_FILE" />
<appender-ref ref="ERROR_FILE" />
</root>
</springProfile>
<!--生产环境:输出到文件-->
<springProfile name="prod">
<root level="info">
<appender-ref ref="DEBUG_FILE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="ERROR_FILE" />
</root>
</springProfile>
</configuration>
7.EureKaHaApplication
package com.demo.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
//排除掉数据库配置项目
@SpringBootApplication( exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
RedisAutoConfiguration.class,
RedisRepositoriesAutoConfiguration.class,
RabbitAutoConfiguration.class
})
@EnableEurekaServer
public class EureKaHaApplication {
public static void main(String[] args) {
SpringApplication.run(EureKaHaApplication.class, args);
}
}
8.EurekaStateChangeListener
package com.demo.eureka;
import com.netflix.appinfo.InstanceInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.netflix.eureka.server.event.*;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class EurekaStateChangeListener {
@EventListener
public void listen(EurekaInstanceCanceledEvent event) {
log.info(event.getServerId() + "\t" + event.getAppName() + " 服务下线");
}
@EventListener
public void listen(EurekaInstanceRegisteredEvent event) {
InstanceInfo instanceInfo = event.getInstanceInfo();
log.info(instanceInfo.getAppName() + "进行注册");
}
@EventListener
public void listen(EurekaInstanceRenewedEvent event) {
log.info(event.getServerId() + "\t" + event.getAppName() + " 服务进行续约");
}
@EventListener
public void listen(EurekaRegistryAvailableEvent event) {
log.info("注册中心 启动");
}
@EventListener
public void listen(EurekaServerStartedEvent event) {
log.info("Eureka Server 启动");
}
}
9.本地先运行项目并测试通过
运行 EureKaHaApplication main() ,访问 http://127.0.0.1:8771/
Eureka 项目打包
1.父项目 clear
Maven
-demo-framework
-Lifecyle
-clean
查看控制台,最后出现成功的提示即可
[INFO] demo-framework ..................................... SUCCESS [ 0.453 s]
[INFO] demo-eureka ........................................ SUCCESS [ 0.361 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.856 s
[INFO] Finished at: 2021-03-14T09:18:01+08:00
[INFO] ------------------------------------------------------------------------
进程已结束,退出代码 0
2.父项目 install
Maven
-demo-framework
-Lifecyle
-install
查看控制台,最后出现成功的提示即可
[INFO] demo-framework ..................................... SUCCESS [ 0.870 s]
[INFO] demo-eureka ........................................ SUCCESS [ 21.390 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 23.711 s
[INFO] Finished at: 2021-03-14T22:24:23+08:00
[INFO] ------------------------------------------------------------------------
进程已结束,退出代码 0
3.eureka 项目 clear
Maven
-demo-eureka
-Lifecyle
-clean
查看控制台,最后出现成功的提示即可
[INFO] -------------------< com.demo.framework:demo-eureka >-------------------
[INFO] Building demo-eureka 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ demo-eureka ---
[INFO] Deleting D:\Java\demo-framework\demo-eureka\target
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.904 s
[INFO] Finished at: 2021-03-14T22:27:42+08:00
[INFO] ------------------------------------------------------------------------
进程已结束,退出代码 0
4.eureka 项目 package
Maven
-demo-eureka
-Lifecyle
-package
查看控制台,最后出现成功的提示即可
[INFO] --- maven-install-plugin:2.4:install (default-install) @ demo-eureka ---
[INFO] Installing D:\Java\demo-framework\demo-eureka\target\demo-eureka.jar to D:\Program Files\Maven\Repository\com\demo\framework\demo-eureka\1.0-SNAPSHOT\demo-eureka-1.0-SNAPSHOT.jar
[INFO] Installing D:\Java\demo-framework\demo-eureka\pom.xml to D:\Program Files\Maven\Repository\com\demo\framework\demo-eureka\1.0-SNAPSHOT\demo-eureka-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.308 s
[INFO] Finished at: 2021-03-14T22:29:10+08:00
[INFO] ------------------------------------------------------------------------
进程已结束,退出代码 0
查看发布包
D:\Java\demo-framework\demo-eureka\target
Eureka 部署到 Linux 服务器
1.创建项目目录和拷贝文件
创建项目目录
mkdir -p /data/USERS/luoma/applications/demo-eureka
其它的文件也是类似的方法,对应文件目录结构如下,需要拷贝打包好的发布包相关内容到对应文件夹
├── conf
│ ├── application.yml
│ └── logback-dev.xml
├── demo-eureka.jar
├── deploy.sh
├── lib
│ ├── 相关 jar 文件
2.application.yml
测试环境 yml 文件和环境有一些细小的差异
server:
port: 8771
# 配置Eureka Server 信息
eureka:
client:
# 不进行注册(当服务注册中心是单点而非高可用时的配置方式)
registerWithEureka: false
# 不获取注册信息(当服务注册中心是单点而非高可用时的配置方式)
fetchRegistry: false
service-url:
defaultZone: http://localhost:${server.port}/eureka/
# 自定义实例编号
instance:
# 优先使用IP地址方式进行注册服务
prefer-ip-address: true
# 配置使用指定IP
ip-address: 127.0.0.1
instance-id: ${eureka.instance.ip-address}:${server.port}
# 配置使用主机名注册服务
#hostname: peer1
logging:
config: conf/logback-dev.xml
path: /data/USERS/luoma/applications/demo-eureka/logs
management:
#暴露所有端点
endpoints:
web:
exposure:
include: "*"
#详细信息显示给所有用户
endpoint:
health:
show-details: ALWAYS
server:
port: 5001
3.服务启动文件 deploy.sh
#!/bin/sh
# 服务名称
SERVER_NAME=demo-eureka.jar
# 全局变量,程序的在系统中的 id
server_pid=0
# 判断程序是否已经启动,若已启动,则初始化全局 server_pid,方便下面停止程序时使用
check_pid(){
javaps=`ps -ef | grep $SERVER_NAME |grep -v grep `
if [ -n "$javaps" ]; then
server_pid=`echo $javaps | awk '{print $2}'`
else
server_pid=0
fi
}
###################################
# 启动程序
# 说明:
# 1.首先判断程序是否已经启动
# 2.已启动,则提示用户;未启动,则执行命令启动程序
# 3.最后输出启动启动程序的结果
###################################
start(){
check_pid
if [ $server_pid -ne 0 ]; then
echo "================================"
echo "warn:$SERVER_NAME already started! (pid=$server_pid)"
echo "================================"
else
echo -n "Starting $SERVER_NAME..."
java -Xms2048m -Xmx2048m -Dserver.port=8771 -Dloader.path=./lib/ -jar $SERVER_NAME --spring.config.location=/data/USERS/luoma/applications/demo-eureka/conf/application.yml >/dev/null 2>&1 &
check_pid
if [ $server_pid -ne 0 ]; then
echo "(pid=$server_pid) [OK]"
else
echo "[Failed]"
fi
fi
}
###################################
#停止程序
# 说明:
# 1. 首先调用 checkpid 函数,刷新 $server_pid 全局变量
# 2. 如果程序已经启动($server_pid 不等于0),则开始执行停止,否则,提示程序未运行
# 3. 使用 kill 命令进行强制杀死进程
# 4. 执行 kill 命令行紧接其后,马上查看上一句命令的返回值: $?
# 5. 如果步骤 4 的结果 $? 等于 0,则打印 [OK],否则打印 [Failed]
# 6. 为了防止 java 程序被启动多次,这里增加反复检查进程,反复杀死的处理(递归调用 stop)。
# 注意: echo -n 表示打印字符后,不换行
# 注意: 在 shell 编程中,"$?" 表示上一句命令或者一个函数的返回值
###################################
stop(){
check_pid
if [ $server_pid -ne 0 ]; then
echo -n "Stopping $SERVER_NAME...(pid=$server_pid) "
kill $server_pid
sleep 2
if [ $? -eq 0 ];then
echo "[OK]"
else
echo "[Failed]"
fi
check_pid
if [ $server_pid -ne 0 ]; then
stop
fi
else
echo "================================"
echo "warn:$SERVER_NAME is not running"
echo "================================"
fi
}
###################################
# 检查程序运行状态
# 说明:
# 1. 首先调用 checkpid 函数,刷新 $server_pid 全局变量
# 2. 如果程序已经启动($server_pid 不等于 0),则提示正在运行并表示出 server_pid
# 3. 否则,提示程序未运行
###################################
status(){
check_pid
if [ $server_pid -ne 0 ]; then
echo "$SERVER_NAME is running! (pid=$server_pid)"
else
echo "$SERVER_NAME is not running"
fi
}
###################################
#读取脚本的第一个参数($1),进行判断
#参数取值范围:{start|debug|stop|restart|status|info|log}
#如参数不在指定范围之内,则打印帮助信息
###################################
case "$1" in
'start')
start
;;
'stop')
stop
;;
'restart')
stop
start
;;
'status')
status
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
esac
exit 0
其它文件和开发环境一致
4.启动 Eureka 项目
进入目录 cd /data/USERS/luoma/applications/demo-eureka
启动项目 ./deploy.sh start
[root@luoma demo-eureka]# ./deploy.sh start
Starting demo-eureka.jar...(pid=3347) [OK]
相关问题总结
1.deploy.sh: 权限不够
进入目录 cd /data/USERS/luoma/applications/demo-eureka
,启动项目,报错
[root@luoma demo-eureka]# ./deploy.sh start
-bash: ./deploy.sh: 权限不够
解决办法
chmod 命令对 shell 脚本赋予权限
chmod 777 ./deploy.sh
2.坏的解释器: 没有那个文件或目录
[root@luoma demo-eureka]# ./deploy.sh start
-bash: ./deploy.sh: /bin/sh^M: 坏的解释器: 没有那个文件或目录
原因是 deploy.sh
文件在 Windows 下编辑过,Linux 下的换行符和 Windows 的不一样,所以需要转换一下
sed -i 's/\r$//' deploy.sh
3.拒绝连接
启动后访问 http://127.0.0.1:8771
报错
[root@luoma demo-eureka]# curl 127.0.0.1:8771
curl: (7) Failed connect to 127.0.0.1:8771; 拒绝连接
解决办法,检查相关 yml 配置文件 application.yml 和启动文件 deploy.sh 中相关配置是否正确
5.运行测试
在 Windows 下打开浏览器,访问 Linux 服务器对应项目地址 http://192.168.114.128:8771/
部署成功。