1. Breve introdução
Na maioria dos aplicativos, o middleware de serviço de mensagem pode ser usado para melhorar a comunicação assíncrona do sistema e expandir os recursos de desacoplamento
- Dois conceitos importantes em serviços de
mensagem : intermediário de mensagem e destino. Quando o remetente da mensagem envia uma mensagem, ela será assumida pelo agente da mensagem, o que garante que a mensagem seja entregue ao destino especificado. - As filas de mensagens têm principalmente duas formas de destinos:
fila: comunicação de mensagem ponto a ponto (ponto a ponto)
tópico: comunicação de mensagem de publicação / assinatura
Dois, instalação
Abra a máquina virtual, execute o Linux, abra o SmarTTY, entre docker pull rabbitmq:3-management
e baixe
docker run -d -p 5672:5672 -p 15672:15672 --name myrabbitmq d55229deb03e
- -d executado em segundo plano
- Ele tem mais duas portas, então apenas -p duas vezes
- --O nome é myrabbitmq
- A pilha de trás é o ID do meu coelho, verificado com as imagens do docker
Então entre no navegador http://192.168.0.102:15672/
, claro, esse IP é meu SmarTTY conectado ao Linux, o que é meu, veja o docker que escrevi antes
Entre, senha da conta de login, o padrão é convidado
Três, RabbitMQ
O produtor publica a mensagem na central, a mensagem finalmente chega na fila e é recebida pelo consumidor, e o Binding determina para qual fila a mensagem da central deve ser enviada.
Quando o Exchange distribui mensagens, existem diferenças de acordo com as diferentes estratégias de distribuição. Atualmente, existem quatro tipos: direto, fanout, tópico e cabeçalhos .
1. Trocador de tópico
O switch de tópico distribui o atributo de chave de roteamento da mensagem por meio de correspondência de padrões e combina a chave de roteamento com um padrão.Neste momento, a fila precisa ser vinculada a um padrão. Ele divide a string da chave de roteamento e da chave de ligação em palavras, que são separadas por pontos. Ele também reconhece dois caracteres curinga: o símbolo "#" e o símbolo "*". # Corresponder 0 ou mais palavras, * Corresponder a uma palavra.
2. Teste primeiro
Diagrama do tutorial em vídeo
Siga o vídeo tutorial para fazer o teste, não sei porque isso está acontecendo. . . Faça algumas trocas e, em seguida, vincule a fila,
3. Crie 3exchange
As principais são estas duas caixas.
Ou seja Durability
: opção Duiable significa persistência. Depois de abri-la da próxima vez, a bolsa ainda está lá, e a outra significa que desaparece após o fechamento.
4. Adicione 4 filas
5. Filas de ligação para todas as 3 trocas
Escolha qual amarrar, clique em
- Mas ah, é um pouco diferente em exchange.topic, porque exchange.topic não está vinculado a todos, o nome da rota precisa ser alterado, conforme explicado mais tarde
Veja a imagem no início, exchange.direct e exchange.fanout estão vinculados às 4 filas, exchange.topic está atguigu.#
vinculado (atguigu como a cabeça) e *.news
vinculado (o fim da notícia)
exchange.direct e exchange.fanout são ambos vinculados Nisso
Em seguida, exchange.topic:
- O que isto significa? Disse depois
6. Teste
1) `exchange.direct
Por exemplo, quando exchange.direct
enviamos uma solicitação atguigu na China, apenas a fila atguigu pode aceitá-la, porque a troca usa direct e o nome da rota é atguigu . O nome da rota é especificado para enviar informações. Outras filas têm nomes diferentes e não podem ser recebido.
- Se o tipo for direto, especifique para quem enviar
2) exchange.fanout
O tipo é fanout
que não importa o que seja especificado, a fila em exchange.fanout irá recebê-lo. Por exemplo, envie uma solicitação em exchange.fanout
- Apenas atguigu's ready é 2 porque o exemplo acima é um pedido atguigu
3) exchange.topic
Enviando em exchange.topic hello.news
, parece que isso não existe, mas preste atenção
porque o topic
tipo é utilizado, então a tecnologia pode ser fuzzy matching. (Isso deve ser entendido como vinculação, porque a fila é escrita no início, e então a troca tem alguma vinculação com cada fila) Então a fila atguigu.news aceita * .news e pode aceitá-lo. A fila gulixueyuan.news aceita * .news e também pode aceitá-lo.
Quatro, teste de projeto
1. Configuração
application.yml:
spring:
rabbitmq:
host: 192.168.0.102
username: guest
password: guest
2. Envie uma mensagem
Pode ser importado automaticamente com @Autowired
@SpringBootTest
class SpringBootAmqpApplicationTests {
@Autowired
RabbitTemplate rabbitTemplate;
@Test
void contextLoads() {
// rabbitTemplate.send(String exchange, String routeKey, Message var3)
// Message(byte[] body, MessageProperties messageProperties) Message为一个数组和一个头消息
// convertAndSend(String var1, String var2, Object var3)
// 其中,Object var3默认为消息体,会自动序列化发送过去的
Map<String,Object> map = new HashMap<>();
map.put("msg","这是一个信息");
rabbitTemplate.convertAndSend("exchange.direct","atguigu.news",map);
}
send(String exchange, String routeKey, Message var3)
: Nome da troca, nome da rota e mensagem. A mensagem consiste no conteúdo da mensagem e no cabeçalho da mensagemconvertAndSend(String var1, String var2, Object var3)
, O envio é muito problemático, existe este método, o objeto var3 será automaticamente convertido para serialização para enviar mensagens
3. Aceite a mensagem
@Test
public void test(){
Message receive = rabbitTemplate.receive("atguigu.news");
System.out.println(receive);
}
(Corpo: '{msg = 这 是 一个 信息}' MessageProperties [headers = {}, contentType = application / x-java-serialized-object, contentLength = 0, receivedDeliveryMode = PERSISTENT, priority = 0, redelivered = true, receivedExchange = exchange.direct, receivedRoutingKey = atguigu.news, deliveryTag = 1, messageCount = 0])
4. A mensagem enviada torna-se do tipo JSON
Como você pode ver, tanto o envio quanto o recebimento são serializados e desserializados, é melhor converter para JSON, basta adicionar uma classe de configuração.
@Configuration
public class MyAMQPConfig {
@Bean
public MessageConverter messageConverter(){
// 把消息转化为JSON格式
return new Jackson2JsonMessageConverter();
}
}
Envie
novamente e aceite novamente
class org.springframework.amqp.core.Message
(Body: '{“msg”: “这 是 一个 信息”}' MessageProperties [headers = { ContentTypeId = java.lang.Object, KeyTypeId = java.lang.Object, TypeId = java.util.HashMap}, contentType = application / json, contentEncoding = UTF-8, contentLength = 0, receivedDeliveryMode = PERSISTENT, priority = 0, redelivered = true, receivedExchange = exchange.direct, receivedRoutingKey = atguigu.news, deliveryTag = 1 , messageCount = 0])
exchange.direct
É assim que ele é enviado , e o mesmo se aplica a outros tipos de trocas.
5. Aceitar mensagens automaticamente
Para mostrar melhor, criamos uma classe com o método toString escrito nela,
public class Person {
String name;
int age;
//xxx
}
Crie uma camada de serviço para receber mensagens automaticamente de uma determinada fila
@Service
public class PersonService {
@RabbitListener(queues = "atguigu.news")
public void receive(Person person){
System.out.println("收到消息"+person);
}
}
@RabbitListener
: Você pode colocar várias filas para aceitar automaticamente as coisas na fila. Se o parâmetro for usado, escreva Pessoa, ou seja, se o JSON enviado for Pessoa, pode ser recebido, caso contrário, é do tipo Mensagem
Ative a anotação de aceitação automática de mensagens no programa principal
@EnableRabbit
@SpringBootApplication
public class SpringBootAmqpApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootAmqpApplication.class, args);
}
}
@EnableRabbit
: Ativa o comentário de aceitação automática de mensagens
Aula de teste
@SpringBootTest
class SpringBootAmqpApplicationTests {
@Autowired
RabbitTemplate rabbitTemplate;
@Test
void contextLoads() {
rabbitTemplate.convertAndSend("exchange.direct","atguigu.news",new Person("小强",22));
}
Uma mensagem de uma classe personalizada é enviada aqui
Recebeu a mensagem Pessoa {nome = 'Xiaoqiang', idade = 22}
Por aceitar a saída de algo, é escrito pela camada de serviço
6. Se for aceito automaticamente como tipo de mensagem
Um método da camada de serviço
@RabbitListener(queues = "atguigu")
public void receive2(Message message){
System.out.println(message.getBody());
System.out.println(message.getMessageProperties());
}
Ainda envia o objeto Person, mas a fila está atguigu, e o acima também aceita atguigu, mas o tipo de aceitação é Message
@Test
void contextLoads() {
rabbitTemplate.convertAndSend("exchange.direct","atguigu",new Person("小强",22));
}
[B @ 5e012317
MessageProperties [headers = { TypeId = com.qiang.Bean.Person}, contentType = application / json, contentEncoding = UTF-8, contentLength = 0, receivedDeliveryMode = PERSISTENT, priority = 0, redelivered = false, receivedExchange = exchange.direct, receivedRoutingKey = atguigu, deliveryTag = 1, consumerTag = amq.ctag-Ws2bRFLJ6Y3d7JXvrKVCTQ, consumerQueue = atguigu]
Quinto, o código substitui as operações de interface
A criação de troca, fila e vinculação que fizemos antes pode ser implementada em Java.
Continue fazendo isso na classe de teste
@Test
public void create(){
amqpAdmin.declareExchange(new DirectExchange("amqpadmin.exchange"));
amqpAdmin.declareQueue(new Queue("amqpadmin.queue",true));
amqpAdmin.declareBinding(new Binding("amqpadmin.queue",Binding.DestinationType.QUEUE,"amqpadmin.exchange","amqp.test",null));
}
DirectExchange
: Existe no máximo este containerDirectExchange(String name, boolean durable, boolean autoDelete, Map<String, Object> arguments)
, mas também existe um container, basta escrever o primeiro. Durável é se é persistente e se o autoDelete booleano é excluído automaticamente, o Map não sabe. . .Queue
o mesmoBinding
:Binding(String destination, Binding.DestinationType destinationType, String exchange, String routingKey, @Nullable Map<String, Object> arguments)
- destino: destino, a qual fila ligar
- Binding.DestinationType destinationType: basta acompanhar. . .
- troca: qual troca
- routingKey: Qual é o nome de roteamento?
- @Nullable Map: não sei. . . .
O código até agora: spring-boot-AMQP