【RabbitMQ】@RabbitListenerの使用と誤報死サイクルの解析


問題の再現:dockerで対応するキュー情報をクリア
exec rabbitmq /bin/bash #rabbitmq    ,      Id
rabbitmqctl purge_queue queue.order # queue.order    
RabbitMQ 、消費者の消費を待つhttp://localhost:15672 【RabbitMQ】@RabbitListener的使用及造成报错死循环的分析_第1张图片
先行知識:
一、@RabbitListenerの使用
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-amqpartifactId>
        dependency>

1.1方法に作用する
キュー名を指定し、複数の @RabbitListenerを使用して、複数の消費実装をバインドできます.
  • 指定キューの消費方法一般用法
    @RabbitListener(queues = "queue.order")
    public void handleMsg(String msg) {
           
    }
    
  • 1.2クラスに作用する
    指定キュー名、 @RabbitListener指定キュー名を配置します.@RabbitHandlerクラス内の複数の にバインドされ、キュー名の複数の消費実装とみなされる
  • @RabbitHandler
    @RabbitListener(queues = "queue.order")
    public class PayOrderUpdateListener {
           
    	//           
    	@RabbitHandler
    	public void handlerMsg(String msg) {
           
    	}
    }
    
  • に協力する必要がある.
  • 注記オプションパラメータ:@RabbitListener(isDefault = true)、このパラメータは注意に値する
    @RabbitHandler(queues = "queue.order", isDefault = true)
    public void handleMsg(String msg) {
           
    }
    
  • 二、メッセージのカプセル化クラスMessage、及び解析規則
    @RabbitHandler(queues = "queue.order")
    public void handleMsg(Message msg) {
         
    }
    
  • キー属性content_type bodyコンテンツ
  • を拘束する
  • http://localhost:15672RabbitMQのコンソール
  • メッセージの設定content_type 【RabbitMQ】@RabbitListener的使用及造成报错死循环的分析_第2张图片
  • content_typeの一般的な値
  • content_type
    handlerの受信可能パラメータ
    text/plain
    String
    application/json
    /
    application/x-java-serialized-object
    エンティティークラス
    application/octet-stream
    byte[]
    指定されていません
    byte[]
    指定されていません
    org.springframework.amqp.core.Message content_typeが指定されていない場合はbyte[]で受信できますが、Messageは可能なすべてのシーケンス化シーンを受信するために使用でき、エラーは報告されません.
    例外キャプチャ
    まず誤りを分析してからデッドサイクルを分析する
    【異常1】:No method found for class
    【RabbitMQ】@RabbitListener的使用及造成报错死循环的分析_第3张图片とは、 が消費の準備をしており、キューにメッセージが存在するが、指定された消費実現方法が見つからないことを意味する.
    異常1問題:なぜ消費実現が見つからないのか.
  • @RabbitListenerまたは@RabbitHandlerの構成エラーは、content_typeの構成および方法に依存する に起因する.クライアントを介してキューにcontent_が挿入された場合typeが空のメッセージ,@RabbitListenerはStringのHandlerとして形参のみであり,上消費に対応して実現することはできない.
  • @RabbitHandlerオプションパラメータisDefaultを使用していない消費者は、消費実装が見つからない場合は、isDefault = truehandlerを探して、ポケット戦略に似ています.

  • 異常1問題:処理構想
  • 方法パラメータとしてMessageを用いる
  • .
  • できるだけ@RabbitListenerをクラスに置いて、@RabbitHandler(isDefault = true)を使ってポケット戦略
  • をします.
    異常1分析:デッドサイクル分析
    これはアプリケーションレベルのデッドサイクルであり、メッセージは消費実装が見つからず、消費実装が見つかるまで再試行されます.このようなデッドサイクルの原因は配置ミスであり,ソースで避けるにはテスト段階で消滅しなければならない.【このようなデッドサイクルを解消する方法を見つけて穴を埋める】.もう1つの処理しなければならない死の循環はすでに消費の実現を見つけたが、消費の過程で死の循環をもたらし、異常2を見た.
    【異常2】消費中に未キャプチャExceptionを投げ出す
    通常、ビジネスロジックによる異常はNullPointerException、脳のないやり方はtry-catchであり、処理が適切でないと死の循環をもたらす.
    異常2問題:try-catch以降もデッドサイクル
    詳細な分析ここでは、RabbitMQのデフォルトの例外ポリシーは であり、fatalのタイプの例外が投げ出されない限り、この例外タイプは次のようになります.
    例外クラス
    MessageConversionException
    MessageConversionException
    MethodArgumentNotValidException
    MethodArgumentTypeMismatchException
    NoSuchMethodException
    ClassCastException NullPointerExceptionと同様に、再試行の範囲を放棄しない、すなわち、アクティブにキャプチャして処理しない、RabbitMQはメッセージを消費しようと試み続け、デッドサイクルを招き、大量のCPUリソースを占有する.
    異常2処理:デッドサイクル終了
    最も簡単な方法は、catch文ブロックにfatal型の異常を投げ出すことである.
        @RabbitHandler
        public void handlerMsg(String msg) {
         
            try {
          // try            
                //1.       map
                Map<String, String> map = JSON.parseObject(msg, Map.class);
                String out_trade_no = map.get("out_trade_no");
                if (map != null && map.get("return_code").equalsIgnoreCase("SUCCESS")) {
         
                }
            } catch (Exception e) {
         
                e.printStackTrace();
                // todo             bug                   
                throw new MessageConversionException("      ,      ,    ");
            }
        }
    

    より堅牢な方法:異常プロセッサ+デッドラインキューを使用してネット上の資料を参照し、比較的包括的です.
    ソリューション
  • 試験段階暴力放出fatal異常、死循環停止
  • 線上不暴力放出fatal異常、先に再試行回数を設定し、詳細パラメータ
  • は再試行回数を超え、メッセージをデッドメッセージキューに追加するか、dbに永続化し、メッセージキューから
  • を一時的に除去する.
  • 失敗したメッセージに基づいてアラートを行い、 APIまたは他の方法で手動介入
  • をトリガする.
    リファレンス
    RabbitMQの用語とパラメータ構成@RabbitListener詳細@RabbitListener詳細,@Payload,@headers MessageConvertシーケンス化関連Spring Boot 2.0でのRabbitMQの異常処理