24.Axon框架-事件(二)

Axon框架-事件(二)

1.什么是事件处理器

2.明确概念

  • EventProcessor:事件处理器
  • ProcessingGroup:处理组
  • EventHandler:事件处理程序

3.事件处理器分层结构

介绍

  1. 事件处理程序(EventHandler):接收事件时需执行的业务逻辑
  2. 事件处理器(EventProcessor):则是负责处理事件处理过程中技术层面工作的组件。它会启动一个工作单元,可能还会开启事务;此外,它还需确保事件处理期间创建的所有消息能正确附加关联数据,同时满足其他非功能需求(如性能、容错等)
  3. 处理组(Processing Group):每个EventHandler仅属于一个处理组。处理组为事件处理提供了可配置的非功能需求能力,例如错误处理、排序策略等

为EventHandler分配ProcessingGroup

介绍

所有EventProcessor都有一个名称,该名称在多个JVM实例间唯一标识一个EventProcessor实例,两个名称相同的EventProcessor会被视为同一EventProcessor的不同实例

所有EventHandler默认会附加到名称为其类所在包名的事件处理器上。此外,Axon默认使用的EventProcessor实现是TrackingEventProcessor(跟踪式事件处理器)

EventHandler大致分为两类:常规EventHandler,Saga的EventHandler,这里介绍常规EventHandler的流程

两种分配方式

更精细的分配方式

介绍

Axon的配置API允许自定义的更精细的分配方式,这些规则可分为两大类:

  • EventHandler → ProcessingGroup
  • ProcessingGroup → EventProcessor
事件处理程序到处理组
  1. byDefaultAssignTo(String):定义EventHandler的默认ProcessingGroup名称。仅在无更具体规则且未标注@ProcessingGroup注解时生效
  2. byDefaultAssignHandlerInstancesTo(Function<Object, String>):通过Lambda表达式为EventHandler实例分配ProcessingGroup(返回ProcessingGroup名称)。仅在无更具体规则且未标注@ProcessingGroup注解时生效
  3. byDefaultAssignHandlerTypesTo(Function<Class<?>, String>):通过Lambda表达式为EventHandler类型分配ProcessingGroup(返回ProcessingGroup名称)。仅在无更具体规则且未标注@ProcessingGroup注解时生效
  4. assignHandlerInstancesMatching(String, Predicate<Object>):根据EventHandler实例是否匹配Predicate条件,将其分配到指定ProcessingGroup。默认优先级为0;若一个实例匹配多个条件,结果未定义
  5. assignHandlerTypesMatching(String, Predicate<Class<?>>):根据EventHandler类型是否匹配Predicate条件,将其分配到指定ProcessingGroup。默认优先级为0;若一个类型匹配多个条件,结果未定义
  6. assignHandlerInstancesMatching(String, int, Predicate<Object>):功能与第4点类似,但可自定义优先级(数值越高,规则优先级越高)
  7. assignHandlerTypesMatching(String, int, Predicate<Class<?>>):功能与第5点类似,但可自定义优先级(数值越高,规则优先级越高)
处理组到事件处理器
  1. assignProcessingGroup(String, String):将指定名称的ProcessingGroup,分配给指定名称的EventProcessor
  2. assignProcessingGroup(Function<String, String>):通过Lambda表达式为ProcessingGroup分配EventProcessor(输入ProcessingGroup,名称,返回EventProcessor名称)

EventProcessor内部的EventHandler顺序问题

介绍

默认顺序就是它们在配置API中的注册顺序一致

Spring环境下的显式排序

若使用Spring进行依赖注入,可通过@Order注解显式指定事件处理程序的排序。该注解标注在事件处理程序类上,通过整数参数指定优先级(数值越小,优先级越高)

java 复制代码
@ProcessingGroup("my-handlers")
@Order(1) // 优先级高于 @Order(2) 的组件
public class HighPriorityHandler {
    @EventHandler
    public void on(ImportantEvent event) {
        // 高优先级逻辑
    }
}

@ProcessingGroup("my-handlers")
@Order(2) // 优先级低于 @Order(1) 的组件
public class LowPriorityHandler {
    @EventHandler
    public void on(ImportantEvent event) {
        // 低优先级逻辑(在 HighPriorityHandler 之后执行)
    }
}
注意事项

4.事件错误处理

介绍

ProcessingGroup层级(ListenerInvocationErrorHandler)

介绍

ListenerInvocationErrorHandler负责处理事件处理程序方法抛出的异常。默认实现为LoggingErrorHandler,记录异常日志后,继续处理下一个处理程序或事件

原生API配置
java 复制代码
public class AxonConfig {
    // 省略其他配置方法...
    public void configureProcessingGroupErrorHandling(EventProcessingConfigurer processingConfigurer) {
        // 1. 配置所有处理组的默认错误处理器
        processingConfigurer
            .registerDefaultListenerInvocationErrorHandler(conf -> {
                // 示例:返回自定义 ListenerInvocationErrorHandler 实例
                return (exception, event, eventHandler) -> {
                    // 自定义逻辑:如重试、忽略、死信队列投递等
                    log.error("EventHandler [{}] failed to process event [{}]", 
                              eventHandler.getClass().getSimpleName(), 
                              event.getPayloadType().getSimpleName(), 
                              exception);
                    // 若需向上传播异常,直接抛出即可
                    // throw new RuntimeException("Propagate error", exception);
                };
            })
            // 2. 为特定处理组配置专属错误处理器
            .registerListenerInvocationErrorHandler("my-processing-group", conf -> {
                // 为 "my-processing-group" 处理组配置自定义错误处理器
                return new CustomMyGroupErrorHandler();
            });
    }
}
SpringBoot配置
java 复制代码
@Configuration
public class AxonConfig {
    // 省略其他配置方法...
    @Bean
    public ConfigurerModule processingGroupErrorHandlingConfigurerModule() {
        return configurer -> configurer.eventProcessing(processingConfigurer ->
            processingConfigurer
                // 配置默认错误处理器
                .registerDefaultListenerInvocationErrorHandler(conf -> {
                    return new LoggingErrorHandler(); // 也可使用自定义实现
                })
                // 为特定处理组配置错误处理器
                .registerListenerInvocationErrorHandler(
                        "my-processing-group",
                        conf -> new CustomMyGroupErrorHandler()
                )
        );
    }
}
自定义ListenerInvocationErrorHandler

实现ListenerInvocationErrorHandler接口即可自定义错误处理逻辑,接口提供以下参数:

java 复制代码
public interface ListenerInvocationErrorHandler {
    void onError(Exception exception,
                 EventMessage<?> event,
                 EventMessageHandler eventHandler) throws Exception;
}
  1. exception:EventHandler抛出的异常
  2. event:待处理的事件
  3. eventHandler:抛出异常的EventHandler

可根据需求选择重试忽略或向上传播异常;若向上传播,异常会进入EventProcessor

EventProcessor层级(ErrorHandler)

介绍

EventHandler方法外抛出的异常或从EventHandler层级传播上来的异常,由ErrorHandler处理。默认实现为PropagatingErrorHandler,直接重新抛出所有捕获的异常

不同事件处理器类型的异常传播行为
  1. 订阅式事件处理器(SubscribingEventProcessor):异常会传播给事件发布者
  2. 流处理式事件处理器(StreamingEventProcessor):进入错误模式,重试失败后暂停处理
原生API配置
java 复制代码
public class AxonConfig {
    public void configure(EventProcessingConfigurer configurer) {
        configurer
            // 1. 配置所有事件处理器的默认错误处理器
            .registerDefaultErrorHandler(conf -> {
                // 示例:自定义 ErrorHandler,支持重试
                return new RetryingErrorHandler(
                        IntervalRetryScheduler.builder()
                                             .retryCount(3)
                                             .interval(Duration.ofSeconds(1))
                                             .build()
                );
            })
            // 2. 为特定事件处理器配置专属错误处理器
            .registerErrorHandler("my-processor", conf -> {
                return new CustomProcessorErrorHandler();
            });
    }
}
SpringBoot配置
java 复制代码
@Configuration
public class AxonConfig {
    @Bean
    public ConfigurerModule processorErrorHandlingConfigurerModule() {
        return configurer -> configurer.eventProcessing(processing ->
            processing
                // 配置全局默认错误处理器
                .registerDefaultErrorHandler(conf -> new RetryingErrorHandler())
                // 为特定事件处理器配置错误处理器
                .registerErrorHandler("my-processor", conf -> new CustomProcessorErrorHandler())
        );
    }
}
自定义ErrorHandler

实现ErrorHandler接口,通过ErrorContext获取错误上下文信息,自定义处理逻辑(如忽略、重试、死信队列投递等):

java 复制代码
public interface ErrorHandler {
    void handleError(ErrorContext errorContext) throws Exception;
}

// 示例:自定义 ErrorHandler
public class CustomErrorHandler implements ErrorHandler {
    @Override
    public void handleError(ErrorContext errorContext) throws Exception {
        Exception cause = errorContext.getCause();
        EventMessage<?> event = errorContext.getEvent();
        // 自定义逻辑:如判断异常类型,决定是否投递到死信队列
        if (cause instanceof NonTransientException) {
            // 非暂时性异常:投递到死信队列
            deadLetterQueue.send(event, cause);
        } else {
            // 暂时性异常:重试
            throw cause; // 向上传播,触发重试
        }
    }
}

死信队列

这一部分内容,还专门有一章,这里理解为一个持续失败的事件会产生不好的影响,需要死信队列来参与解决

5.EventProcessor通用配置

介绍

除了处理EventHandler分配和错误处理,EventProcessor还支持其他组件的配置。订阅式和流处理式事件处理器的专属配置以后说,这里是通用配置

EventProcessorBuilder

介绍

EventProcessingConfigurer提供了大量EventProcessor的可配置组件,但有时直接提供构建EventProcessor的完整逻辑会更便捷。此时可通过EventProcessorBuilder自定义构建逻辑

配置方式

EventProcessingConfigurer提供两种配置EventProcessorBuilder的方法:

  1. registerEventProcessorFactory(EventProcessorBuilder):为未配置专属构建器的EventProcessor,配置默认构建工厂
  2. registerEventProcessor(String, EventProcessorBuilder):为指定名称的EventProcessor,配置专属构建器
java 复制代码
public class AxonConfig {
    public void configureEventProcessorBuilder(EventProcessingConfigurer processingConfigurer) {
        // 1. 配置默认构建器:所有未指定专属构建器的处理器使用此逻辑
        processingConfigurer.registerEventProcessorFactory((name, config, invoker) -> {
            // 示例:根据处理器名称,选择构建 Subscribing 或 Tracking 处理器
            if (name.startsWith("subscribing-")) {
                return SubscribingEventProcessor.builder()
                                                .name(name)
                                                .eventHandlerInvoker(invoker)
                                                .messageSource(config.eventBus())
                                                .build();
            } else {
                return TrackingEventProcessor.builder()
                                             .name(name)
                                             .eventHandlerInvoker(invoker)
                                             .tokenStore(config.tokenStore())
                                             .build();
            }
        });

        // 2. 为 "custom-processor" 配置专属构建器
        processingConfigurer.registerEventProcessor("custom-processor", 
            (name, config, invoker) -> new CustomEventProcessor(name, invoker, config.eventStore())
        );
    }
}

EventHandler拦截器

介绍

EventProcessor是EventHandler的调用者,因此也是配置EventHandler拦截器的合适位置。由于EventProcessor专门处理事件,此处的拦截器需针对EventMessage,即EventHandlerInterceptor

配置方式

EventProcessingConfigurer提供两种配置拦截器的方法:

  1. registerDefaultHandlerInterceptor(BiFunction<Configuration, String, MessageHandlerInterceptor<? super EventMessage<?>>>):为所有EventProcessor配置默认拦截器(输入全局配置和EventProcessor名称,返回拦截器实例)
  2. registerHandlerInterceptor(String, Function<Configuration, MessageHandlerInterceptor<? super EventMessage<?>>>):为指定名称的EventProcessor配置专属拦截器
java 复制代码
public class AxonConfig {
    public void configureInterceptors(EventProcessingConfigurer processingConfigurer) {
        // 1. 配置全局默认拦截器:为所有处理器添加关联数据拦截
        processingConfigurer.registerDefaultHandlerInterceptor((config, processorName) -> 
            new CorrelationDataInterceptor<>(config.correlationDataProviders())
        );

        // 2. 为 "audit-processor" 配置专属审计拦截器
        processingConfigurer.registerHandlerInterceptor("audit-processor", config -> 
            new AuditLoggingInterceptor() // 自定义审计拦截器,记录事件处理日志
        );
    }
}

消息监控

介绍

所有EventProcessor实例都支持配置MessageMonitor。MessageMonitor用于监控Axon应用中消息的流转过程,对于EvnetProcessor而言,它会专门监控从EventProcessor流向EventHandler的事件

配置方式

MessageMonitorFactory是Axon配置API中通用的监控器构建接口,支持更灵活的监控器创建逻辑:

java 复制代码
@FunctionalInterface
public interface MessageMonitorFactory {
    // 参数说明:
    // - configuration:全局配置(可获取依赖组件)
    // - componentType:组件类型(事件处理器场景下为 EventProcessor 实现类)
    // - componentName:组件名称(事件处理器名称)
    MessageMonitor<Message<?>> create(Configuration configuration,
                                      Class<?> componentType,
                                      String componentName);
}

示例:

java 复制代码
public class AxonConfig {
    public void configureMessageMonitor(EventProcessingConfigurer processingConfigurer) {
        // 使用工厂为 "metrics-processor" 配置监控器
        processingConfigurer.registerMessageMonitorFactory("metrics-processor", 
            (config, componentType, componentName) -> {
                // 示例:基于 Micrometer 实现事件处理指标监控
                return MicrometerMessageMonitor.builder(componentName)
                                              .meterRegistry(config.getComponent(MeterRegistry.class))
                                              .build();
            }
        );
    }
}

事务管理

介绍

EventProcessor负责事件处理,因此也是配置事务的合理位置。大多数场景下,默认配置已足够,本节仅介绍可调整的选项

TransactionManager

Axon使用TransactionManager为每个工作单元附加事务:

  1. Spring环境:默认使用SpringTransactionManager,底层依赖Spring的PlatformTransactionManager
  2. 非Spring环境:若需事务管理,需自定义TransactionManager实现,仅需实现TransactionManager#startTransaction()方法
配置方式

通过EventProcessingConfigurer的registerTransactionManager方法配置:

java 复制代码
public class AxonConfig {
    public void configureTransactionManager(EventProcessingConfigurer processingConfigurer) {
        // 为 "transactional-processor" 配置自定义事务管理器
        processingConfigurer.registerTransactionManager("transactional-processor", 
            config -> new CustomTransactionManager()
        );
    }
}
回滚配置

RollbackConfiguration用于决定工作单元何时需要回滚事务。默认配置为任何Throwable都会触发回滚,其他可选配置可参考工作单元

通过EventProcessingConfigurer的registerRollbackConfiguration方法配置:

java 复制代码
public class AxonConfig {
    public void configureRollback(EventProcessingConfigurer processingConfigurer) {
        // 为 "custom-rollback-processor" 配置自定义回滚策略:仅 RuntimeException 触发回滚
        processingConfigurer.registerRollbackConfiguration("custom-rollback-processor", 
            config -> RollbackConfigurationType.ANY_RUNTIME_EXCEPTION
        );
    }
}
相关推荐
㳺三才人子6 小时前
初探 Flask
后端·python·flask·html
星栈独行6 小时前
我在 Rust 全栈项目里用 JWT 做无状态认证
开发语言·后端·rust·前端框架·开源·github·web
Java爱好狂.6 小时前
Java程序员体系化学习路线(2026最新版)
java·后端·java面试·java架构师·java程序员·java八股文·java学习路线
陈随易6 小时前
Redis 8.8发布,一定要更新
前端·后端·程序员
装不满的克莱因瓶7 小时前
SpringBoot 如何将 lib 目录中jar包打包进最终的jar包里面
spring boot·后端·maven·jar·mvn
ltl7 小时前
Transformer 原论文实验结果:为什么 28.4 BLEU 足以改写路线图
后端
excel8 小时前
为什么我推荐使用 Termius:现代 SSH 工具的完整体验
前端·后端
卷毛的技术笔记9 小时前
Java后端硬核实战:用Spring AI Alibaba+Redis给LLM装上“超强记忆中枢”
java·人工智能·redis·后端·spring·ai·系统架构
IT_陈寒9 小时前
Java的Optional差点让我掉坑里,这几个坑你别踩
前端·人工智能·后端
子兮曰10 小时前
Harness 驾驭工程深度教程:从 AGENTS.md 到全链路 AI 编码基础设施
前端·后端·ai编程