Browse Source

feat(消息): sse-base

huey 2 năm trước cách đây
mục cha
commit
4c15d0e813

+ 0 - 0
log/partal-service/error.2023-06-12.log


+ 22 - 0
log/partal-service/output.2023-06-12.log

@@ -0,0 +1,22 @@
+2023-06-12 20:31:16.960 [main] INFO  com.dragon.tj.portal.PortalServiceApplication - Starting PortalServiceApplication using Java 1.8.0_191 on 192.168.18.7 with PID 72207 (/Users/huey/dev/java/ideaWorkSpace/jl/portal-service/target/classes started by huey in /Users/huey/dev/java/ideaWorkSpace/jl/portal-service)
+2023-06-12 20:31:16.960 [background-preinit] INFO  org.hibernate.validator.internal.util.Version - HV000001: Hibernate Validator 6.2.5.Final
+2023-06-12 20:31:16.964 [main] INFO  com.dragon.tj.portal.PortalServiceApplication - The following 1 profile is active: "local"
+2023-06-12 20:31:18.879 [main] INFO  org.apache.coyote.http11.Http11NioProtocol - Initializing ProtocolHandler ["http-nio-8080"]
+2023-06-12 20:31:18.880 [main] INFO  org.apache.catalina.core.StandardService - Starting service [Tomcat]
+2023-06-12 20:31:18.881 [main] INFO  org.apache.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/9.0.75]
+2023-06-12 20:31:19.036 [main] INFO  org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext
+2023-06-12 20:31:20.278 [main] INFO  org.apache.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8080"]
+2023-06-12 20:31:20.311 [main] INFO  com.dragon.tj.portal.PortalServiceApplication - Started PortalServiceApplication in 4.218 seconds (JVM running for 5.421)
+2023-06-12 20:31:21.332 [http-nio-8080-exec-1] INFO  org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/] - Initializing Spring DispatcherServlet 'dispatcherServlet'
+2023-06-12 20:31:21.398 [http-nio-8080-exec-1] INFO  com.dragon.tj.portal.message.SseEmitterServer - 创建新的sse连接,当前用户:1122
+2023-06-12 20:32:34.328 [http-nio-8080-exec-2] INFO  com.dragon.tj.portal.message.SseEmitterServer - 创建新的sse连接,当前用户:1122
+2023-06-12 20:32:46.163 [http-nio-8080-exec-3] INFO  com.dragon.tj.portal.message.SseEmitterServer - SSE 发送信息成功!id = 1122 , message: 测试 SSE 发送消息!2 
+2023-06-12 20:32:46.177 [http-nio-8080-exec-3] INFO  com.dragon.tj.portal.message.SSEWebServer - 添加到队列,userId:1122 
+2023-06-12 20:33:10.976 [http-nio-8080-exec-4] INFO  com.dragon.tj.portal.message.SseEmitterServer - SSE 发送信息成功!id = 1122 , message: 测试 SSE 发送消息1 
+2023-06-12 20:33:10.976 [http-nio-8080-exec-4] INFO  com.dragon.tj.portal.message.SSEWebServer - 添加到队列,userId:1122 
+2023-06-12 20:33:21.379 [http-nio-8080-exec-5] INFO  com.dragon.tj.portal.message.SseEmitterServer - SSE 发送信息成功!id = 1122 , message: 测试 SSE 发送消息2 
+2023-06-12 20:33:21.380 [http-nio-8080-exec-5] INFO  com.dragon.tj.portal.message.SSEWebServer - 添加到队列,userId:1122 
+2023-06-12 20:33:25.920 [http-nio-8080-exec-6] INFO  com.dragon.tj.portal.message.SseEmitterServer - SSE 发送信息成功!id = 1122 , message: 测试 SSE 发送消息3 
+2023-06-12 20:33:25.920 [http-nio-8080-exec-6] INFO  com.dragon.tj.portal.message.SSEWebServer - 添加到队列,userId:1122 
+2023-06-12 20:58:06.578 [http-nio-8080-exec-9] INFO  com.dragon.tj.portal.message.SseEmitterServer - 创建新的sse连接,当前用户:1122
+2023-06-12 21:06:01.642 [http-nio-8080-exec-10] INFO  com.dragon.tj.portal.message.SseEmitterServer - 创建新的sse连接,当前用户:1122

+ 36 - 0
logs/project.artifactId_IS_UNDEFINED/debug.log

@@ -0,0 +1,36 @@
+2023-06-14 20:48:19,603 [main] ERROR [org.springframework.boot.SpringApplication] SpringApplication.java:821 - Application run failed
+java.lang.IllegalStateException: java.lang.IllegalStateException: Logback configuration error detected: 
+ERROR in ch.qos.logback.core.joran.action.AppenderAction - Could not create an Appender of type [com.sunacwy.frame.common.log.appender.LogbackConsoleAppender]. ch.qos.logback.core.util.DynamicClassLoadingException: Failed to instantiate type com.sunacwy.frame.common.log.appender.LogbackConsoleAppender
+ERROR in ch.qos.logback.core.joran.spi.Interpreter@22:96 - ActionException in Action for tag [appender] ch.qos.logback.core.joran.spi.ActionException: ch.qos.logback.core.util.DynamicClassLoadingException: Failed to instantiate type com.sunacwy.frame.common.log.appender.LogbackConsoleAppender
+ERROR in ch.qos.logback.core.joran.action.AppenderRefAction - Could not find an appender named [console]. Did you define it below instead of above in the configuration file?
+ERROR in ch.qos.logback.core.joran.action.AppenderRefAction - See http://logback.qos.ch/codes.html#appender_order for more details.
+	at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:344)
+	at org.springframework.boot.context.logging.LoggingApplicationListener.initialize(LoggingApplicationListener.java:298)
+	at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(LoggingApplicationListener.java:246)
+	at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:223)
+	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
+	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
+	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
+	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:131)
+	at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:85)
+	at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:66)
+	at java.util.ArrayList.forEach(ArrayList.java:1257)
+	at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:120)
+	at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:114)
+	at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:65)
+	at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:343)
+	at org.springframework.boot.SpringApplication.run(SpringApplication.java:301)
+	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303)
+	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292)
+	at com.dragon.tj.portal.PortalServiceApplication.main(PortalServiceApplication.java:10)
+Caused by: java.lang.IllegalStateException: Logback configuration error detected: 
+ERROR in ch.qos.logback.core.joran.action.AppenderAction - Could not create an Appender of type [com.sunacwy.frame.common.log.appender.LogbackConsoleAppender]. ch.qos.logback.core.util.DynamicClassLoadingException: Failed to instantiate type com.sunacwy.frame.common.log.appender.LogbackConsoleAppender
+ERROR in ch.qos.logback.core.joran.spi.Interpreter@22:96 - ActionException in Action for tag [appender] ch.qos.logback.core.joran.spi.ActionException: ch.qos.logback.core.util.DynamicClassLoadingException: Failed to instantiate type com.sunacwy.frame.common.log.appender.LogbackConsoleAppender
+ERROR in ch.qos.logback.core.joran.action.AppenderRefAction - Could not find an appender named [console]. Did you define it below instead of above in the configuration file?
+ERROR in ch.qos.logback.core.joran.action.AppenderRefAction - See http://logback.qos.ch/codes.html#appender_order for more details.
+	at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:179)
+	at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithConventions(AbstractLoggingSystem.java:80)
+	at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:60)
+	at org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LogbackLoggingSystem.java:132)
+	at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:329)
+	... 18 common frames omitted

+ 0 - 0
logs/project.artifactId_IS_UNDEFINED/error.log


+ 9 - 0
pom.xml

@@ -94,6 +94,15 @@
             <artifactId>hutool-all</artifactId>
             <version>5.5.8</version>
         </dependency>
+        <dependency>
+            <groupId>org.springframework.kafka</groupId>
+            <artifactId>spring-kafka</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.78</version>
+        </dependency>
 
     </dependencies>
 

+ 62 - 0
src/main/java/com/dragon/tj/portal/message/kafka/Consumer.java

@@ -0,0 +1,62 @@
+package com.dragon.tj.portal.message.kafka;
+
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.kafka.annotation.KafkaListener;
+import org.springframework.kafka.support.Acknowledgment;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.util.Map;
+
+@Component
+@Slf4j
+public class Consumer {
+
+    @Autowired
+    private Map<String, OpenApiSseEmitter> sseEmitters;
+
+    /**
+     * get client published message from kafka,process it according to the serverId
+     *
+     * @param msg
+     * @param ack
+     */
+//    @KafkaListener(topics = {"sseTopic"}, clientIdPrefix = "${spring.application.name}", id = "openapi-be-sse-connection-", idIsGroup = false, groupId = "openapi-be-sse-connection-" + "#{T(java.util.UUID).randomUUID()}")
+    @KafkaListener(topics = {"sseTopic"})
+    public void sseConnectionProcess(String msg, Acknowledgment ack) {
+//        log.info("get kafka msg from topic:{}, msg:{}", customProperty.getKafka().getTopics().getSseConnection().getTopic(), msg);
+        log.info("get kafka msg from topic:{}, msg:{}", KafkaInitialConfiguration.sseTopic, msg);
+        if (StrUtil.isEmpty(msg)) {
+            log.error("kafka msg is empty, no process");
+            return;
+        }
+        SsePublishReqDto reqDto;
+        try {
+            reqDto = JSONObject.parseObject(msg, SsePublishReqDto.class);
+        } catch (Exception e) {
+            log.error("parsing string to obj failed, msg={}, e={}", msg, e);
+            return;
+        }
+
+        OpenApiSseEmitter emitter = sseEmitters.get(reqDto.getClientId());
+        if (emitter == null) {
+            log.error("can't find the sseEmitter obj from sseEmitters, no process");
+            return;
+        }
+
+        try {
+            // 发送消息给客户端
+            log.info("send sse msg={} to clientId={}", reqDto.getMessage(), reqDto.getClientId());
+            emitter.send(reqDto.getMessage(), MediaType.APPLICATION_JSON);
+            ack.acknowledge();
+        } catch (IOException e) {
+            emitter.completeWithError(e);
+        }
+    }
+
+}

+ 29 - 0
src/main/java/com/dragon/tj/portal/message/kafka/KafkaInitialConfiguration.java

@@ -0,0 +1,29 @@
+package com.dragon.tj.portal.message.kafka;
+
+import org.apache.kafka.clients.admin.NewTopic;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class KafkaInitialConfiguration {
+
+    public static String sseTopic = "sseTopic";
+
+    /**
+     * 创建一个名为 sseTopic 的Topic并设置分区数为8,分区副本数为2
+     */
+    @Bean
+    public NewTopic initialTopic() {
+
+        return new NewTopic(sseTopic, 1, (short) 1);
+
+    }
+
+    // 如果要修改分区数,只需修改配置值重启项目即可
+    // 修改分区数并不会导致数据的丢失,但是分区数只能增大不能减小
+    @Bean
+    public NewTopic updateTopic() {
+        return new NewTopic(sseTopic, 1, (short) 1);
+
+    }
+}

+ 13 - 0
src/main/java/com/dragon/tj/portal/message/kafka/OpenApiSseEmitter.java

@@ -0,0 +1,13 @@
+package com.dragon.tj.portal.message.kafka;
+
+import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
+
+public class OpenApiSseEmitter extends SseEmitter {
+
+    public OpenApiSseEmitter() {
+    }
+
+    public OpenApiSseEmitter(Long timeout) {
+        super(timeout);
+    }
+}

+ 35 - 0
src/main/java/com/dragon/tj/portal/message/kafka/Producer.java

@@ -0,0 +1,35 @@
+
+package com.dragon.tj.portal.message.kafka;
+
+import cn.hutool.core.util.StrUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.kafka.core.KafkaTemplate;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+@Component
+@Slf4j
+public class Producer {
+
+    @Autowired
+    private KafkaTemplate<String, Object> kafkaTemplate;
+
+    public boolean send(String topic, String msg) {
+        if (!StrUtil.isAllNotEmpty(topic, msg)) {
+            log.error("topic={} or/and msg={} is empty. Will not be sent to Topic.", topic, msg);
+            return false;
+        }
+        log.info("msg will be sent to topic:{}, msg={}", topic, msg);
+
+        try {
+            kafkaTemplate.send(topic, msg).get();
+            log.info("success send msg to topic:{} message:{}", topic, msg);
+        } catch (Exception e) {
+            log.error("send msg fail, topic:{} message: {}, err msg:{}", topic, msg, e.getMessage());
+            return false;
+        }
+        return true;
+    }
+}

+ 48 - 0
src/main/java/com/dragon/tj/portal/message/kafka/SseController.java

@@ -0,0 +1,48 @@
+package com.dragon.tj.portal.message.kafka;
+
+import com.alibaba.fastjson.JSON;
+import com.dragon.tj.portal.common.base.R;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Map;
+
+@Slf4j
+@RestController
+public class SseController {
+
+    @Resource
+    private Map<String, OpenApiSseEmitter> sseEmitters;
+
+    @Resource
+    private Producer producer;
+
+    @GetMapping("/subscribe/{clientId}")
+    public SseEmitter subscribe(@PathVariable String clientId, HttpServletResponse response) {
+
+        response.addHeader("Cache-Control", "no-cache");
+        response.addHeader("X-Accel-Buffering", "no");
+        response.setHeader("Access-Control-Allow-Origin","*");
+
+        log.info("got a subscription, clientId={} will be bound to serverId={}", clientId, "appId");
+        // 创建一个新的SseEmitter对象并设置超时时间,并将其存储在Map中
+        OpenApiSseEmitter emitter = new OpenApiSseEmitter(Long.MAX_VALUE);
+        sseEmitters.put(clientId, emitter);
+        emitter.onCompletion(() -> sseEmitters.remove(clientId));
+
+        return emitter;
+    }
+
+    @PostMapping("/publish/{clientId}")
+    public R publish(@PathVariable String clientId, @RequestBody String message) {
+
+        SsePublishReqDto build = SsePublishReqDto.builder().clientId(clientId).message(message).serverId("appId").build();
+        boolean send = producer.send(KafkaInitialConfiguration.sseTopic, JSON.toJSONString(build));
+        return R.ok(send);
+    }
+
+
+}

+ 19 - 0
src/main/java/com/dragon/tj/portal/message/kafka/SseEmitterBean.java

@@ -0,0 +1,19 @@
+package com.dragon.tj.portal.message.kafka;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Component
+public class SseEmitterBean {
+
+    /**
+     * 在这里存储特定客户端的SseEmitter对象
+     */
+    @Bean(name = "sseEmitters")
+    public Map<String, OpenApiSseEmitter> sseEmitters() {
+        return new ConcurrentHashMap<>();
+    }
+}

+ 18 - 0
src/main/java/com/dragon/tj/portal/message/kafka/SsePublishReqDto.java

@@ -0,0 +1,18 @@
+package com.dragon.tj.portal.message.kafka;
+
+import lombok.*;
+
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class SsePublishReqDto {
+
+    private String serverId;
+
+    private String clientId;
+
+    private String message;
+
+}

+ 13 - 1
src/main/resources/application-local.properties

@@ -3,4 +3,16 @@ spring.datasource.url=jdbc:mysql:///portal?useSSL=true&useUnicode=true&character
 spring.datasource.username=root
 spring.datasource.password=123456
 mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
-#log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl
+#log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl
+spring.kafka.bootstrap-servers=149.28.158.127:9092
+spring.kafka.producer.retries=2
+spring.kafka.producer.acks=1
+spring.kafka.producer.batch-size=16384
+spring.kafka.producer.buffer-memory=33554432
+spring.kafka.consumer.group-id=sse_group
+spring.kafka.consumer.enable-auto-commit=false
+spring.kafka.consumer.auto-commit-interval=100
+spring.kafka.listener.ack-mode=manual
+
+
+

+ 78 - 0
src/main/resources/logback-dev.xml

@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration debug="false">
+    <!-- 应用名称 -->
+    <property name="APP_NAME" value="partal-service"/>
+    <!--日志文件的保存路径,首先查找系统属性-Dlog.dir,如果存在就使用其;否则,在当前目录下创建名为logs目录做日志存放的目录 -->
+    <property name="LOG_HOME" value="${log.dir:-log}/${APP_NAME}"/>
+    <!-- 日志输出格式 -->
+    <property name="ENCODER_PATTERN"
+              value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{80} - %msg%n"/>
+    <contextName>${APP_NAME}</contextName>
+
+
+    <!-- 控制台日志:输出全部日志到控制台 -->
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <Pattern>${ENCODER_PATTERN}</Pattern>
+        </encoder>
+    </appender>
+
+    <!-- 文件日志:输出全部日志到文件 -->
+    <appender name="FILE"
+              class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_HOME}/output.%d{yyyy-MM-dd}.log.gz</fileNamePattern>
+            <maxHistory>15</maxHistory>
+        </rollingPolicy>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${ENCODER_PATTERN}</pattern>
+        </encoder>
+    </appender>
+
+    <!-- 错误日志:用于将错误日志输出到独立文件 -->
+    <appender name="ERROR_FILE"
+              class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_HOME}/error.%d{yyyy-MM-dd}.log.gz</fileNamePattern>
+            <maxHistory>30</maxHistory>
+        </rollingPolicy>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${ENCODER_PATTERN}</pattern>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>WARN</level>
+        </filter>
+    </appender>
+
+    <!-- 4. 最终的策略 -->
+    <!-- 4.1 开发环境:打印控制台 -->
+    <springProfile name="dev">
+        <root>
+            <level value="info"/>
+            <appender-ref ref="STDOUT"/>
+            <appender-ref ref="FILE"/>
+            <appender-ref ref="ERROR_FILE"/>
+        </root>
+    </springProfile>
+
+    <springProfile name="local">
+        <root>
+            <level value="info"/>
+            <appender-ref ref="STDOUT"/>
+            <appender-ref ref="FILE"/>
+            <appender-ref ref="ERROR_FILE"/>
+        </root>
+    </springProfile>
+
+
+    <!-- 4.2 生产环境:输出到文档 -->
+    <springProfile name="prod">
+        <root>
+            <level value="INFO"/>
+            <appender-ref ref="STDOUT"/>
+            <appender-ref ref="FILE"/>
+            <appender-ref ref="ERROR_FILE"/>
+        </root>
+    </springProfile>
+
+</configuration>

+ 0 - 72
src/main/resources/logback-spring.xml

@@ -1,72 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    小技巧: 在根pom里面设置统一存放路径,统一管理方便维护
-    <properties>
-        <log-path>/Users/lengleng</log-path>
-    </properties>
-    1. 其他模块加日志输出,直接copy本文件放在resources 目录即可
-    2. 注意修改 <property name="${log-path}/log.path" value=""/> 的value模块
--->
-<configuration debug="false" scan="false">
-	<property name="log.path" value="logs/${project.artifactId}"/>
-	<!-- 彩色日志格式 -->
-	<property name="CONSOLE_LOG_PATTERN"
-			  value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} [%tid] %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}}"/>
-	<!-- 彩色日志依赖的渲染类 -->
-	<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"/>
-	<!-- Console log output -->
-	<appender name="console" class="com.sunacwy.frame.common.log.appender.LogbackConsoleAppender">
-		<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
-			<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
-				<pattern>${CONSOLE_LOG_PATTERN}</pattern>
-			</layout>
-		</encoder>
-	</appender>
-
-	<!-- Log file debug output -->
-	<appender name="debug" class="ch.qos.logback.core.rolling.RollingFileAppender">
-		<file>${log.path}/debug.log</file>
-		<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-			<fileNamePattern>${log.path}/%d{yyyy-MM, aux}/debug.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
-			<maxFileSize>50MB</maxFileSize>
-			<maxHistory>30</maxHistory>
-		</rollingPolicy>
-		<encoder>
-			<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern>
-		</encoder>
-	</appender>
-
-	<!-- Log file error output -->
-	<appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
-		<file>${log.path}/error.log</file>
-		<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-			<fileNamePattern>${log.path}/%d{yyyy-MM}/error.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
-			<maxFileSize>50MB</maxFileSize>
-			<maxHistory>30</maxHistory>
-		</rollingPolicy>
-		<encoder>
-			<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern>
-		</encoder>
-		<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
-			<level>ERROR</level>
-		</filter>
-	</appender>
-
-	<logger name="org.activiti.engine.impl.db" level="DEBUG">
-		<appender-ref ref="debug"/>
-	</logger>
-
-	<!--nacos 心跳 INFO 屏蔽-->
-	<logger name="com.alibaba.nacos" level="OFF">
-		<appender-ref ref="error"/>
-	</logger>
-	<!-- Level: FATAL 0  ERROR 3  WARN 4  INFO 6  DEBUG 7 -->
-	<root level="INFO">
-		<appender-ref ref="console"/>
-		<appender-ref ref="debug"/>
-	</root>
-</configuration>