You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Cloud微服务系统中Axon事件溯源落地全流程咨询

Hey there! Let's walk through how to implement Axon Framework with Event Sourcing in your Spring Cloud microservices setup— I’ll cover all your questions, from core configuration to aggregate design, plus point you to fresh, up-to-date examples since the old GitHub ones are too dated.

Axon + Spring Cloud: Event Sourcing Implementation Guide

1. Core Architecture Overview

First, let’s align on the big picture: Axon ties together command routing (via distributed command bus), event propagation (across services via event bus/MQ), and event storage (for event sourcing) in Spring Cloud. Each microservice will own its aggregates, handle commands, publish events, and subscribe to events from other services to update read models or trigger workflows.

2. Step-by-Step Configuration

2.1 Distributed Command Bus (DCB)

Axon’s DCB uses Spring Cloud Service Discovery (like Eureka) to route commands to the correct service that owns the target aggregate.

Dependencies

Add these to your pom.xml (use the latest stable Axon version, e.g., 4.9.x):

<!-- Axon Spring Cloud integration -->
<dependency>
    <groupId>org.axonframework</groupId>
    <artifactId>axon-spring-cloud-starter</artifactId>
    <version>4.9.0</version>
</dependency>
<!-- Spring Cloud Eureka Client (or your preferred service discovery) -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

Application Configuration (application.yml)

axon:
  distributed:
    enabled: true
    command-bus:
      spring-cloud:
        enabled: true
        discovery-client: eureka
        routing-strategy: consistent-hash # Use round-robin for simple load balancing
spring:
  application:
    name: order-service # Unique name for each microservice
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

Why consistent-hash? It ensures commands targeting the same aggregate always go to the same service instance, avoiding concurrency issues.

2.2 Event Bus & MQ Integration

For cross-service event propagation, you have two solid options:

Option 1: Axon Server (Recommended)

Axon Server is the official, purpose-built tool for Axon— it handles event storage, command routing, and event propagation out of the box, so you don’t need a separate MQ.

Dependencies
<dependency>
    <groupId>org.axonframework</groupId>
    <artifactId>axon-server-connector-spring-boot-starter</artifactId>
    <version>4.9.0</version>
</dependency>
Configuration
axon:
  server:
    enabled: true
    servers: axon-server:8124 # Your Axon Server instance address

Axon Server automatically syncs events across all services and provides a dashboard to monitor event streams and command traffic.

Option 2: Kafka/RabbitMQ as Event Bus

If you prefer using an existing MQ, Axon integrates seamlessly with Kafka or RabbitMQ. Here’s a Kafka example:

Dependencies
<dependency>
    <groupId>org.axonframework</groupId>
    <artifactId>axon-kafka-spring-boot-starter</artifactId>
    <version>4.9.0</version>
</dependency>
Configuration
axon:
  eventhandling:
    processors:
      default:
        mode: tracking # Persists processing progress, critical for event replay
  kafka:
    producer:
      bootstrap-servers: localhost:9092
    consumer:
      bootstrap-servers: localhost:9092
      group-id: ${spring.application.name} # Each service gets its own consumer group

2.3 Data Source Configuration for Event Store

If you’re not using Axon Server, you’ll need to configure a custom event store (e.g., JDBC/MongoDB). Here’s a JDBC setup with MySQL:

Dependencies

<dependency>
    <groupId>org.axonframework</groupId>
    <artifactId>axon-jdbc</artifactId>
    <version>4.9.0</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

Configuration Class

@Configuration
public class AxonJdbcConfig {

    @Autowired
    private DataSource dataSource;

    @Bean
    public EventStorageEngine eventStorageEngine(Serializer serializer) {
        return JdbcEventStorageEngine.builder()
                .dataSource(dataSource)
                .serializer(serializer)
                .build();
    }
}

Application Configuration

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/axon_event_store
    username: root
    password: your-password
    driver-class-name: com.mysql.cj.jdbc.Driver

Axon will auto-create the required tables (domain_event_entry, snapshot_event_entry) to store events.

3. Microservice Event Storage Mechanism

You have two event storage strategies to choose from:

  • Centralized Event Store: Use Axon Server as a single source of truth for all events. This simplifies cross-service event queries and replay, and is ideal for most use cases.
  • Distributed Event Store: Each microservice maintains its own event store (JDBC/Mongo). Great for strict data isolation, but requires additional work to build cross-service read models (e.g., using Axon Query Bus or projecting events to a shared database).

Snapshotting (Critical for Performance)

To avoid replaying hundreds/thousands of events when loading an aggregate, enable snapshotting:

axon:
  snapshot:
    trigger:
      threshold: 50 # Take a snapshot after 50 events per aggregate

You can also customize snapshot triggers with the @SnapshotTriggerDefinition annotation on your aggregate class.

4. Aggregate Object Generation Logic

Aggregates are the heart of event sourcing— their state is entirely built by replaying past events. Follow these rules:

  1. Annotate the Aggregate: Use @Aggregate for the class, @AggregateIdentifier for the unique ID field.
  2. Command Handlers: Use @CommandHandler to handle commands and publish events via AggregateLifecycle.apply().
  3. Event Sourcing Handlers: Use @EventSourcingHandler to update the aggregate’s state when events are applied.
  4. No-Arg Constructor: Required for Axon to reconstruct the aggregate from events.

Example Aggregate

@Aggregate
public class OrderAggregate {

    @AggregateIdentifier
    private String orderId;
    private OrderStatus status;

    // Required for event sourcing reconstruction
    protected OrderAggregate() {}

    @CommandHandler
    public OrderAggregate(CreateOrderCommand command) {
        // Validate command input
        if (StringUtils.isEmpty(command.getOrderId())) {
            throw new IllegalArgumentException("Order ID cannot be empty");
        }
        // Publish event to trigger state change
        AggregateLifecycle.apply(new OrderCreatedEvent(
                command.getOrderId(),
                command.getProductId(),
                command.getQuantity()
        ));
    }

    @EventSourcingHandler
    public void on(OrderCreatedEvent event) {
        this.orderId = event.getOrderId();
        this.status = OrderStatus.CREATED;
    }

    @CommandHandler
    public void handle(ConfirmOrderCommand command) {
        if (!status.equals(OrderStatus.CREATED)) {
            throw new IllegalStateException("Only created orders can be confirmed");
        }
        AggregateLifecycle.apply(new OrderConfirmedEvent(command.getOrderId()));
    }

    @EventSourcingHandler
    public void on(OrderConfirmedEvent event) {
        this.status = OrderStatus.CONFIRMED;
    }
}

When you load an aggregate, Axon fetches all its events from the event store and runs them through the @EventSourcingHandler methods to rebuild the current state.

5. Up-to-Date Example Projects

Since the old GitHub examples are outdated, here are reliable ways to get started:

  • Official Axon Samples: The Axon Framework repo has a samples directory with a spring-cloud-sample project (using 4.9.x) that demonstrates distributed command routing, Axon Server integration, and cross-service event handling.
  • Custom Multi-Service Demo: Build two simple services:
    1. order-service: Handles order commands, publishes order events.
    2. inventory-service: Subscribes to order events to update inventory levels.
      Use Axon Server for event storage and propagation, plus Eureka for service discovery.

6. Key Best Practices

  • Keep Aggregates Small: Each aggregate should own a single business boundary (e.g., Order, InventoryItem) to avoid bloated event streams.
  • Use Event Upcasters: When you need to change event schemas, use upcasters to convert old events to new formats without breaking event replay.
  • Test Event Sourcing: Write tests that verify aggregate state is correctly rebuilt from events, and that commands produce the expected events.
  • Monitor Event Processing: Use Axon Server’s dashboard or Spring Actuator metrics to track event latency and failures.

内容的提问来源于stack exchange,提问作者Mavlarn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:38:03