通义千问3-VL-Reranker-8B保姆级教程:模型分片加载与延迟加载机制解析

核心内容摘要

MiniCPM-o-4.5-nvidia-FlagOS效果展示:基于Java的智能作业批改系统
括号配对问题

Faiss与Milvus实战对比:如何根据项目需求选择向量数据库(附性能测试数据)

一ã€�æ ¸å¿ƒå�Ÿç�†åŸºäº�观察者模å¼�的轻é‡�å®�ç�°Spring事件模å¼�本质是对观察者模å¼�å�‘布-订阅模å¼�çš„å°�装ä¸�å¢�å¼ºæ ¸å¿ƒç›®æ ‡æ˜¯å®�ç�°ç»„ä»¶é—´æ�¾è€¦å�ˆé€šä¿¡â€”—让事件å�‘布者ä¸�监å�¬è€…互ä¸�ç›´æ�¥ä¾�赖通过中间事件载体完æˆ�交互。其è¿�行ä¾�èµ–å››å¤§æ ¸å¿ƒç»„ä»¶å��å�Œæ”¯æ’‘事件的å�‘布ã€�广播ä¸�处ç�†å…¨æµ�程。

1 å››å¤§æ ¸å¿ƒç»„ä»¶äº‹ä»¶Eventæ•°æ�®è½½ä½“å°�è£…éœ€ä¼ é€’çš„ä¸šåŠ¡ä¿¡æ�¯ã€‚Spring

2�需继承ApplicationEvent抽象类基�JDKEventObject

2å��支æŒ�ä»»æ„�POJO作为事件ç�µæ´»æ€§æ˜¾è‘—æ��å�‡ã€‚常è§�场景如用户注册ã€�订å�•状æ€�å�˜æ›´äº‹ä»¶ä»…需å°�è£…æ ¸å¿ƒå­—æ®µç”¨æˆ·IDã€�订å�•å�·ç­‰å�³å�¯ã€‚事件å�‘布者Publisher负责触å�‘å¹¶å�‘布事件通过ApplicationEventPublisheræ�¥å�£çš„publishEvent()方法å®�ç�°ã€‚å› Spring容器ApplicationContext本身å®�ç�°äº†è¯¥æ�¥å�£Beanå�¯ç›´æ�¥æ³¨å…¥ApplicationEventPublisher或通过ApplicationEventPublisherAwareæ�¥å�£è�·å�–å�‘布能力。事件监å�¬å™¨Listener订阅并处ç�†ç‰¹å®šäº‹ä»¶çš„ä¸šåŠ¡è½½ä½“æ ¸å¿ƒæ˜¯ç»‘å®šç›®æ ‡äº‹ä»¶ç±»å�‹å¹¶æ‰§è¡Œé€»è¾‘支æŒ�å�Œæ­¥ã€�异步ã€�æ�¡ä»¶è¿‡æ»¤ç­‰å¢�强特性。事件广播器Multicasterè¿�æ�¥å�‘布者ä¸�监å�¬è€…çš„æ ¸å¿ƒæ�¢çº½é»˜è®¤å®�ç�°ä¸ºSimpleApplicationEventMulticaster。其è�Œè´£æ˜¯æ�¥æ”¶å�‘布者事件ã€�筛选匹é…�监å�¬å™¨å†�将事件分å�‘给对应监å�¬å™¨æ˜¯äº‹ä»¶æµ�转的关键中转站。

2 完整è¿�行æµ�程事件触å�‘æ ¸å¿ƒä¸šåŠ¡é€»è¾‘æ‰§è¡Œå®Œæˆ�å��如用户注册æˆ�功å�‘布者调用publishEvent()æ–¹æ³•ä¼ å…¥äº‹ä»¶å¯¹è±¡äº‹ä»¶è½¬å�‘ApplicationEventPublisher将事件委托给ApplicationEventMulticaster监å�¬å™¨åŒ¹é…�å¹¿æ’­å™¨æ ¹æ�®äº‹ä»¶ç±»å�‹ç­›é€‰å‡ºæ‰€æœ‰è®¢é˜…该事件的监å�¬å™¨æ”¯æŒ�æ³›å�‹åŒ¹é…�ã€�æ�¡ä»¶è¿‡æ»¤äº‹ä»¶å¤„ç�†å¹¿æ’­å™¨å°†äº‹ä»¶åˆ†å�‘给匹é…�监å�¬å™¨æ‰§è¡Œé»˜è®¤å�Œæ­¥æ‰§è¡Œå�‘布者阻å¡�等待所有监å�¬å™¨å®Œæˆ�å�¯é…�置为异步。二ã€�深度ç�†è§£æ ¸å¿ƒä»·å€¼ä¸�关键特性

1 æ ¸å¿ƒä»·å€¼è§£è€¦ä¸�æ‰©å±•ä¼ ç»Ÿä¸šåŠ¡ä¸­ä¸»çº¿é€»è¾‘ä¸�副线逻辑常通过直æ�¥è°ƒç”¨è€¦å�ˆå¦‚用户注册å��ç›´æ�¥è°ƒç”¨çŸ­ä¿¡ã€�ä¼˜æƒ åˆ¸æœ�务导致代ç �臃肿ã€�扩展性差。Spring事件模å¼�通过“事件契约â€�拆分逻辑å�‘布者仅负责å�‘布事件ä¸�关心è°�处ç�†ç›‘å�¬è€…仅关注事件处ç�†ä¸�关心事件æ�¥æº�æ ¸å¿ƒä»·å€¼ä½“ç�°åœ¨é™�ä½�耦å�ˆæ¨¡å�—é—´ä»…ä¾�èµ–äº‹ä»¶å¯¹è±¡æ— ç›´æ�¥å¼•用修改æŸ�一逻辑如新å¢�æ�¨é€�æœ�åŠ¡æ— éœ€æ”¹åŠ¨ä¸»çº¿ä»£ç �å¢�强å�¯æ‰©å±•æ–°å¢�å‰¯çº¿ä¸šåŠ¡ä»…éœ€æ·»åŠ ç›‘å�¬å™¨ç¬¦å�ˆâ€œå¼€é—­å�Ÿåˆ™â€�异步æ��速日志ã€�通知等é��æ ¸å¿ƒé€»è¾‘å¼‚æ­¥å¤„ç�†é�¿å…�阻å¡�主线æµ�程æ��å�‡æ�¥å�£å“�应速度è�Œè´£å�•一主线è�šç„¦æ ¸å¿ƒä¸šåŠ¡å¦‚æ³¨å†Œå‰¯çº¿é€»è¾‘åˆ†æ•£åˆ°å¯¹åº”ç›‘å�¬å™¨ä»£ç �å�¯è¯»æ€§ä¸�å�¯ç»´æŠ¤æ€§æ›´å¼ºã€‚

2 关键特性解�

2.

1 å�Œæ­¥ä¸�异步执行默认å�Œæ­¥æ‰§è¡Œå�‘布者线程会等待所有监å�¬å™¨å¤„ç�†å®Œæˆ�适用äº�需ä¿�è¯�æ•°æ�®ä¸€è‡´æ€§çš„场景如订å�•创建å��å�Œæ­¥æ‰£å‡�库存。异步é…�置需两步é…�ç½®ç±»æ·»åŠ EnableAsync注解开å�¯å¼‚步支æŒ�监å�¬å™¨æ–¹æ³•æ·»åŠ Asyncæ³¨è§£æŒ‡å®šå¼‚æ­¥æ‰§è¡Œã€‚å»ºè®®è‡ªå®šä¹‰çº¿ç¨‹æ± æ›¿ä»£é»˜è®¤SimpleAsyncTaskExecutor默认æ¯�次创建新线程性能较差。

2.

2 事务绑定事件部分场景需确�事务�交��执行事件如订�支付�功��券��事务�滚导致数��一致�通过TransactionalEventListener替代EventListener支�指定事务阶段触�phase TransactionPhase.AFTER_COMMIT默认事务�交�触�phase TransactionPhase.AFTER_ROLLBACK事务�滚�触�phase TransactionPhase.BEFORE_COMMIT事务�交�触�。

2.

3 监å�¬å™¨æ‰§è¡Œé¡ºåº�多个监å�¬å™¨è®¢é˜…å�Œä¸€äº‹ä»¶æ—¶å�¯é€šè¿‡Order注解数值越å°�优先级越高或Orderedæ�¥å�£æŒ‡å®šé¡ºåº�。注æ„�异步场景下Orderå¤±æ•ˆå› ç›‘å�¬å™¨åœ¨ä¸�å�Œçº¿ç¨‹æ‰§è¡Œæ— 法ä¿�è¯�顺åº�。

2.

4 ä¸�消æ�¯é˜Ÿåˆ—MQ的区别Spring事件是JVM内部轻é‡�通信方å¼�ä¸�MQ定ä½�差异æ˜�显需按需选择特性Spring事件MQKafka/RabbitMQ作用范围å�•体应用内å�Œä¸€JVM跨进程ã€�è·¨æœ�务分布å¼�æŒ�ä¹…åŒ–æ— è¿›ç¨‹å´©æºƒäº‹ä»¶ä¸¢å¤±æ”¯æŒ�æŒ�久化å�¯é� 性高适用场景å�•体/å�•æœ�务内解耦ã€�è½»é‡�业务微æœ�务跨æœ�务通信ã€�高å�¯é� 需求三ã€�å®�战案例用户注册场景完整å�¯è¿�行版本案例基äº�Spring Boot

2.

xå®�ç�°â€œç”¨æˆ·æ³¨å†Œæˆ�功å��â€�多场景è�”动å�Œæ­¥å�‘欢è¿�邮件ã€�异步å�‘æ–°äººä¼˜æƒ åˆ¸ã€�事务æ��交å��记录日志补充ä¾�èµ–ã€�异常处ç�†ä¸�测试步骤确ä¿�代ç �å�¯ç›´æ�¥å¤�用。

1 �境准备

3.

1 ä¾�赖引入Mavenlt;dependenciesgt; !-- Spring Bootæ ¸å¿ƒä¾�èµ– -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-contextlt;/artifactIdgt; lt;/dependencygt; !-- Webä¾�赖用äº�æ�¥å�£æµ‹è¯• -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-weblt;/artifactIdgt; lt;/dependencygt; !-- JPAä¾�赖模拟数æ�®åº“事务 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-jpalt;/artifactIdgt; lt;/dependencygt; !-- H2内存数æ�®åº“æ— éœ€é¢�外部署 -- dependency groupIdcom.h2database/groupId artifactIdh2/artifactId scoperuntime/scope /dependency /dependencies

3.

2 �置文件application.ymlspring: # H2数�库�置 datasource: url: jdbc:h2:mem:testdb driver-class-name: org.h

Driver username: sa password: # JPAé…�置自动建表ã€�打å�°SQL jpa: hibernate: ddl-auto: create-drop # å�¯åŠ¨å»ºè¡¨å…³é—­åˆ è¡¨ä»…æµ‹è¯•ç”¨ show-sql: true properties: hibernate: format_sql: true # H2æ�§åˆ¶å�°è®¿é—®http://localhost:8080/h2-console h2: console: enabled: true # è‡ªå®šä¹‰å¼‚æ­¥çº¿ç¨‹æ± é…�ç½® async: executor: core-pool-size: 5 max-pool-size: 10 queue-capacity: 20 thread-name-prefix: EventAsync-

3.

3 æ ¸å¿ƒé…�置类import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.transaction.annotation.EnableTransactionManagement; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; Configuration EnableAsync // å¼€å�¯å¼‚步支æŒ� EnableTransactionManagement // å¼€å�¯äº‹åŠ¡ç®¡ç�† EnableScheduling public class EventConfig { Value(${async.executor.core-pool-size}) private int corePoolSize; Value(${async.executor.max-pool-size}) private int maxPoolSize; Value(${async.executor.queue-capacity}) private int queueCapacity; Value(${async.executor.thread-name-prefix}) private String threadNamePrefix; // è‡ªå®šä¹‰å¼‚æ­¥çº¿ç¨‹æ± Bean(name eventTaskExecutor) public Executor eventTaskExecutor() { ThreadPoolTaskExecutor executor new ThreadPoolTaskExecutor(); executor.setCorePoolSize(corePoolSize); executor.setMaxPoolSize(maxPoolSize); executor.setQueueCapacity(queueCapacity); executor.setThreadNamePrefix(threadNamePrefix); // æ‹’ç»�ç­–ç•¥çº¿ç¨‹æ± æ»¡æ—¶ç”±è°ƒç”¨çº¿ç¨‹æ‰§è¡Œé�¿å…�任务丢失 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; } // 异步异常统一处ç�†å™¨ Bean public AsyncUncaughtExceptionHandler asyncUncaughtExceptionHandler() { return (ex, method, params) - { System.err.println(异步任务执行异常方法 method.getName() 异常信æ�¯ ex.getMessage()); ex.printStackTrace(); }; } }

2 æ ¸å¿ƒå®�体ä¸�事件定义

3.

1 Userå®�ä½“ç±»æ˜ å°„æ•°æ�®åº“表import lombok.Data; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import java.io.Serializable; Entity // JPAå®�体注解对应数æ�®åº“表 Data // Lombok自动生æˆ�getterã€�setterã€�toString public class User implements Serializable { private static final long serialVersionUID 1L; Id // 主键 GeneratedValue(strategy GenerationType.IDENTITY) // 自å¢�ç­–ç•¥ private Long userId; private String username; private String email; private String password; // å®�é™…å¼€å�‘éœ€åŠ å¯†å­˜å‚¨ }

3.

2 自定义事件UserRegisteredEvent用POJO�装事件数�字段设为final�������监�过程中数�被篡改// 用户注册事件Spring

2æ— éœ€ç»§æ‰¿ApplicationEvent public class UserRegisteredEvent { // äº‹ä»¶æ ¸å¿ƒæ•°æ�®ä¸�å�¯å�˜ private final Long userId; private final String username; private final String email; // å…¨å�‚æ�„é€ å™¨åˆ�始化事件数æ�® public UserRegisteredEvent(Long userId, String username, String email) { this.userId userId; this.username username; this.email email; } // ä»…æ��ä¾›getteræ— setter public Long getUserId() { return userId; } public String getUsername() { return username; } public String getEmail() { return email; } }

3 事件å�‘布者å®�ç�°æ ¸å¿ƒä¸šåŠ¡æœ�务UserServiceå®�ç�°æ³¨å†Œæ ¸å¿ƒé€»è¾‘注入JPA Repositoryæ“�作数æ�®åº“事务æ��交å��å�‘布事件å�Œæ—¶å¤„ç�†ä¸šåС异叏import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; Service public class UserService { Autowired private UserRepository userRepository; // JPAæ•°æ�®è®¿é—®æ�¥å�£ Autowired private ApplicationEventPublisher eventPublisher; // 事件å�‘布器 // 事务注解ä¿�è¯�注册逻辑ä¸�æ•°æ�®åº“æ“�作å�Ÿå­�性 Transactional(rollbackFor Exception.class) public void register(User user) { try { //

æ ¸å¿ƒä¸šåŠ¡åŠ å¯†å¯†ç �模拟å®�际用BCryptç­‰åŠ å¯† user.setPassword(encrypted_ user.getPassword()); //

�存用户到数�库 User savedUser userRepository.save(user); System.out.println(用户[ savedUser.getUsername() ]注册�功ID savedUser.getUserId()); //

å�‘布用户注册事件事务æ��交å��事务绑定监å�¬å™¨æ‰�会执行 eventPublisher.publishEvent(new UserRegisteredEvent( savedUser.getUserId(), savedUser.getUsername(), savedUser.getEmail() )); } catch (Exception e) { System.err.println(用户注册失败å�Ÿå› e.getMessage()); throw e; // 抛出异常触å�‘事务å›�滚 } } }

3.

1 UserRepositoryJPAæ•°æ�®è®¿é—®æ�¥å�£import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; // JpaRepositoryæ��ä¾›CRUDã€�åˆ†é¡µç­‰åŸºç¡€æ–¹æ³•æ— éœ€æ‰‹åŠ¨å®�ç�° Repository public interface UserRepository extends JpaRepositoryUser, Long { // 自定义查询判断用户å��是å�¦å·²å­˜åœ¨ boolean existsByUsername(String username); }

4 事件监å�¬å™¨å®�ç�°å¤šåœºæ™¯è�”动定义3个监å�¬å™¨è¦†ç›–å�Œæ­¥ã€�异步ã€�事务绑定场景å�Œæ—¶æ·»åР异叏æ�•è�·import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import org.springframework.transaction.event.TransactionPhase; import org.springframework.transaction.event.TransactionalEventListener; import org.springframework.core.annotation.Order; Component // 交给Spring管ç�† public class UserRegisteredListeners { //

�步监���欢�邮件需�时�馈优先级最高 EventListener Order(

// 数值越�优先级越高 public void sendWelcomeEmail(UserRegisteredEvent event) { try { // 模拟邮件��耗时�作�际调用邮件SDK Thread.sleep(

; System.out.println(��步任务】��欢�邮件给用户[ event.getUsername() ]邮箱 event.getEmail()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.err.println(��欢�邮件失败用户ID event.getUserId()); } } //

异步监å�¬å�‘æ”¾æ–°äººä¼˜æƒ åˆ¸é��æ ¸å¿ƒé€»è¾‘ç»‘å®šè‡ªå®šä¹‰çº¿ç¨‹æ± Async(eventTaskExecutor) EventListener Order(

public void grantNewUserCoupon(UserRegisteredEvent event) { // æ¨¡æ‹Ÿä¼˜æƒ åˆ¸å�‘æ”¾é€»è¾‘è°ƒç”¨ä¼˜æƒ åˆ¸æœ�务 System.out.println(ã€�异步任务】å�‘æ”¾æ–°äººä¼˜æƒ åˆ¸ç»™ç”¨æˆ·[ event.getUserId() ]线程å�� Thread.currentThread().getName()); } //

事务绑定监�记录注册日志事务�交�执行��数�一致性 TransactionalEventListener(phase TransactionPhase.AFTER_COMMIT) public void recordRegisterLog(UserRegisteredEvent event) { // 模拟日志记录�际写入数�库或日志框� System.out.println(�事务绑定任务】事务�交�记录用户[ event.getUserId() ]注册日志用户� event.getUsername()); } }

5 测试验�

3.

1 测试æ�¥å�£UserControllerimport org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; RestController RequestMapping(/api/user) public class UserController { Autowired private UserService userService; Autowired private UserRepository userRepository; // 注册æ�¥å�£æ�¥æ”¶JSONå�‚æ•° PostMapping(/register) public String register(RequestBody User user) { // æ ¡éªŒç”¨æˆ·å��是å�¦å·²å­˜åœ¨ if (userRepository.existsByUsername(user.getUsername())) { return 用户å��已存在; } userService.register(user); return 注册æˆ�功已触å�‘å��续任务; } }

3.

2 测试步骤ä¸�预期结æ�œå�¯åŠ¨åº”ç”¨è®¿é—®H2æ�§åˆ¶å�°http://localhost:8080/h2-console验è¯�æ•°æ�®åº“表结æ�„通过Postman/curl调用æ�¥å�£curl -X POST http://localhost:8080/api/user/register-H “Content-Type: application/jsonâ€�-d ‘{“usernameâ€�:“zhangsanâ€�,“emailâ€�:“zhangsantest.comâ€�,“passwordâ€�:“123456â€�}’预期日志顺åº�体ç�°å�Œæ­¥ã€�异步ã€�事务绑定差异用户[zhangsan]注册æˆ�功ID1æ ¸å¿ƒä¸šåŠ¡æ‰§è¡Œã€�å�Œæ­¥ä»»åŠ¡ã€‘å�‘é€�欢è¿�邮件给用户[zhangsan]邮箱zhangsantest.comå�Œæ­¥é˜»å¡�ã€�事务绑定任务】事务æ��交å��记录用户[1]注册日志事务æ��交å��触å�‘ã€�异步任务】å�‘æ”¾æ–°äººä¼˜æƒ åˆ¸ç»™ç”¨æˆ·[1]线程å��EventAsync-1异步é��阻å¡�。事务å›�滚验è¯�在UserServiceå�‘布事件å‰�抛出异常观察事务å›�滚事务绑定任务ä¸�执行。

6 扩展场景æ�¡ä»¶ç›‘å�¬é€šè¿‡conditionå±�性å®�ç�°æ�¡ä»¶è¿‡æ»¤ä»…对特定用户触å�‘逻辑如ä¼�业邮箱用户// 仅当用户邮箱为ä¼�业邮箱时触å�‘ EventListener(condition #event.email.endsWith(company.com)) public void sendVipWelcomeMessage(UserRegisteredEvent event) { System.out.println(ã€�VIP专å±�】å�‘é€�ä¼�业用户欢è¿�消æ�¯ç”¨æˆ· event.getUsername()); }å››ã€�生产ç�¯å¢ƒæ³¨æ„�事项事件ä¸�å�¯å�˜äº‹ä»¶å­—段设为final并通过æ�„é€ å™¨åˆ�始化é�¿å…�监å�¬è¿‡ç¨‹ä¸­æ•°æ�®è¢«ç¯¡æ”¹å¯¼è‡´é€»è¾‘异常幂等性设计监å�¬å™¨å�¯èƒ½å› é‡�试ã€�异步延迟é‡�å¤�处ç�†éœ€é€šè¿‡â€œç”¨æˆ·ID业务类å�‹â€�å�šå¹‚ç­‰æ ¡éªŒå¦‚æ•°æ�®åº“唯一索引ã€�ç¼“å­˜æ ‡è®°é�¿å…�循ç�¯å�‘布ç¦�止在监å�¬å™¨ä¸­å�‘布å�Œç±»äº‹ä»¶é˜²æ­¢æ­»å¾ªç�¯è€—尽系统资æº�异常处ç�†å�Œæ­¥åœºæ™¯ä¸‹ç›‘å�¬å™¨å¼‚常会阻断å�‘布者æµ�程需主动æ�•è�·å¼‚步场景异常默认ä¸�ä¼ æ’­éœ€é€šè¿‡AsyncUncaughtExceptionHandler统一处ç�†ä¸�滥用事件仅

个副线逻辑的简å�•ä¸šåŠ¡æ— éœ€å¼•å…¥äº‹ä»¶é�¿å…�å¢�åŠ ç³»ç»Ÿå¤�æ�‚度适用äº�多组件è�”动ã€�需扩展的场景。五ã€�å¾®æœ�务中Spring事件模å¼�的适é…�方案微æœ�务æ�¶æ�„下Spring事件并é��ä¸�å�¯ç”¨æ ¸å¿ƒè¾¹ç•Œæ˜¯ä»…适用äº�å�•æœ�务内解耦跨æœ�务通信需结å�ˆMQ补充形æˆ�“å�•æœ�务内事件跨æœ�务MQâ€�的混å�ˆæ¨¡å¼�兼顾轻é‡�解耦ä¸�分布å¼�å�¯é� 性。

1 å�•æœ�åŠ¡å†…å¸¸è§„ä½¿ç”¨æ ¸å¿ƒåœºæ™¯å�•个微æœ�务节点如用户æœ�务ã€�订å�•æœ�务内部的组件通信用法ä¸�å�•ä½“åº”ç”¨ä¸€è‡´ç›®æ ‡æ˜¯è§£è€¦æœ�务内模å�—Controllerã€�Serviceã€�Listenerä¸�ä¾�赖外部中间件。

5.

1 使用è¦�点适用场景æœ�务内副线逻辑è�”动如注册å��更新本地缓存ã€�è®°å½•æœ¬åœ°æ—¥å¿—æ— éœ€è·¨æœ�务交互注æ„�事项多å®�例部署时事件仅在å�‘布å®�ä¾‹å†…ä¼ æ’­å…¶ä»–å®�ä¾‹æ— æ³•æ„ŸçŸ¥éœ€ç»“å�ˆä¸šåС容å¿�åº¦é€‰æ‹©ä¼˜åŠ¿æ— ç½‘ç»œå¼€é”€ã€�è½»é‡�高效ä¸�å¢�åŠ å¾®æœ�务æ�¶æ�„å¤�æ�‚度。

2 è·¨æœ�务通信适é…�关键补充微æœ�务跨æœ�务è�”动如用户注册å��é€šçŸ¥ä¼˜æƒ åˆ¸æœ�务需通过“Spring事件MQâ€�å®�ç�°æ ¸å¿ƒæ€�路用MQ承æ�¥è·¨æœ�务消æ�¯ç›®æ ‡æœ�务消费MQå��触å�‘自身Spring事件处ç�†ä¿�æŒ�消费端内部分解耦。

5.

1 å®�ç�°æµ�程å�‘布端用户æœ�务注册æˆ�功å��å�Œæ—¶å�‘布本地事件处ç�†æœ�务内逻辑和MQ消æ�¯é€šçŸ¥è·¨æœ�务MQä¼ è¾“é€šè¿‡MQå®�ç�°è·¨æœ�务数æ�®ä¼ 递利用æŒ�久化ã€�é‡�试机制ä¿�éšœå�¯é� æ€§æ¶ˆè´¹ç«¯ä¼˜æƒ åˆ¸æœ�务监å�¬MQ消æ�¯æ¶ˆè´¹æˆ�功å��å�‘布本地事件触å�‘å�‘券ã€�日志等逻辑。

5.

2 代ç �å®�战基äº�å‰�文扩展第一步引入MQä¾�èµ–å�‘布端ã€�消费端å�‡éœ€!-- Kafkaä¾�赖示例 -- dependency groupIdorg.springframework.kafka/groupId artifactIdspring-kafka/artifactId /dependency第二步å�‘布端用户æœ�务å¢�强import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.kafka.core.KafkaTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; Service public class UserService { Autowired private UserRepository userRepository; Autowired private ApplicationEventPublisher eventPublisher; Autowired private KafkaTemplateString, String kafkaTemplate; Autowired private ObjectMapper objectMapper; Transactional(rollbackFor Exception.class) public void register(User user) { try { user.setPassword(encrypted_ user.getPassword()); User savedUser userRepository.save(user); System.out.println(用户[ savedUser.getUsername() ]注册æˆ�功ID savedUser.getUserId()); //

�布本地事件处��务内逻辑 UserRegisteredEvent localEvent new UserRegisteredEvent( savedUser.getUserId(), savedUser.getUsername(), savedUser.getEmail() ); eventPublisher.publishEvent(localEvent); //

å�‘é€�MQ消æ�¯é€šçŸ¥è·¨æœ�务 String mqMessage objectMapper.writeValueAsString(localEvent); kafkaTemplate.send(user-registered-topic, mqMessage); } catch (Exception e) { System.err.println(用户注册失败å�Ÿå› e.getMessage()); throw e; // 事务å›�滚需é…�å�ˆMQ事务消æ�¯ä¿�è¯�一致性 } } }ç¬¬ä¸‰æ­¥æ¶ˆè´¹ç«¯ä¼˜æƒ åˆ¸æœ�务å®�ç�°import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; Component public class UserMqConsumer { Autowired private ApplicationEventPublisher eventPublisher; Autowired private ObjectMapper objectMapper; // 监å�¬MQ主题æ�¥æ”¶ç”¨æˆ·æ³¨å†Œæ¶ˆæ�¯ KafkaListener(topics user-registered-topic) public void consumeUserRegisteredMessage(String message) { try { // å��åº�列化消æ�¯ä¸ºäº‹ä»¶å¯¹è±¡ UserRegisteredEvent event objectMapper.readValue(message, UserRegisteredEvent.class); // å�‘布本地事件解耦消费ä¸�业务逻辑 eventPublisher.publishEvent(new CouponGrantEvent(event.getUserId(), event.getUsername())); } catch (Exception e) { System.err.println(消费用户注册消æ�¯å¤±è´¥æ¶ˆæ�¯å†…容 message); // 异常处ç�†è§¦å�‘é‡�试ã€�死信队列 } } // ä¼˜æƒ åˆ¸æœ�务本地事件 public static class CouponGrantEvent { private final Long userId; private final String username; public CouponGrantEvent(Long userId, String username) { this.userId userId; this.username username; } // getter方法 public Long getUserId() { return userId; } public String getUsername() { return username; } } // 本地事件监å�¬å™¨å¤„ç�†å�‘券逻辑 Component public static class CouponGrantListener { EventListener Async(eventTaskExecutor) public void grantCoupon(CouponGrantEvent event) { System.out.println(ã€�ä¼˜æƒ åˆ¸æœ�务】为用户[ event.getUserId() ]å�‘æ”¾æ–°äººä¼˜æƒ åˆ¸); // æ ¸å¿ƒå�‘券逻辑æ“�ä½œä¼˜æƒ åˆ¸DAOã€�缓存更新等 } } }

3 å¾®æœ�务特有注æ„�事项事务一致性å�‘布端需使用MQ事务消æ�¯å¦‚Kafka事务ã€�RabbitMQ Confirm机制确ä¿�“本地事务æ��交â€�ä¸�“MQ消æ�¯å�‘é€�â€�å�Ÿå­�性多å®�例隔离å�•æœ�务多å®�例部署时本地事件仅在å�‘布å®�例生效需全å®�例感知å�¯ç»“å�ˆMQ广播模å¼�如RabbitMQ Fanout交æ�¢æœºå¹‚等性强化跨æœ�务场景下MQ消æ�¯å�¯èƒ½é‡�å¤�消费需在监å�¬å™¨ä¸­å�šå¹‚ç­‰æ ¡éªŒé�¿å…�过度嵌套跨æœ�åŠ¡æ ¸å¿ƒä¸šåŠ¡ä¼˜å…ˆç”¨MQç›´æ�¥æ¶ˆè´¹å‡�少“事件嵌套â€�带æ�¥çš„æ�’查å¤�æ�‚度。六ã€�总结Spring事件模å¼�是å�•体/å�•å¾®æœ�务内解耦的轻é‡�工具基äº�观察者模å¼�æ��ä¾›å�Œæ­¥ã€�异步ã€�äº‹åŠ¡ç»‘å®šç­‰ç‰¹æ€§æ ¸å¿ƒä»·å€¼æ˜¯ç®€åŒ–ç»„ä»¶è�”动ã€�æ��å�‡ä»£ç �å�¯æ‰©å±•性。其使用边界清晰å�•æœ�务内å�¯ç›´æ�¥å¤�用本文å®�战方案跨æœ�务需结å�ˆMQå®�ç�°åˆ†å¸ƒå¼�通信形æˆ�“内用事件ã€�外用MQâ€�的混å�ˆæ¨¡å¼�。å®�é™…å¼€å�‘ä¸­éœ€ä¸¥æ ¼åŒºåˆ†ä½¿ç”¨åœºæ™¯è§„é�¿å¼‚常ã€�循ç�¯å�‘布ã€�æ•°æ�®ä¸€è‡´æ€§ç­‰é™·é˜±æ—¢èƒ½å�‘挥其轻é‡�高效的优势å�ˆèƒ½é€‚é…�ä¸�å�Œæ�¶æ�„å�•体/å¾®æœ�务的需求å®�ç�°ä¸šåŠ¡é€»è¾‘çš„æ¸…æ™°åˆ†å±‚ä¸�å�¯é� è¿�行。

蘑菇视频隐藏路线版最新版-蘑菇视频隐藏路线版最新版应用

百度百家号客服电话人工服务

123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123