Integrasi sederhana RabbitMQ dan Spring Boot

Terjemahan artikel disiapkan sebelum dimulainya kursus "Pengembang Kerangka Kerja Musim Semi" .




Halo semuanya!

Saya ingin berbagi dengan Anda pustaka sumber terbuka yang memfasilitasi integrasi RabbitMQ dengan aplikasi di Spring Boot. Selain itu, perpustakaan ini menawarkan konsep retries baru yang ditingkatkan (dibandingkan dengan pendekatan AMQP Musim Semi standar).
Disederhanakan? Tapi bagaimana caranya?


Konfigurasi otomatis


Misalkan kita ingin menerapkan interaksi (misalnya, menggunakan SSL) dengan RabbitMQ menggunakan Spring AMQP. Kita perlu membuat beberapa kacang-kacangan, seperti ConnectionFactory, RabbitAdmin, RabbitTemplatedan AbstractRabbitListenerContainerFactory.

Tapi bayangkan ada beberapa host virtual di RabbitMQ. Secara default, di Spring AMQP, Anda perlu membuat ekosistem seperti itu untuk setiap host virtual dengan konfigurasi manual RabbitTemplatedan RabbitListener.



Seperti yang Anda lihat, semua konfigurasi ini membutuhkan waktu dan dapat menjadi sakit kepala.

Sadar akan masalah ini, perpustakaan yang diusulkan secara otomatis mengonfigurasi semua kacang ini untuk Anda. Satu-satunya hal yang perlu Anda lakukan adalah menentukan konfigurasi application.properties, dan sihir akan terjadi!
Wow, tapi seperti apa konfigurasi itu application.properties?

Semuanya sangat sederhana. Pertama, ada awalan untuk properti - ini spring.rabbitmq.custom.

Setelah itu, Anda harus menentukan nama acara. Ini adalah bagian yang sangat penting, karena semua pengaturan yang dibuat perpustakaan didasarkan pada nama ini.

Setelah nama acara, Anda dapat menentukan properti dan nilainya. Semua properti dijelaskan dalam dokumentasi .

Jadi, templatnya adalah sebagai berikut: Di bawah ini adalah contoh konfigurasi untuk dua koneksi yang berbeda.

spring.rabbitmq.custom.<YOUR_EVENT>.<PROPERTY>=<VALUE>




spring.rabbitmq.custom.some-event.host=localhost
spring.rabbitmq.custom.some-event.port=5672
spring.rabbitmq.custom.some-event.ttlRetryMessage=5000
spring.rabbitmq.custom.some-event.maxRetriesAttempts=5
spring.rabbitmq.custom.some-event.ttlMultiply=2
spring.rabbitmq.custom.some-event.queueRoutingKey=ROUTING.KEY.TEST
spring.rabbitmq.custom.some-event.exchange=ex.custom.direct
spring.rabbitmq.custom.some-event.exchangeType=direct
spring.rabbitmq.custom.some-event.queue=queue.custom.test
spring.rabbitmq.custom.some-event.autoCreate=true
spring.rabbitmq.custom.some-event.concurrentConsumers=1
spring.rabbitmq.custom.some-event.maxConcurrentConsumers=1
spring.rabbitmq.custom.some-event.virtualHost=tradeshift
spring.rabbitmq.custom.some-event.primary=true
spring.rabbitmq.custom.some-event.sslConnection=true
spring.rabbitmq.custom.some-event.tlsKeystoreLocation=file:///etc/tradeshift/your-service/tls-keystore.pkcs12
spring.rabbitmq.custom.some-event.tlsKeystorePassword=${RABBITMQ_PASS_CERT}

spring.rabbitmq.custom.another-event.host=localhost
spring.rabbitmq.custom.another-event.port=5672
spring.rabbitmq.custom.another-event.ttlRetryMessage=5000
spring.rabbitmq.custom.another-event.maxRetriesAttempts=5
spring.rabbitmq.custom.another-event.queueRoutingKey=TEST.QUEUE
spring.rabbitmq.custom.another-event.exchange=ex_test_1
spring.rabbitmq.custom.another-event.exchangeType=direct
spring.rabbitmq.custom.another-event.queue=queue_test_1
spring.rabbitmq.custom.another-event.autoCreate=true
spring.rabbitmq.custom.another-event.concurrentConsumers=1
spring.rabbitmq.custom.another-event.maxConcurrentConsumers=1
spring.rabbitmq.custom.another-event.username=guest
spring.rabbitmq.custom.another-event.password=${RABBITMQ_PASS}

Seperti yang Anda lihat, kami belum menulis satu baris kode pun !!!
Bagus, tetapi Anda mengatakan sesuatu tentang strategi replay baru, kan?

Ya kata teman saya!

Tapi sebelum menjelaskan strategi baru ini, mari kita lihat perilaku default RabbitMQ dan Spring AMQP.

Secara default, RabbitMQ tidak menyediakan pemrosesan ulang yang akan memungkinkan Anda untuk mengontrol seluruh siklus hidup pesan.

Misalnya, sebelum RabbitMQ 3.8 , header pesan tidak memiliki properti untuk mengontrol jumlah percobaan yang dilakukan.

Perilaku default RabbitMQ:

  • Jika Anda belum menentukan waktu-untuk-hidup (TTL, seumur hidup), maka RabbitMQ akan terus mencoba untuk mengantri pesan Anda.
  • Jika Anda mendefinisikan TTL tetapi tidak mendefinisikan dlx , maka setelah TTL pesan akan dihapus dari antrian dan Anda akan kehilangan itu.
  • Jika Anda telah menetapkan TTL dan dlx , maka setelah TTL pesan akan dikirim ke exchanger yang didefinisikan dalam dlx.


Perilaku default RabbitMQ

Tetapi bagaimana jika kita menginginkan TTL yang meningkat (misalnya, jika operasi tidak stabil) dan mengontrol jumlah percobaan ulang?

Pertanyaan bagus!

Saatnya untuk menjelaskan cara kerja pustaka Spring AQMP dan Spring Rabbit Tuning!

Coba lagi strategi


Spring AMQP secara default


Saat menggunakan Spring AMQP secara default, Anda dapat menentukan opsi coba lagi menggunakan properti di bawah ini.

Namun pendekatan ini memiliki masalah. Secara default, Spring AMQP akan memblokir antrian Anda ketika Anda mencoba mengirim pesan lagi.

Masalah ini dapat diselesaikan dengan cara memutar: gunakan paralelisme. Tetapi dengan cara ini kita memuat JVM, dan ini bukan pendekatan terbaik. Jika Anda memiliki lima pesan bermasalah (seperti pada contoh), maka kemacetan akan muncul lagi, dan kami masih perlu menentukan kacang secara manual di @Configurationnampan untuk setiap koneksi dan wadah.

spring.rabbitmq.listener.simple.retry.enabled=true
spring.rabbitmq.listener.simple.retry.initial-interval=2000
spring.rabbitmq.listener.simple.retry.max-attempts=5
spring.rabbitmq.listener.simple.retry.multiplier=2
spring.rabbitmq.listener.simple.max-concurrency=5
spring.rabbitmq.listener.simple.concurrency=5


Spring RabbitMQ Tuning


Perpustakaan ini mengambil pendekatan berbeda dengan antrian terpisah untuk mencoba lagi. Dengan cara ini kita dapat mengontrol TTL menggunakan parameter pesan kedaluwarsa, dan parameter x-death untuk mengontrol jumlah coba lagi.
Tapi bagaimana caranya?

Kami menggunakan konsep dlx dalam antrian coba lagi untuk mengirim ulang pesan ke antrian utama. Dengan demikian, kita memiliki akses ke parameter x-death dan secara terprogram kita dapat menentukan umur pesan.

Catatan. Karena perpustakaan ini adalah perpanjangan dari Spring AMQP, Anda dapat menggunakan strategi coba lagi default, dan menggunakan perpustakaan ini hanya untuk konfigurasi otomatis kacang.


Spring RabbitMQ Mencoba Tuning
Bisakah saya menggunakan strategi coba lagi tanpa konfigurasi otomatis? Saya sudah punya banyak kacang, dan saya tidak punya waktu untuk menulis ulang.

Kami tahu bahwa dunia tidak sempurna, dan untuk situasi ini, kami memiliki tanda yang memungkinkan Anda untuk menonaktifkan konfigurasi otomatis dan hanya menggunakan pendekatan kami untuk pemrosesan berulang dan keuntungan lainnya, seperti manajemen tempat sampah.

Anda dapat menonaktifkan konfigurasi otomatis menggunakan properti berikut:

spring.rabbitmq.enable.custom.autoconfiguration=false

Tetapi saya memiliki dua koneksi yang berbeda, apa yang harus saya lakukan dalam kasus ini?

Jika Anda memiliki lebih dari satu koneksi dan Anda ingin menonaktifkan konfigurasi otomatis, maka Anda perlu menentukan nama bean RabbitTemplateuntuk setiap koneksi. Ini dijelaskan di sini . Anda masih dapat menggunakan kacang kami untuk membuat bekerja dengan Spring AMQP lebih mudah.

spring.rabbitmq.custom.<YOUR_EVENT>.rabbitTemplateBeanName= <RABBITTEMPLATE_BEAN_NAME>

RabbitTemplateHandler
Sangat baik! Jadi, saya ingin menggunakan ini. Bagaimana saya bisa melakukan ini? Apakah Anda memiliki contoh atau dokumentasi?
Iya!

Kami memiliki contoh proyek di repositori ini , di mana Anda dapat melihat cara menggunakan perpustakaan ini untuk penerbit dan pelanggan.

Tapi itu sangat sederhana sehingga saya akan memberi contoh di sini!

Penerbit


Ada kelas di perpustakaan RabbitTemplateHandlerdan sangat mudah digunakan. Anda perlu memanggil metode getRabbitTemplatedan mengirimkan host virtual sebagai parameter untuk mendapatkan kacang RabbitTemplate. Setelah itu, Anda dapat memanggil metode convertAndSend dan meneruskannya dalam parameter kunci pertukaran dan perutean.

Catatan : kunci pertukaran dan perutean dapat diperoleh dengan menggunakan anotasiNilai.

Contoh :

@Value("${spring.rabbitmq.custom.some-event.exchange}")
private String exchangeSomeEvent;

@Value("${spring.rabbitmq.custom.some-event.queueRoutingKey}")
private String routingKeySomeEvent;

@Autowired
private final RabbitTemplateHandler rabbitTemplateHandler;

public void sendMessage(final String message) {
   rabbitTemplateHandler.getRabbitTemplate("some-event").convertAndSend(exchangeSomeEvent, routingKeySomeEvent, message);
}

Pelanggan


Pelanggan juga sangat sederhana. Satu-satunya hal yang perlu Anda lakukan adalah menambahkan anotasi ke metode RabbitListener(Spring AMQP annotation secara default) dan berikan nama containerFactory.
Bagaimana cara mengetahui nama containerFactory yang benar untuk host virtual?

Anda tidak perlu mengetahuinya, cukup berikan nama acara tersebut, dan perpustakaan akan melakukan semua keajaiban untuk Anda! Perpustakaan ini juga memiliki kemampuan untuk memasukkan retries dan dlq, yang direkomendasikan.

Menyalakannya sangat sederhana. Anda perlu menambahkan anotasi ke metode EnableRabbitRetryAndDlqdan meneruskan nama properti sebagai argumen.

Catatan : Anda juga bisa menentukan pengecualian mana yang harus ditangani dengan percobaan ulang dan dlq. Ini diproses secara default Exception.class, yang berarti menangani semua pengecualian.

Contoh:

@RabbitListener(containerFactory = "some-event", queues = "${spring.rabbitmq.custom.some-event.queue}")
@EnableRabbitRetryAndDlq(event = "some-event", exceptions = { IllegalArgumentException.class, RuntimeException.class })
public void onMessage(Message message) {
   ...
}

Itu semua! Saya harap Anda menikmati perpustakaan ini sebanyak yang kami lakukan!

Dan, yang paling penting: jangan ragu untuk berkontribusi atau mengirim umpan balik!

Terima kasih khusus untuk


Andre Luis Gomes
Rogerio Bueno
Leonardo Ferreira



Mendaftar untuk pelajaran gratis.


All Articles