[SpringCloud] Einführung in Microservice Technology Stack 4 – Eine vorläufige Studie von RabbitMQ

RabbitMQ


Rabbitmq installieren

Stellen Sie zunächst sicher, dass Sie Docker installiert haben

Es ist Docker, der die Bilddatei abruft:docker pull rabbitmq:3-management

Öffnen Sie nach dem Ziehen den Behälter

docker run \
 -e RABBITMQ_DEFAULT_USER=itcast \
 -e RABBITMQ_DEFAULT_PASS=123321 \
 --name mq \
 --hostname mq1 \
 -p 15672:15672 \
 -p 5672:5672 \
 -d \
 rabbitmq:3-management

Öffnen Sie den Browser für Port 15672 der virtuellen Maschine und Sie sehen die Rabbitmq-Verwaltungsoberfläche.

Fügen Sie hier eine Bildbeschreibung ein

Wir können neue Benutzer im Admin-Tab hinzufügen

wobeican access virtual hosts den virtuellen Host darstellt, der dem aktuellen Benutzer entspricht
Es wird empfohlen, dass verschiedene Benutzer unterschiedlichen virtuellen Hosts entsprechen, um einen Isolationseffekt zu erzielen

Ein virtueller Host kann durch Klicken auf die Schaltfläche virtual hosts auf der rechten Seite des Bildes oben erstellt werden


SpringAMQP-Basiswarteschlange

Da die offizielle native Methode zum Betrieb von RabbitMQ zu grob ist und viel Code enthält, ist sie nicht für die tägliche Entwicklung geeignet. Es wird empfohlen, SpringAMQP zu verwenden, um den Vorgang zu vereinfachen.

Koordinaten importieren

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>
<!--AMQP依赖,包含RabbitMQ-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!--单元测试-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>

Rabbitmq-Link konfigurieren

logging:
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS
spring:
  rabbitmq:
    host: 192.168.113.146 # rabbitMQ的ip地址
    port: 5672 # 端口
    username: itcast
    password: 123321
    virtual-host: /

Der Herausgeber schreibt Testklassen, um AMQP zu testen

Da unser Rabbitmq standardmäßig keine Warteschlange erstelltsimple.queue, erhalten Sie keine Informationen, wenn Sie es direkt senden. Sie müssen zuerst ein Urteil fällen. Ob die Warteschlange nicht existiert Erstellen Sie zunächst die entsprechende Warteschlange. Erst nach dem Senden können Sie sie empfangen!

@Test
public void testSendMessage2SimpleQueue() {
    
    
  RabbitAdmin admin = new RabbitAdmin(rabbitTemplate);
  String queueName = "simple.queue";
  String message = "hello, spring amqp!";

  // 队列是否存在的判断
  if (Objects.isNull(admin.getQueueProperties(queueName))) {
    
    
      Queue queue = new Queue(queueName);
      admin.declareQueue(queue);
  }

  // 发送消息到消息队列
  rabbitTemplate.convertAndSend(queueName, message);
}

Wenn nichts anderes passiert, können Sie die neu erstellte simple.queue-Warteschlange in der Option queue der Rabbitmq-Konsole sehen, die die erste von uns gesendete Nachricht enthält.


Der Verbraucher verbraucht Nachrichten in der entsprechenden Warteschlange

Vor dem Abhören müssen Sie außerdem dieselbe application.yaml wie der Herausgeber konfigurieren, damit Sie eine Verbindung zu Rabbitmq herstellen können.

Erstellen Sie eine neue Überwachungskonsumentenklasse SpringRabbitListener und übergeben Sie den folgenden Code, um die Überwachung auszuführen

@Component
public class SpringRabbitListener {
    
    
  // 设置消费者需要监听的队列
  @RabbitListener(queues = "simple.queue")
  public void listenWorkQueue1(String msg) throws InterruptedException {
    
    
    // 获取队列中信息
      System.out.println("消费者1接收到消息:【" + msg + "】" + LocalTime.now());
      Thread.sleep(20);
  }
}

WorkQueue

Fügen Sie hier eine Bildbeschreibung ein

Die obige Abbildung zeigt das Flussdiagramm der Arbeitswarteschlange. Tatsächlich wird ein Verbraucher hinzugefügt, um die Nachrichten in der Warteschlange zu konsumieren.

Da wir im vorherigen Abschnitt bereits simple.queue erstellt haben, besteht hier kein Grund zur Beurteilung. Wir können alle 20 ms direkt eine Information darin einfügen.

@Test
public void testSendMessage2WorkQueue() throws InterruptedException {
    
    
  String queueName = "simple.queue";
  String message = "hello, message__";
  for (int i = 1; i <= 50; i++) {
    
    
      rabbitTemplate.convertAndSend(queueName, message + i);
      Thread.sleep(20);
  }
}

Befolgen Sie auf ähnliche Weise die Anweisungen im Flussdiagramm, um zwei Consumer-Listener einzurichten
Achtung! Der erste Verbraucher empfängt alle 20 ms Nachrichten, während der zweite Verbraucher alle 200 ms Nachrichten erhält

@RabbitListener(queues = "simple.queue")
public void listenWorkQueue1(String msg) throws InterruptedException {
    
    
    System.out.println("消费者1接收到消息:【" + msg + "】" + LocalTime.now());
    Thread.sleep(20);
}

@RabbitListener(queues = "simple.queue")
public void listenWorkQueue2(String msg) throws InterruptedException {
    
    
    System.err.println("消费者2........接收到消息:【" + msg + "】" + LocalTime.now());
    Thread.sleep(200);
}

Führen Sie zuerst den Consumer aus und fügen Sie dann mit dem Publisher 50 Nachrichten ein

Aus der Protokollausgabe haben wir herausgefunden, dass Verbraucher 1 und 2 die gleiche Datenmenge verarbeitet haben (jeweils 25 Elemente), aber es ist offensichtlich, dass der zweite Verbraucher viel langsamer ist, da er nur alle 200 ms eine Nachricht verarbeitet.

Der Grund für diese Situation ist消息预取, was bedeutet, dass alle Verbraucher die gleiche Anzahl an Nachrichten erhalten, unabhängig davon, wie oft sie die Nachrichten verarbeiten


Lösen Sie das Problem der ungleichmäßigen Nachrichtenverteilung

Das Prefetch-Konfigurationselement wird zur Konfigurationsdatei hinzugefügt. Dies bedeutet, dass eine Nachricht verarbeitet werden muss, bevor die nächste Nachricht zur Verarbeitung herausgenommen werden kann, wodurch effektiv vermieden wird, dass alle Nachrichten im Voraus abgerufen und auf einmal auf einem Verbraucher gestapelt werden.

spring:
  rabbitmq:
    host: 192.168.113.146 # rabbitMQ的ip地址
    port: 5672 # 端口
    username: itcast
    password: 123321
    virtual-host: /
    listener:
      simple:
        prefetch: 1

Wiederholen Sie zu diesem Zeitpunkt den obigen Vorgang und stellen Sie fest, dass der Effekt „Je leistungsfähiger ist mühsamer“ erzielt wird. Verbraucher 1 verbraucht aufgrund seiner hohen Verarbeitungsgeschwindigkeit die überwiegende Mehrheit der Nachrichten, während Verbraucher 2 nur sehr wenige Nachrichten verarbeitet.

Dadurch wird die Gesamtverarbeitungszeit auf 1 Sekunde oder weniger komprimiert.


Route veröffentlichen und abonnieren FanoutExchange

Fügen Sie hier eine Bildbeschreibung ein

Das Einrichten der Routing-Veröffentlichung und des Abonnements erfordert drei Schritte: Einrichten des Routing-Exchange, Einrichten der Warteschlange Queue und Binden der Warteschlange an das Routing.

Erstellen Sie die Fanout-Konfigurationsdatei FanoutConfig. Wir erstellen einfach 1 Route und 2 Warteschlangen gemäß dem folgenden Code und führen den Bindungsvorgang durch.

@Configuration
public class FanoutConfig {
    
    
  // 配置路由:itcast.fanout
  @Bean
  public FanoutExchange fanoutExchange(){
    
    
      return new FanoutExchange("itcast.fanout");
  }

  // 配置队列:fanout.queue1
  @Bean
  public Queue fanoutQueue1(){
    
    
      return new Queue("fanout.queue1");
  }

  // 绑定队列1到交换机
  @Bean
  public Binding fanoutBinding1(Queue fanoutQueue1, FanoutExchange fanoutExchange){
    
    
      return BindingBuilder
              .bind(fanoutQueue1)
              .to(fanoutExchange);
  }

  // fanout.queue2
  @Bean
  public Queue fanoutQueue2(){
    
    
      return new Queue("fanout.queue2");
  }

  // 绑定队列2到交换机
  @Bean
  public Binding fanoutBinding2(Queue fanoutQueue2, FanoutExchange fanoutExchange){
    
    
      return BindingBuilder
              .bind(fanoutQueue2)
              .to(fanoutExchange);
  }
}

Da sie alle Bean-Anmerkungen hinzugefügt haben, führen Sie das Verbraucherprojekt direkt aus und sie werden automatisch zusammengestellt.

Öffnen Sie zu diesem Zeitpunkt das Rabbitmq-Kontrollfeld und geben Sie die Austauschoption ein. Dort finden Sie unsere neu erstellte Route und die entsprechende Warteschlangenbindungsbeziehung.

Fügen Sie hier eine Bildbeschreibung ein


Den nachfolgenden Code für Herausgeberinformationen und Verbraucherverbrauchsinformationen können Sie im vorherigen Abschnitt selbst vervollständigen, daher werde ich hier nicht auf Details eingehen.


DirectExchange

Fügen Sie hier eine Bildbeschreibung ein

Es kann als Routing- und Weiterleitungsmechanismus mit Regeln verstanden werden, und der Weiterleitungsvorgang wird durch die konsistente Paarung von Bindungsschlüssel und Routingschlüssel implementiert.


Konfigurieren Sie die Verbraucherüberwachung

// value 监听队列
// exchange 监听路由
// key bindingkey
@RabbitListener(bindings = @QueueBinding(
        value = @Queue(name = "direct.queue1"),
        exchange = @Exchange(name = "itcast.direct", type = ExchangeTypes.DIRECT),
        key = {
    
    "red", "blue"}
))

@RabbitListener(bindings = @QueueBinding(
        value = @Queue(name = "direct.queue2"),
        exchange = @Exchange(name = "itcast.direct", type = ExchangeTypes.DIRECT),
        key = {
    
    "red", "yellow"}
))

Anschließend sendet der Herausgeber die Nachricht mit Routingkey an die entsprechende Route.

@Test
public void testSendDirectExchange() {
    
    
    // 交换机名称
    String exchangeName = "itcast.direct";
    // 消息
    String message = "hello, red!";
    // 发送消息
    rabbitTemplate.convertAndSend(exchangeName, "red", message);
}

Themenaustausch

Fügen Sie hier eine Bildbeschreibung ein

Ähnlich wie Directexchange, aber Routingkey ist eine Liste mit mehreren Wörtern. Das spezifische Format finden Sie in der Abbildung oben.

Die Schreibmethode von Herausgeber und Verbraucher ist im Grunde dieselbe wie bei DirectExchange. Zu beachten ist die Schreibmethode von Routingkey und Bindingkey.


Supongo que te gusta

Origin blog.csdn.net/delete_you/article/details/133611740
Recomendado
Clasificación