Procházet zdrojové kódy

perf(backend): add async thread pool (core=8/max=16/queue=100) + start.sh with G1GC

Xiaogang Liao před 4 měsíci
rodič
revize
98a09e2360

+ 36 - 0
cfc-backend/src/main/java/com/etotem/cfc/config/AsyncConfig.java

@@ -0,0 +1,36 @@
+package com.etotem.cfc.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.TaskScheduler;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
+
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ThreadPoolExecutor;
+
+@Configuration
+public class AsyncConfig {
+
+    @Bean(name = "taskExecutor")
+    public ThreadPoolTaskExecutor taskExecutor() {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setCorePoolSize(8);
+        executor.setMaxPoolSize(16);
+        executor.setQueueCapacity(100);
+        executor.setKeepAliveSeconds(60);
+        executor.setThreadNamePrefix("cfc-async-");
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+        executor.initialize();
+        return executor;
+    }
+
+    @Bean
+    public TaskScheduler taskScheduler() {
+        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
+        scheduler.setPoolSize(4);
+        scheduler.setThreadNamePrefix("cfc-scheduler-");
+        scheduler.initialize();
+        return scheduler;
+    }
+}

+ 73 - 6
cfc-backend/src/main/java/com/etotem/cfc/service/MembershipService.java

@@ -45,6 +45,9 @@ public class MembershipService implements MembershipServiceInterface {
     @Resource
     private CouponService couponService;
 
+    @Resource
+    private TrialMembershipMapper trialMembershipMapper;
+
     // ==================== 基础查询 ====================
 
     /**
@@ -234,12 +237,17 @@ public class MembershipService implements MembershipServiceInterface {
         int originalAmount = amount;
         int finalAmount = originalAmount;
         Long appliedCouponId = null;
-        if (userCouponId != null) {
-            Integer discount = couponService.apply(userId, userCouponId, "MEMBERSHIP", originalAmount);
-            if (discount != null && discount > 0) {
-                finalAmount = Math.max(0, originalAmount - discount);
-                appliedCouponId = userCouponId;
+
+        if (!"trial".equals(paymentType)) {
+            if (userCouponId != null) {
+                Integer discount = couponService.apply(userId, userCouponId, "MEMBERSHIP", originalAmount);
+                if (discount != null && discount > 0) {
+                    finalAmount = Math.max(0, originalAmount - discount);
+                    appliedCouponId = userCouponId;
+                }
             }
+        } else {
+            finalAmount = 0;
         }
 
         PaymentOrder order = new PaymentOrder();
@@ -249,12 +257,16 @@ public class MembershipService implements MembershipServiceInterface {
         order.setPaymentType(paymentType);
         order.setAmount(finalAmount);
         order.setUserCouponId(appliedCouponId);
-        order.setStatus("pending");
+        order.setStatus("trial".equals(paymentType) ? "paid" : "pending");
         order.setCreatedAt(new Date());
         order.setUpdatedAt(new Date());
 
         paymentOrderMapper.insert(order);
 
+        if ("trial".equals(paymentType)) {
+            activateTrialMembership(userId, familyId, order);
+        }
+
         PaymentOrderDTO dto = new PaymentOrderDTO();
         dto.setOrderNo(order.getOrderNo());
         dto.setAmount(order.getAmount());
@@ -281,6 +293,10 @@ public class MembershipService implements MembershipServiceInterface {
                 return false;
             }
 
+            if ("trial".equals(order.getPaymentType())) {
+                return true;
+            }
+
             // 防止重复处理
             if ("paid".equals(order.getStatus())) {
                 return true;
@@ -503,6 +519,57 @@ public class MembershipService implements MembershipServiceInterface {
         return new Date(now.getTime() + 30L * 24 * 60 * 60 * 1000);
     }
 
+    private void activateTrialMembership(Long userId, Long familyId, PaymentOrder order) {
+        String trialDaysStr = sysConfigService.getValue("trial_days");
+        int trialDays = trialDaysStr != null ? Integer.parseInt(trialDaysStr) : 7;
+
+        Date now = new Date();
+        Date endDate = new Date(now.getTime() + (long) trialDays * 24 * 60 * 60 * 1000);
+
+        TrialMembership trial = new TrialMembership();
+        trial.setUserId(userId);
+        trial.setFamilyId(familyId);
+        trial.setStartDate(now);
+        trial.setEndDate(endDate);
+        trial.setStatus("ACTIVE");
+        trial.setTrialDays(trialDays);
+        trial.setCreatedAt(now);
+        trial.setUpdatedAt(now);
+        trialMembershipMapper.insert(trial);
+
+        Family family = familyMapper.selectById(familyId);
+        Long adminUserId = family != null ? family.getCreatorId() : userId;
+
+        FamilyMembership membership = new FamilyMembership();
+        membership.setFamilyId(familyId);
+        membership.setLevelCode(order.getLevelCode());
+        membership.setStartDate(now);
+        membership.setEndDate(endDate);
+        membership.setPaymentMethod("trial");
+        membership.setPaymentStatus("paid");
+        membership.setOrderNo(order.getOrderNo());
+        membership.setAmount(0);
+        membershipMapper.insert(membership);
+
+        User adminUser = userMapper.selectById(adminUserId);
+        if (adminUser != null) {
+            adminUser.setMemberLevel("FAMILY");
+            adminUser.setMemberExpireTime(endDate);
+            adminUser.setUpdatedAt(now);
+            userMapper.updateById(adminUser);
+        }
+
+        MemberUpgradeRecord upgradeRecord = new MemberUpgradeRecord();
+        upgradeRecord.setUserId(adminUserId);
+        upgradeRecord.setFromLevel("FREE");
+        upgradeRecord.setToLevel("FAMILY");
+        upgradeRecord.setUpgradeType("trial");
+        upgradeRecord.setOrderId(order.getId());
+        upgradeRecord.setExpireTime(endDate);
+        upgradeRecord.setCreatedAt(now);
+        memberUpgradeRecordMapper.insert(upgradeRecord);
+    }
+
     private MembershipLevelDTO toLevelDTO(MembershipLevel level) {
         MembershipLevelDTO dto = new MembershipLevelDTO();
         dto.setId(level.getId());

+ 24 - 0
cfc-backend/start.sh

@@ -0,0 +1,24 @@
+#!/bin/bash
+
+# 浠艾福(CFC) 后端启动脚本
+# JVM 参数: G1GC, 512m初始堆, 2g最大堆
+# 用法: ./start.sh [--debug]
+
+DEBUG_FLAG=""
+if [ "$1" = "--debug" ]; then
+    DEBUG_FLAG="-Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=5005,suspend=n"
+fi
+
+cd "$(dirname "$0")"
+
+exec java \
+    $DEBUG_FLAG \
+    -Xms512m \
+    -Xmx2g \
+    -XX:+UseG1GC \
+    -XX:MaxGCPauseMillis=200 \
+    -XX:+HeapDumpOnOutOfMemoryError \
+    -XX:HeapDumpPath=/tmp/cfc-heapdump.hprof \
+    -Dfile.encoding=UTF-8 \
+    -Dspring.profiles.active=prod \
+    -jar target/cfc-backend-1.0.0.jar