概要
Neteaseで面接をしていたとき、インタビュアーは私に質問をして言った
注文した後、ユーザーが支払いをせず、注文をキャンセルする必要がある場合、私は何ができますか?
当時の私の答えは、DBテーブルをスキャンするためにタイムされたタスクを使用することでした。インタビュアーはあまり満足しておらず、尋ねました:
タイミングのあるタスクを使用して正確なリアルタイム通知を実現する他の方法はありますか?
当時の私の答えは次のとおりです。
キューを使用できます。注文が行われた後、メッセージがキューに送信され、有効期限が指定されます。時間が届くと、コールバックインターフェイスが実行されます。
インタビュアーが聞いた後、彼は尋ねるのをやめました。実際、私のアイデアはその時でしたが、私はあまり専門的ではありませんでした。専門的なことわざは、遅延メッセージを使用することです。
実際、タイミングのあるタスクを使用することには、実際にいくつかの問題があります。元のビジネスシステムは、注文が10分で支払われない場合、注文はすぐにキャンセルされ、製品在庫がリリースされることを望んでいます。ただし、データボリュームが大きくなると、未払いの注文データを取得する時間が延長されます。一部の注文は10分後にキャンセルされ、15分、20分などになる可能性があります。このようにして、在庫は時間内にリリースされず、奇数にも影響します。遅延メッセージを使用して、注文キャンセル操作は、設定された時間に従って理論的に実行できます。
現在、rabbitmqを使用して遅延メッセージを実装することに関するインターネット上の記事のほとんどは、Rabbitmqの死んだ文字キューを使用して実装する方法に関するものです。実装ソリューションは非常に複雑に見え、元のRabbitMQクライアントAPIを使用して実装されています。これはさらに冗長です。
Spring BootはRabbitMQクライアントAPIをラップしました。これを使用するのがはるかに簡単です。 rabbitmq_delayed_message_exchangeプラグインとスプリングブーツを使用して遅延メッセージを実装する方法の詳細な紹介を次に示します。
ソフトウェアの準備
エルラン
この記事で使用されているバージョンは次のとおりです。Erlang20.3
rabbitmq
この記事では、rabbitmqのウィンドウバージョンを使用しています。バージョン番号は3.7.4です。
rabbitmq_delayed_message_exchangeプラグイン
プラグインのダウンロードアドレス:http://www.rabbitmq.com/community-plugins.html
URLを開いた後、ctrl + fとrabbitmq_delayed_message_exchangeを検索します。
覚えておいてください、バージョン番号を選択する必要があります。 rabbitmq 3.7.4を使用しているため、対応するrabbitmq_delayed_message_exchangeプラグインも3.7.xを選択する必要があります。
適切なバージョンを選択しないと、遅延メッセージを使用するとさまざまな奇妙な問題が発生し、インターネット上に解決策がありません。私はこの問題のために一晩中苦労しました。適切なプラグインバージョンを選択することを忘れないでください。
プラグインをダウンロードした後、RabbitMQインストールディレクトリの下のプラグインディレクトリに配置し、次のコマンドを使用してプラグインを開始します。
rabbitmq-pluginsはrabbitmq_delayed_message_exchangeを有効にします
スタートアップが成功した場合、次のメッセージが表示されます。
次のプラグインが有効になっています:rabbitmq_delayed_message_exchange
プラグインが正常に起動されたら、RabbitMQを再起動して有効にすることを忘れないでください。
統合されたrabbitmq
これは非常に簡単です。Mavenプロジェクトのpom.xmlファイルに追加するだけです
<Dependency> groupId> org.springframework.boot </groupid> <artifactid> spring-boot-starter-amqp </artifactid> </dependency>
Spring Bootには2.0.1.Releaseを使用しています。
次に、Application.PropertiesファイルにRedis構成を追加します。
spring.rabbitmq.host = 127.0.0.1spring.rabbitmq.port = 5672spring.rabbitmq.username = guestspring.rabbitmq.password = guest
ConnectionFactoryとrabbittemplateを定義します
また、非常にシンプルで、コードは次のとおりです。
パッケージcom.mq.rabbitmq; Import org.springframework.amqp.rabbit.connection.cachingconnectionfactory; Import org.springframework.amqp.rabbit.connection.connectionFactory; Import org.springframework.amqp.rabbit.core.core.core.core.core.core.core.core.core.core.core.core.core.core.core.core.core.core.core.core.core.core.core.core.core.core org.springframework.boot.context.properties.configurationproperties; Import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration;@configuration@configuration@configurationproperties(private.rabbitmqccnq "" ")spring.rabbitmqccnq;プライベートインターポート;プライベート文字列ユーザー名;プライベート文字列パスワード。 @bean public ConnectionFactory ConnectionFactory(){cachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory(host、port); cachingConnectionFactory.setUsername(username); cachingConnectionFactory.setPassWord(パスワード); CachingConnectionFactory.setVirtualHost( "/"); cachingConnectionFactory.setPublisherConfirms(true); CachingConnectionFactoryを返します。 } @bean public rabbittemplate rabbittemplate(){rabbittemplate rabbittemplate = new rabbittemplate(connectionfactory()); rabbittemplateを返します。 } public string gethost(){return host; } public void sethost(string host){this.host = host; } public int getport(){return port; } public void setport(int port){this.port = port; } public string getUsername(){return username; } public void setUsername(string username){this.username = username; } public string getPassWord(){パスワードを返します。 } public void setPassword(string password){this.password = password; }}交換およびキューの構成
パッケージcom.mq.rabbitmq; Import org.springframework.amqp.core。*; import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; import java.util.hashmap; import java.util.util.util.util.util.util.util.util.util.util.util.util.util.util.util.util.util.util.util.util.util.util.util.util.util.util.util.util.util.til. {@bean public customexchange delayexchange(){map <string、object> args = new hashmap <>(); args.put( "x-delayed-type"、 "direct");新しいcustomexchange( "test_exchange"、 "x-delayed-message"、true、false、args)を返します。 } @bean public queue queue(){queue queue = new queue( "test_queue_1"、true);キューを返します。 } @bean public binding binding(){return bindingbuilder.bind(queue())。to(delayexchange())。with( "test_queue_1")。 }}ここでは、customexchangeが直接的な変化ではなく使用されており、Customexchangeのタイプはx-delayed-messageでなければならないことに注意する必要があります。
メッセージ送信を実装します
パッケージcom.mq.rabbitmq; Import org.springframework.amqp.amqpexception; Import org.springframework.amqp.core.message; import org.springframework.amqp.core.messagepostprocessor; Import org.springframework.rabbit.core.crabbit.core.corework.mqp.pmbit.core.corework springframework.beans.factory.annotation.autowired; import org.springframework.stereotype.service; import java.text.simpledateformat; import java.util.date; @servicepublic class messageserviceimpl {@autowided privated rabbittemplate rabbitemplate; public void sendmsg(string queuename、string msg){simpledateformat sdf = new simpledateFormat( "yyyy-mm-dd hh:mm:ss"); system.out.println( "メッセージ送信時間:"+sdf.format(new date())); rabbittemplate.convertandsend( "test_exchange"、queuename、msg、new messagepostprocessor(){@override public message postprocessmessage(message message)throws amqpexception {message.getMessageProperties()。 }}送信中は、ヘッダーを追加する必要があることに注意してください
X-Delay
ここで設定した遅延時間は3秒です。
メッセージ消費者
package com.mq.rabbitmq;import org.springframework.amqp.rabbit.annotation.RabbitHandler;import org.springframework.amqp.rabbit.annotation.RabbitListener;import org.springframework.stereotype.Component;import java.text.SimpleDateFormat;import java.util.date; @componentpublic class messagereceiver {@rabbitlistener(queues = "test_queue_1")public void receive(string msg){simpledateformat sdf = new simpledateformat( "yyyy-mm-dd hh:mm:ss"); system.out.println( "メッセージ受信時間:"+sdf.format(new date())); system.out.println( "受信メッセージ:"+msg); }}スプリングブートプログラムを実行し、メッセージを送信します
Spring Bootプログラムをメインメソッドで直接実行すると、Spring BootはMessagereceiverクラスを自動的に解析します。
次に、Junitを使用して、メッセージを送信するインターフェイスを実行します。
パッケージcom.mq.rabbitmq; Import org.junit.test; import org.junit.runner.runwith; import org.springframework.beans.factory.annotation.autowired; import org.springframework.boot.test.test.context.springboottest; Import; org.springframework.test.context.junit4.springrunner; @runwith(springrunner.class)@springboottestpublic class rabbitmqapplicationtests {@autowired private messagaseviceimpl messageservice; @test public void send(){messageService.sendmsg( "test_queue_1"、 "hello i are delay msg"); }}実行後、次の情報を確認できます。
メッセージの送信時間:2018-05-03 12:44:53
3秒後、Spring Boot Consoleが出力されます。
メッセージ受信時間:2018-05-03 12:44:56
受信したメッセージ:こんにちは私はmsgを遅らせています
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。