Rumah > Java > javaTutorial > Analisis masalah biasa dan penyelesaian baris gilir mesej Java RabbitMQ

Analisis masalah biasa dan penyelesaian baris gilir mesej Java RabbitMQ

王林
Lepaskan: 2023-04-23 09:49:06
ke hadapan
2220 orang telah melayarinya

Pengumpulan mesej

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.

Pastikan mesej tidak hilang

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 surat mati

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>
Salin selepas log masuk

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
Salin selepas log masuk

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);
    }
}
Salin selepas log masuk

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);
    }
}
Salin selepas log masuk

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);
    }
}
Salin selepas log masuk

Halaman pengurusan baris gilir latar belakang adalah seperti berikut:

Analisis masalah biasa dan penyelesaian baris gilir mesej Java RabbitMQ

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.

Barisan Kelewatan

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.

Analisis masalah biasa dan penyelesaian baris gilir mesej Java RabbitMQ

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.

Masalah mati pucuk mesej RabbitMQ

Mekanisme cuba semula automatik mesej RabbitMQ

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.

Pilihan munasabah mekanisme cuba semula

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.

Pengguna menghidupkan mod ack manual

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);
}
Salin selepas log masuk

Bagaimanakah rabbitMQ menyelesaikan masalah mati pucuk mesej

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:

Analisis masalah biasa dan penyelesaian baris gilir mesej Java RabbitMQ

RabbitMQ menyelesaikan masalah transaksi teragih

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

Idea menyelesaikan transaksi teragih berdasarkan RabbitMQ: (Mengguna pakai penyelesaian ketekalan akhir)

    Sahkan Mesej pengeluar kami mesti dihantar ke MQ (mekanisme pengesahan mesej Jika penghantaran gagal, teruskan mencuba
  • Pengguna menggunakan ack manual untuk mengesahkan mesej untuk mencapai penggunaan perhatian kepada isu idempoten , apabila penggunaan gagal, mq secara automatik membantu pengguna mencuba semula.
  • Pastikan transaksi pertama pengeluar kami dilaksanakan terlebih dahulu Jika pelaksanaan gagal, gunakan baris gilir pesanan tambahan (tambah transaksi pengeluar sendiri untuk memastikan transaksi pertama pengeluar selesai [data adalah. akhirnya konsisten] seks】).
  • Peta penyelesaian: Intinya ialah menggunakan mq untuk menghantar mesej kepada sistem lain untuk mengubah suai data kembali.

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!

Label berkaitan:
sumber:yisu.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan