Senario penjanaan pengumpulan mesej:
Kelajuan mesej yang dijana oleh pengeluar lebih besar daripada kelajuan penggunaan oleh pengguna. Penyelesaian: Tingkatkan bilangan atau kelajuan pengguna.
Apabila tiada pengguna yang mengambil. Penyelesaian: Baris gilir surat mati, tetapkan tempoh sah mesej. Ia bersamaan dengan menetapkan tempoh sah untuk mesej kami Jika tiada penggunaan dalam masa yang ditetapkan, ia akan tamat tempoh secara automatik Apabila ia tamat, kaedah pemantauan panggilan balik pelanggan akan dilaksanakan untuk menyimpan mesej dalam rekod jadual pangkalan data. pampasan akan direalisasikan kemudian.
1. Penerbit menggunakan mekanisme pengesahan mesej untuk memastikan mesej dapat dihantar ke MQ dengan jayanya.
2. Pelayan MQ harus meneruskan mesej ke cakera keras
3 Pengguna menggunakan mekanisme ack manual untuk mengesahkan bahawa penggunaan mesej berjaya
Apa yang perlu. lakukan jika kapasiti pelayan MQ penuh?
Gunakan baris gilir huruf mati untuk menyimpan mesej dalam pangkalan data dan mengimbangi penggunaan kemudian.
Baris gilir huruf mati RabbitMQ biasanya dikenali sebagai baris gilir tayar ganti; selepas perisian tengah mesej menolak mesej atas sebab tertentu, ia boleh dipindahkan ke baris gilir huruf mati untuk penyimpanan , baris gilir huruf mati Terdapat juga suis dan kekunci penghalaan, dsb.
Latar belakang generasi:
Mesej yang dihantar ke MQ dan disimpan dalam MQ telah tamat tempoh
Baris gilir telah mencapai maksimum panjang (bekas baris gilir Sudah penuh) Pengeluar enggan menerima mesej
Jika pengguna gagal menggunakan berbilang mesej, ia akan dipindahkan ke baris gilir huruf mati
Contoh kod:
kebergantungan maven
<dependencies> <!-- springboot-web组件 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 添加springboot对amqp的支持 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <!--fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.49</version> </dependency> </dependencies>
konfigurasi yml
server: # 服务启动端口配置 port: 8081 servlet: # 应用访问路径 context-path: / spring: #增加application.druid.yml 的配置文件 # profiles: # active: rabbitmq rabbitmq: ####连接地址 host: www.kaicostudy.com ####端口号 port: 5672 ####账号 username: kaico ####密码 password: kaico ### 地址 virtual-host: /kaicoStudy ###模拟演示死信队列 kaico: dlx: exchange: kaico_order_dlx_exchange queue: kaico_order_dlx_queue routingKey: kaico.order.dlx ###备胎交换机 order: exchange: kaico_order_exchange queue: kaico_order_queue routingKey: kaico.order
Kelas konfigurasi baris gilir
@Configuration public class DeadLetterMQConfig { /** * 订单交换机 */ @Value("${kaico.order.exchange}") private String orderExchange; /** * 订单队列 */ @Value("${kaico.order.queue}") private String orderQueue; /** * 订单路由key */ @Value("${kaico.order.routingKey}") private String orderRoutingKey; /** * 死信交换机 */ @Value("${kaico.dlx.exchange}") private String dlxExchange; /** * 死信队列 */ @Value("${kaico.dlx.queue}") private String dlxQueue; /** * 死信路由 */ @Value("${kaico.dlx.routingKey}") private String dlxRoutingKey; /** * 声明死信交换机 * * @return DirectExchange */ @Bean public DirectExchange dlxExchange() { return new DirectExchange(dlxExchange); } /** * 声明死信队列 * * @return Queue */ @Bean public Queue dlxQueue() { return new Queue(dlxQueue); } /** * 声明订单业务交换机 * * @return DirectExchange */ @Bean public DirectExchange orderExchange() { return new DirectExchange(orderExchange); } /** * 绑定死信队列到死信交换机 * * @return Binding */ @Bean public Binding binding() { return BindingBuilder.bind(dlxQueue()) .to(dlxExchange()) .with(dlxRoutingKey); } /** * 声明订单队列,并且绑定死信队列 * * @return Queue */ @Bean public Queue orderQueue() { // 订单队列绑定我们的死信交换机 Map<String, Object> arguments = new HashMap<>(2); arguments.put("x-dead-letter-exchange", dlxExchange); arguments.put("x-dead-letter-routing-key", dlxRoutingKey); return new Queue(orderQueue, true, false, false, arguments); } /** * 绑定订单队列到订单交换机 * * @return Binding */ @Bean public Binding orderBinding() { return BindingBuilder.bind(orderQueue()) .to(orderExchange()) .with(orderRoutingKey); } }
Mati pengguna baris gilir surat
@Component public class OrderDlxConsumer { /** * 死信队列监听队列回调的方法 * @param msg */ @RabbitListener(queues = "kaico_order_dlx_queue") public void orderDlxConsumer(String msg) { System.out.println("死信队列消费订单消息" + msg); } }
Pengguna baris gilir biasa
@Component public class OrderConsumer { /** * 监听队列回调的方法 * * @param msg */ @RabbitListener(queues = "kaico_order_queue") public void orderConsumer(String msg) { System.out.println("正常订单消费者消息msg:" + msg); } }
Halaman pengurusan baris gilir latar belakang adalah seperti berikut:
Kaedah penggunaan : Barisan gilir huruf mati tidak boleh digabungkan dengan baris gilir biasa wujud dalam pelayan yang sama dan harus disimpan dalam pelayan yang berasingan.
Pelan pelaksanaan untuk sistem tamat masa secara automatik dan ditutup jika pesanan tidak dibayar selama 30 minit.
Berdasarkan penjadualan tugas, kecekapan adalah sangat rendah.
Dilaksanakan berdasarkan kunci tamat tempoh redis Apabila kunci tamat tempoh, kaedah akan dipanggil semula kepada klien.
Apabila pengguna membuat pesanan, token (tempoh sah) dijana selama 30 minit dan disimpan dalam redis kami;
Baris gilir kelewatan berasaskan MQ (penyelesaian terbaik) kes rabbitmq.
Prinsip: Apabila kami membuat pesanan, kami menghantar mesej kepada mq dan menetapkan tempoh sah kepada 30 minit Tetapi apabila mesej tersebut tamat tempoh (tanpa digunakan), laksanakan kaedah pada pelanggan kami untuk memberitahu kami Mesej telah tamat tempoh Pada masa ini, semak sama ada pesanan telah dibayar.
Logik pelaksanaan:
Terutamanya digunakan baris gilir huruf mati untuk dilaksanakan.
Kod yang anda inginkan: pengguna biasa tidak menggunakan mesej, atau tiada pengguna biasa, masukkan baris gilir surat mati selepas masa yang ditetapkan, dan kemudian pengguna laksanakan logik perniagaan yang sepadan.
Apabila pengecualian dilemparkan dalam kod logik perniagaan pengguna, percubaan semula dilaksanakan secara automatik (lalai ialah percubaan semula yang tidak terkira banyaknya) Cuba)
Had hendaklah dilaksanakan pada bilangan percubaan semula RabbitMQ, seperti maksimum 5 percubaan semula, dengan selang 3 saat setiap kali; jika mencuba semula beberapa kali masih gagal, simpannya dalam baris gilir huruf mati atau simpan dalam jadual pangkalan data Rekodkan pampasan buruh kemudian. Kerana selepas bilangan percubaan semula yang gagal, baris gilir akan memadam mesej secara automatik.
Prinsip percubaan semula mesej: Semasa proses cuba semula, gunakan aop untuk memintas kaedah mendengar penggunaan kami dan log ralat ini tidak akan dicetak. Jika ia gagal selepas mencuba semula beberapa kali, log ralat akan dicetak hanya apabila bilangan kegagalan maksimum dicapai.
Jika penggunaan gagal beberapa kali:
1 Padamkan mesej secara automatik; (mesej mungkin hilang)
Penyelesaian:
Jika pengayaan gagal. beberapa kali, ia akhirnya akan disimpan dalam baris gilir huruf mati;
menggunakan pengelogan jadual untuk merekodkan log ralat kegagalan penggunaan, dan akan mengimbangi mesej secara automatik kemudian secara manual.
Selepas pengguna memperoleh mesej, ia memanggil antara muka pihak ketiga (permintaan HTTP), tetapi bagaimana jika panggilan ke antara muka pihak ketiga gagal? Perlu mencuba lagi?
Jawapan: Kadangkala panggilan gagal disebabkan oleh pengecualian rangkaian dan ia mungkin perlu dicuba semula beberapa kali.
Selepas pengguna memperoleh mesej, pengecualian data dilemparkan kerana masalah kod. Adakah ia perlu dicuba semula?
Jawapan: Tidak perlu mencuba semula Jika kod tidak normal, projek keluaran kod perlu diubah suai lagi.
Langkah pertama, konfigurasi projek springboot perlu menghidupkan mod ack
mod acknowledge: manual
Langkah kedua, kod Java pengguna
int result = orderMapper.addOrder(orderEntity); if (result >= 0) { // 开启消息确认机制 channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); }
Apakah itu mati pucuk mesej? Bagaimanakah pengguna MQ memastikan mati pucuk?
Sebabnya: Pengguna mungkin menghidupkan percubaan semula automatik dan proses percubaan semula boleh menyebabkan kod logik perniagaan pengguna dilaksanakan berulang kali. Pada masa ini, mesej telah digunakan Kerana ralat perniagaan menyebabkan mesej digunakan semula,
akan muncul pada masa ini: Gunakan id global mesej untuk menentukan mengikut perniagaan boleh menilai mesej ini berdasarkan id perniagaan (id unik global Mesej telah digunakan).
Logik kod pengguna:
Transaksi teragih: Dalam sistem teragih, kerana di seluruh Terdapat berbilang transaksi yang berbeza dalam antara muka panggilan perkhidmatan, dan setiap transaksi tidak menjejaskan satu sama lain. Terdapat masalah transaksi yang diedarkan.
Menyelesaikan idea teras urus niaga yang diedarkan: ketekalan akhir data.
Kata nama dalam medan yang diedarkan:
Konsistensi yang kuat: sama ada kelajuan penyegerakan sangat pantas atau mekanisme kunci tidak membenarkan bacaan yang kotor; A menyegerakkan data kepada data B dengan sangat cepat, atau pangkalan data B tidak boleh membaca data sebelum penyegerakan pangkalan data A selesai.
Konsistensi yang lemah: Data yang dibenarkan dibaca ialah data asli yang kotor, dan keputusan yang dibaca dibenarkan tidak konsisten.
Ketekalan akhirnya: Dalam sistem edaran kami, kerana data dikomunikasikan secara serentak melalui rangkaian, kelewatan data pendek dibenarkan, tetapi data akhir mestilah konsisten.
Idea menyelesaikan transaksi teragih berdasarkan RabbitMQ
Atas ialah kandungan terperinci Analisis masalah biasa dan penyelesaian baris gilir mesej Java RabbitMQ. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!