Panduan Lengkap Spring Boot 4 · Pelajaran

Penerbitan Peristiwa Transaksi dan Peti Keluar

Jamin penghantaran peristiwa dengan daftar penerbitan peristiwa dan corak peti keluar transaksi.

Pelajaran 3 daripada 413 langkah

Penerbitan Peristiwa Transaksi dan Peti Keluar ialah pelajaran Panduan Lengkap Spring Boot 4 percuma di CoddyKit. Ini ialah pelajaran 3 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Panduan Lengkap Spring Boot 4, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Panduan Lengkap Spring Boot 4 merangkumi sejumlah 4 pelajaran.

Sebab Acara Hilang

Dalam aplikasi Spring Modulith dipacu acara, modul berkomunikasi antara satu sama lain dengan menerbitkan acara aplikasi. Sesuatu modul mencetuskan acara dalam transaksi, kemudian pendengar dalam modul lain bertindak balas terhadapnya.

Risikonya: secara lalai, apabila anda menerbitkan acara dan pendengar memprosesnya secara tak segerak (atau dalam transaksi berasingan), kerja pendengar boleh gagal selepas penerbit sudah melakukan komit. Hasilnya ialah acara yang hilang — keadaan penerbit berubah, tetapi kesan sampingan hiliran tidak pernah berlaku.

  • Penerbit melakukan komit terhadap Order sebagai PAID.
  • Pendengar tak segerak yang menghantar e-mel pengesahan mengalami ranap.
  • Tiada sesiapa mencuba semula — pelanggan tidak pernah menerima e-mel itu.

Pelajaran ini menunjukkan cara Event Publication Registry Spring Modulith melaksanakan corak peti keluar transaksional untuk menjamin penghantaran.

Corak Peti Keluar Transaksional

Corak peti keluar transaksional menyelesaikan masalah dua penulisan: anda mesti secara atomik (1) mengubah keadaan perniagaan dan (2) merekodkan bahawa sesuatu acara perlu dihantar.

Daripada cuba menulis ke pangkalan data dan perantara mesej dalam satu transaksi (mustahil tanpa transaksi teragih), anda menulis kedua-duanya ke dalam pangkalan data yang sama dalam transaksi setempat yang sama:

  • Perubahan perniagaan (contohnya baris pesanan).
  • Satu baris dalam jadual peti keluar yang menerangkan acara itu.

Proses berasingan kemudiannya membaca baris peti keluar yang belum diproses dan menghantarnya, sambil menandakan setiap satunya sebagai selesai. Oleh sebab penulisan peti keluar berkongsi transaksi perniagaan, sesuatu acara direkodkan jika dan hanya jika perubahan perniagaan berjaya dikomit.

Event Publication Registry Spring Modulith

Spring Modulith disertakan dengan peti keluar yang sedia digunakan: Event Publication Registry. Apabila sesuatu acara mempunyai pendengar transaksional (dianotasi dengan @ApplicationModuleListener), Modulith secara automatik:

  • Menulis baris pengeluaran acara sebelum pendengar berjalan.
  • Menandainya sebagai selesai apabila pendengar selesai dengan jayanya.
  • Membiarkannya belum selesai jika pendengar menghasilkan pengecualian — supaya acara itu boleh dicuba semula.

Anda mendayakannya dengan menambahkan pemula dan modul kegigihan. Pendaftaran itu menyimpan pengeluaran dalam jadual seperti event_publication.

<dependency>
  <groupId>org.springframework.modulith</groupId>
  <artifactId>spring-modulith-starter-jpa</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.modulith</groupId>
  <artifactId>spring-modulith-events-jpa</artifactId>
</dependency>

@ApplicationModuleListener

Anotasi utama ialah @ApplicationModuleListener. Ia ialah anotasi gubahan yang menggabungkan tiga tingkah laku:

  • @Async — pendengar berjalan pada utas berasingan, lalu mengasingkan modul.
  • @Transactional(propagation = REQUIRES_NEW) — pendengar berjalan dalam transaksinya sendiri.
  • @TransactionalEventListener(phase = AFTER_COMMIT) — ia dicetuskan hanya selepas transaksi penerbit dikomit.

Apabila digabungkan dengan pendaftaran pada laluan kelas, setiap acara yang dikendalikan oleh pendengar sedemikian mendapat entri peti keluar. Jika pendengar gagal, pengeluaran kekal belum selesai dan bertahan selepas aplikasi dimulakan semula.

@Component
class OrderNotifications {

    @ApplicationModuleListener
    void on(OrderCompleted event) {
        // runs async, in a NEW transaction, after the publisher committed
        emailService.sendConfirmation(event.orderId());
    }
}

Menerbitkan Acara

Bahagian penerbitan kekal mudah. Dalam kaedah perkhidmatan biasa @Transactional, anda memanggil ApplicationEventPublisher.publishEvent(...). Spring Modulith memintas penerbitan itu dan, kerana terdapat pendengar modul transaksional, menulis baris peti keluar dalam transaksi yang sama dengan perubahan perniagaan anda.

Gunakan rekod Java yang tidak berubah untuk acara — rekod ini ringkas, boleh disiri dan jelas ditaip sebagai nilai.

public record OrderCompleted(String orderId) {}

@Service
class OrderService {

    private final OrderRepository orders;
    private final ApplicationEventPublisher events;

    OrderService(OrderRepository orders, ApplicationEventPublisher events) {
        this.orders = orders;
        this.events = events;
    }

    @Transactional
    public void complete(String orderId) {
        Order order = orders.findById(orderId).orElseThrow();
        order.markCompleted();          // business change
        events.publishEvent(new OrderCompleted(orderId)); // outbox row, same tx
    }
}

Cara Keatomikan Berfungsi

Berikut ialah urutan penting yang menjamin penghantaran:

  • Kaedah complete() anda membuka transaksi dan mengubah pesanan.
  • publishEvent menyebabkan Modulith memasukkan baris event_publication yang belum selesai dalam transaksi yang sama.
  • Transaksi dikomit — perubahan pesanan dan baris peti keluar disimpan bersama secara atomik.
  • Selepas komit, @ApplicationModuleListener berjalan dalam transaksi baharu.
  • Apabila berjaya, pengeluaran ditandakan sebagai selesai.

Jika JVM ranap antara komit dengan kejayaan pendengar, baris itu masih belum selesai dalam pangkalan data dan sedia untuk diterbitkan semula. Tiada acara yang tercicir secara senyap.

Jadual event_publication

Modul kegigihan JPA menyimpan pengeluaran dalam sebuah jadual. Setiap baris mengenal pasti acara bersiri dan pendengar sasarannya, bersama cap masa. Mengetahui skema ini membantu anda memahami percubaan semula dan pemantauan.

  • id — kunci utama UUID.
  • listener_id — kaedah pendengar yang layak sepenuhnya dan mesti mengendalikannya.
  • event_type + serialized_event — muatan acara (JSON secara lalai melalui Jackson).
  • publication_date — masa ia dicipta.
  • completion_date — NULL selagi belum selesai; ditetapkan apabila pendengar berjaya.

Baris dengan completion_date IS NULL ialah acara tertunggak yang menunggu penghantaran semula.

CREATE TABLE event_publication (
  id UUID NOT NULL,
  listener_id TEXT NOT NULL,
  event_type TEXT NOT NULL,
  serialized_event TEXT NOT NULL,
  publication_date TIMESTAMP WITH TIME ZONE NOT NULL,
  completion_date TIMESTAMP WITH TIME ZONE,
  PRIMARY KEY (id)
);

Menerbitkan Semula Semasa Dimulakan

Pengeluaran yang belum selesai tidak berguna melainkan ada sesuatu yang mencubanya semula. Spring Modulith boleh menerbitkan semula acara tertunggak semasa aplikasi dimulakan, sekali gus memulihkan keadaan selepas ranap yang berlaku ketika penghantaran sedang berlangsung.

Dayakannya dalam application.properties:

  • spring.modulith.republish-outstanding-events-on-restart=true

Semasa dimulakan, Modulith membaca semua baris event_publication yang belum selesai dan memanggil semula pendengarnya. Oleh sebab pendengar sepatutnya idempoten, memainkan semula acara yang diproses sebahagiannya adalah selamat.

# application.properties
spring.modulith.republish-outstanding-events-on-restart=true

# optional: also serialize events as JSON columns you can query
spring.modulith.events.jdbc.schema-initialization.enabled=true

Pendengar Idempoten

Oleh sebab sesuatu acara mungkin dihantar lebih daripada sekali (percubaan semula selepas ranap atau penghantaran semula berjadual), jaminan sekurang-kurangnya sekali memerlukan pendengar anda bersifat idempoten. Memproses acara yang sama dua kali mesti menghasilkan keadaan akhir yang sama seperti memprosesnya sekali.

Teknik biasa:

  • Gunakan kunci perniagaan semula jadi (id pesanan) dan semak sama ada kesan sampingan itu sudah berlaku.
  • Jejaki id acara yang telah diproses dalam jadual deduplikasi dengan kekangan unik.
  • Jadikan operasi itu sememangnya idempoten (UPSERT atau tetapkan kepada keadaan tertentu, bukannya menambah nilai).
@Component
class InventoryAdjuster {

    private final ProcessedEventRepository processed;

    @ApplicationModuleListener
    void on(OrderCompleted event) {
        // skip if we've already handled this exact event
        if (!processed.markIfNew(event.orderId())) {
            return;
        }
        inventory.release(event.orderId());
    }
}

Penghantaran Semula Acara Belum Selesai Secara Berjadual

Penerbitan semula semasa dimulakan hanya membantu apabila anda memulakan semula aplikasi. Untuk perkhidmatan yang berjalan lama, anda juga memerlukan pemulihan berkala bagi pengeluaran yang tersekat (contohnya pendengar yang menghasilkan ralat sementara). Modulith menyediakan penjadual penyelesaian / penghantaran semula.

  • spring.modulith.events.completion-mode — mengawal sama ada baris yang selesai dipadamkan, diarkibkan atau dikemas kini.
  • Dayakan penghantaran semula berkala supaya acara yang belum selesai dan lebih lama daripada ambang dicuba semula secara automatik.

Digabungkan dengan keidempotenan, ini menjadikan peti keluar sebagai saluran penghantaran yang memulihkan dirinya sendiri tanpa perantara mesej berasingan.

# application.properties
spring.modulith.events.republish-outstanding-events-on-restart=true
spring.modulith.events.completion-mode=update

# resubmit publications still incomplete after this interval
spring.modulith.events.republish-outstanding-events.interval=PT10M

Daripada Peti Keluar kepada Perantara Luaran

Pendaftaran yang sama boleh menghubungkan kepada pemesejan luaran. Spring Modulith menyediakan modul pengeluaran luaran (Kafka, RabbitMQ, AMQP, SQS dan sebagainya). Anda menganotasi acara dengan @Externalized, kemudian pendengar transaksional menerbitkannya kepada perantara — disokong oleh peti keluar yang sama.

Ini bermakna jaminan sekurang-kurangnya sekali melangkaui sempadan proses: penghantaran kepada perantara itu sendiri ialah pengeluaran acara yang hanya ditandakan selesai selepas mesej diterima oleh perantara.

import org.springframework.modulith.events.Externalized;

@Externalized("orders.completed::#{orderId()}")
public record OrderCompleted(String orderId) {}

// add: spring-modulith-events-kafka
// spring.modulith routes the event to topic "orders.completed"
// keyed by orderId, only after the publishing tx commits

Semakan Pantas

Uji pemahaman anda tentang jaminan peti keluar transaksional.

Imbas Kembali

Anda telah mempelajari cara menjamin penghantaran peristiwa dalam Spring Modulith menggunakan corak transactional outbox:

  • Event Publication Registry menyimpan baris event_publication dalam transaksi yang sama dengan perubahan perniagaan anda — sekali gus menyelesaikan masalah penulisan berganda.
  • @ApplicationModuleListener = async + transaksi REQUIRES_NEW + AFTER_COMMIT, jadi pendengar berjalan selepas penerbit membuat commit dan menerima entri outboxnya sendiri.
  • Sesuatu penerbitan dianggap belum lengkap sehingga pendengarnya berjaya (completion_date IS NULL); kegagalan akan membiarkannya untuk dicuba semula.
  • Penerbitan semula apabila dimulakan semula dan penyerahan semula berjadual memulihkan peristiwa yang tersekat — lalu menjadikan penghantaran sekurang-kurangnya sekali.
  • Oleh sebab penghantaran berlaku sekurang-kurangnya sekali, pendengar mestilah idempoten.
  • @Externalized menghubungkan outbox yang sama kepada Kafka/RabbitMQ/SQS untuk jaminan merentas proses.
Percuma untuk bermula

Pelajari Java dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
21
Pelajaran
84

Soalan Lazim

Adakah pelajaran “Penerbitan Peristiwa Transaksi dan Peti Keluar” percuma?

Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Panduan Lengkap Spring Boot 4, termasuk “Penerbitan Peristiwa Transaksi dan Peti Keluar”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Panduan Lengkap Spring Boot 4 merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Penerbitan Peristiwa Transaksi dan Peti Keluar”?

Jamin penghantaran peristiwa dengan daftar penerbitan peristiwa dan corak peti keluar transaksi. Anda berlatih Panduan Lengkap Spring Boot 4 menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Panduan Lengkap Spring Boot 4?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Panduan Lengkap Spring Boot 4 di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 3 daripada 4.

Berapa lamakah pelajaran “Penerbitan Peristiwa Transaksi dan Peti Keluar” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Panduan Lengkap Spring Boot 4 ini?

Ya. Setiap pelajaran Panduan Lengkap Spring Boot 4 menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Modul Aplikasi dan Pengesahan Sempadan
  2. Peristiwa Aplikasi Dalaman dan Pendengar
  3. Penerbitan Peristiwa Transaksi dan Peti Keluar
  4. Ujian Integrasi Modul Aplikasi dan Senario
← Kembali ke Panduan Lengkap Spring Boot 4