同步调用与异步调用
- 同步调用:时效性很强,feign调用方式是是同步调用
- 耦合度高
- 性能下降
- 资源浪费
- 级联失败
- 异步调用方案,事件驱动模式:通过发布、订阅事件实现
- 服务解耦
- 性能提升、吞吐量高
- 服务没有强依赖、不担心级联失败问题
- 资源浪费失败
- 流量削峰
MQ(MessageQueue)
- 相当于事件驱动架构中的Broker
- 常用mq技术:
RabbitMQ下载安装
-
官网:https://www.rabbitmq.com/
-
channel: 操作mq的工具
-
exchange: 路由消息到队列中
-
queue: 缓存消息
-
virtual host: 虚拟主机,是对queue、exchange等资源的逻辑分组
-
erlang下载地址:https://www.rabbitmq.com/documentation.html
-
rabbitmq下载:https://www.rabbitmq.com/install-windows.html
-
erlang 配置环境遍历
- 新建ERLANG_HOME 值为erlang安装地址
- 在Path中添加 %ERLANG_HOME%\bin
- rabbitmq
- 环境遍历添加RABBITMQ_SERVER 值为
- Path添加%RABBITMQ_SERVER%\sbin
- 安装rabbit管理插件命令 rabbitmq-plugins enable rabbitmq_management
net start RabbitMQ 启动
net stop RabbitMQ 停止
rabbitmqctl status 查看状态
健康检查: rabbitmqctl status
启动监控管理器:rabbitmq-plugins enable rabbitmq_management
关闭监控:rabbitmq-plugins disable rabbitmq_management
停止服务:rabbitmq-service stop
启动服务:rabbitmq-service start
重启命令:net stop RabbitMQ && net start
帮助命令:rabbitmqctl help
rabbitmqctl list_queues查看所有队列
rabbitmqctl reset清除所有队列
rabbitmqctl list_exchanges查看所有交换器
rabbitmqctl add_user username password添加用户
rabbitmqctl set_user_tags username administrator分配角色
rabbitmqctl list_bindings 查看交换器和队列的绑定关系
- 注意:erlang和rabbitmq是有版本要求的,最好不要用最新的,可能会有坑
- 访问地址:http://127.0.0.1:15672/
- 一般这个东西都会在linux系统上,会在linux上安装,如果会docker,可以直接docker安装更方便一点
rabbitmq创建用户及分配权限
1、超级管理员(administrator)
可登陆管理控制台,可查看所有的信息,并且可以对用户,策略(policy)进行操作。
2、监控者(monitoring)
可登陆管理控制台,同时可以查看rabbitmq节点的相关信息(进程数,内存使用情况,磁盘使用情况等)
3、策略制定者(policymaker)
可登陆管理控制台, 同时可以对policy进行管理。但无法查看节点的相关信息(上图红框标识的部分)。
4、普通管理者(management)
仅可登陆管理控制台,无法看到节点信息,也无法对策略进行管理。
5、其他
无法登陆管理控制台,通常就是普通的生产者和消费者。
rabbitmq实现简单消息模型案例
- 新建一个mq-demo父工程、在创建publisher、consumer子工程
- 依赖
- springboot版本管理有两种方式一种是spring-boot-dependencies, 一般都配置在父工程中,子工程可继承父工程的版本
- 另外一种是spring-boot-parent,一般都配置在父工程中,子工程可继承父工程的版本
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-boot-dependencies.version>2.3.12.RELEASE</spring-boot-dependencies.version>
<spring-boot-starter-test.version>2.3.12.RELEASE</spring-boot-starter-test.version>
<lombok.version>1.18.20</lombok.version>
<spring-boot-starter-amqp.version>2.3.12.RELEASE</spring-boot-starter-amqp.version>
<amqp-client.version>5.9.0</amqp-client.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot-dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring-boot-starter-test.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<version>${spring-boot-starter-amqp.version}</version>
</dependency>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>${amqp-client.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
- 简单消息模式例子参考:https://www.rabbitmq.com/getstarted.html (网上很多例子,卸不下来copy一个看看,下面的puhlisher、consumer是我从网上copy下来的,改一改ip地址和用户名及密码)
- 生产者
package com.konglz.publisher.test;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
/**
* @description: 简单模式Simple
*/
public class Producer {
public static void main(String[] args) {
// 所有的中间件技术都是基于tcp/ip协议基础之上构建新型的协议规范,只不过rabbitmq遵循的是amqp
// ip port
// 1: 创建连接工程
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.0.114");
connectionFactory.setPort(5672);
connectionFactory.setUsername("klz");//rabbitmq登录的账号
connectionFactory.setPassword("klz");//rabbitmq登录的密码
connectionFactory.setVirtualHost("/");
//springboot ---rabbitmq
Connection connection = null;
Channel channel = null;
try {
// 2: 创建连接Connection Rabbitmq为什么是基于channel去处理而不是链接? 长连接----信道channel
connection = connectionFactory.newConnection("生产者");
// 3: 通过连接获取通道Channel
channel = connection.createChannel();
// 4: 通过通创建交换机,声明队列,绑定关系,路由key,发送消息,和接收消息
String queueName = "queue1";
/*
* @params1 队列的名称
* @params2 是否要持久化durable=false 所谓持久化消息是否存盘,如果false 非持久化 true是持久化? 非持久化会存盘吗? 会存盘,但是会随从重启服务会丢失。
* @params3 排他性,是否是独占独立
* @params4 是否自动删除,随着最后一个消费者消息完毕消息以后是否把队列自动删除
* @params5 携带附属参数
*/
channel.queueDeclare(queueName, true, false, false, null);
// 5: 准备消息内容
String message = "Hello rabbitmq!!!";
// 6: 发送消息给队列queue
// @params1: 交换机 @params2 队列、路由key @params 消息的状态控制 @params4 消息主题
// 面试题:可以存在没有交换机的队列吗?不可能,虽然没有指定交换机但是一定会存在一个默认的交换机。
channel.basicPublish("", queueName, null, message.getBytes());
System.out.println("消息发送成功!!!");
} catch (Exception ex) {
ex.printStackTrace();
} finally {
// 7: 关闭通道
if (channel != null && channel.isOpen()) {
try {
channel.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
// 8: 关闭连接
if (connection != null && connection.isOpen()) {
try {
connection.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
}
- 消费者
package com.konglz.consumer.test;
import com.rabbitmq.client.*;
import java.io.IOException;
public class Consumer {
public static void main(String[] args) {
// 所有的中间件技术都是基于tcp/ip协议基础之上构建新型的协议规范,只不过rabbitmq遵循的是amqp
// ip port
// 1: 创建连接工程
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.0.114");//服务器IP
connectionFactory.setPort(5672);
connectionFactory.setUsername("klz");
connectionFactory.setPassword("klz");
connectionFactory.setVirtualHost("/");
Connection connection = null;
Channel channel = null;
try {
// 2: 创建连接Connection
connection = connectionFactory.newConnection("消费者");
// 3: 通过连接获取通道Channel
channel = connection.createChannel();
// 4: 通过通创建交换机,声明队列,绑定关系,路由key,发送消息,和接收消息
// true = ack 正常的逻辑是没问题 死循环 rabbit 重发策略
// false = nack 消息这在消费消息的时候可能会异常和故障
final Channel channel2 = channel;
channel2.basicConsume("queue1", false, new DeliverCallback() {
public void handle(String consumerTag, Delivery message) throws IOException {
try {
System.out.println("收到消息是" + new String(message.getBody(), "UTF-8"));
channel2.basicAck(message.getEnvelope().getDeliveryTag(),false);
}catch (Exception ex){
ex.printStackTrace();
// 三次确认 -- reject + sixin
}
}
}, new CancelCallback() {
public void handle(String consumerTag) throws IOException {
System.out.println("接受失败了...");
}
});
System.out.println("开始接受消息");
System.in.read();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
// 7: 关闭通道
if (channel != null && channel.isOpen()) {
try {
channel.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
// 8: 关闭连接
if (connection != null && connection.isOpen()) {
try {
connection.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
}
AMQP
- AMQP(advanced message queuing protocol)
- Spring AMQP是一个模板
Spring AMQP实现简单消息模型
-
spring AMQP是spring对rabbit做的封装,提供的模板工具,使用起来很方便
-
依赖(生产者、消费者都要引入)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
- 生产者(写在测试模块)
package com.konglz.publisher;
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class PublisherApplicationTests {
@Autowired
RabbitTemplate rabbitTemplate;
@Test
void test1(){
String queueName = "queue1";
String message = "hello world i am spring amqp";
rabbitTemplate.convertAndSend(queueName,message);
}
}
- 消费者(写完之后运行这个服务)
package com.konglz.consumer.test;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* @Description
* @Author konglz
* @Data 2022/9/28 14:14
*/
@Component
public class SpringRabbitListener {
//注意这个queues的名称对应rabbitmq队列的名称,和生产者那边的队列名称一样
@RabbitListener(queues = "queue1")
public void springRabbitListener(String message){
System.out.println("消费者接收到的消息:" + message);
}
}
Spring AMQP实现工作消息模型
- publisher:下面这段关于工作队列代码可能会报错,报没有这个队列名称的异常,这个时候我们可以手动的在rabbitmq总新建一个同名队列,或者使用代码创建同名队列
package com.konglz.publisher;
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class PublisherApplicationTests {
@Autowired
RabbitTemplate rabbitTemplate;
@Test
void test1(){
String queueName = "queue1";
String message = "hello world i am spring amqp";
rabbitTemplate.convertAndSend(queueName,message);
}
@Test
void workQueue() throws InterruptedException {
String queueName = "workQueue";
String message = "hello world i am spring amqp__";
for(int i = 0; i < 100; i++){
rabbitTemplate.convertAndSend(queueName,message+i);
Thread.sleep(20);
}
}
}
- Consumer:两个消费者的睡眠事件不要设置一样,一个大一个小,要不可能是一个消费者接受了所有信息
package com.konglz.consumer.test;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* @Description
* @Author konglz
* @Data 2022/9/28 14:14
*/
@Component
public class SpringRabbitListener {
//注意这个queues的名称对应rabbitmq队列的名称,和生产者那边的队列名称一样
@RabbitListener(queues = "queue1")
public void springRabbitListener(String message){
System.out.println("消费者接收到的消息:" + message);
}
@RabbitListener(queues = "workQueue")
public void listenerWorkQueueConsumer1(String message) throws InterruptedException {
System.out.println("=====消费者1接收到的消息:" + message + LocalDateTime.now());
Thread.sleep(20);
}
@RabbitListener(queues = "workQueue")
public void listenerWorkQueueConsumer2(String message) throws InterruptedException {
System.err.println("=====费者2接收到的消息:" + message + LocalDateTime.now());
Thread.sleep(200);
}
}
Spring AMQP实现发布、订阅消息模型(Fanout)
-
发布订阅模式与之前的区别是允许将同一消息发送给多个消费者。通过交换机实现
-
exchange(交换机),路由转发消息时可能会失败,造成消息丢失
- Fanout: 广播
- Direct: 路由
- Topic:话题
-
交换机绑定队列: 注意不要忘记加@Bean注解
- @Configuration: 相当于,@Bean用在加了@Configuration的类内,是从Spring单例池中拿对象,而不是每次新new一个类对象出来
- @Bean:相当于,告诉我们方法会返回一个对象,这个对象要注册为Spring应用上下文中的bean,@Bean 需要在配置类中使用,即类上需要加上@Configuration注解
- @Component:表明一个类会作为组件类,并告知Spring要为这个类创建bean,@Bean用在加了@Component的类内,,不是从Spring单例池中拿对象,而是每次新new一个类对象出来
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Description
* @Author konglz
* @Data 2022/9/28 15:32
*/
@Configuration
public class FanoutConfig {
@Bean
public FanoutExchange fanoutExchange(){
return new FanoutExchange("konglz.fanout");
}
@Bean
public Queue fanoutQueue1(){
return new Queue("fanoutQueue1");
}
@Bean
public Binding fanoutBinding1(Queue fanoutQueue1, FanoutExchange fanoutExchange){
return BindingBuilder
.bind(fanoutQueue1)
.to(fanoutExchange);
}
@Bean
public Queue fanoutQueue2(){
return new Queue("fanoutQueue2");
}
@Bean
public Binding fanoutBinding2(Queue fanoutQueue2, FanoutExchange fanoutExchange){
return BindingBuilder
.bind(fanoutQueue2)
.to(fanoutExchange);
}
}
- 消费者
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* @Description
* @Author konglz
* @Data 2022/9/28 14:14
*/
@Component
public class SpringRabbitListener {
@RabbitListener(queues = "fanoutQueue1")
public void fanoutQueue1(String message){
System.out.println("fanoutQueue1消费者接收到的消息:" + message);
}
@RabbitListener(queues = "fanoutQueue2")
public void fanoutQueue2(String message){
System.out.println("fanoutQueue2消费者接收到的消息:" + message);
}
}
- 生产者
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class PublisherApplicationTests {
@Autowired
RabbitTemplate rabbitTemplate;
@Test
void fanout(){
String exchangeName = "konglz.fanout";
String message = "今日有雨,请带伞!";
//通过交换机与队列的绑定关系,将消息发送给每一个消费者
rabbitTemplate.convertAndSend(exchangeName,"",message);
}
}
Spring AMQP实现发布、订阅消息模型(Direct)
-
将消息更加规则路由到指定Queue,常被称为路由模式
-
每一个Queue都与Exchange设置一个BindKey
-
发送消息时指定RoutingKey
-
Exchang将消息路由到BindingKey与RoutingKey一样的队列
-
绑定关系
- 消费者:通过@RabbitListener注解绑定交换机、队列、routingKey,可以根据提示写绑定关系
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* @Description
* @Author konglz
* @Data 2022/9/28 14:14
*/
@Component
public class SpringRabbitListener {
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "directQueue1"),
exchange = @Exchange(name = "konglz.direct",type = ExchangeTypes.DIRECT),
key = {"user","role"}
))
public void listenDirectQueue1(String message){
System.out.println("directQueue1消费者接收到的消息:" + message);
}
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "directQueue2"),
exchange = @Exchange(name = "konglz.direct",type = ExchangeTypes.DIRECT),
key = {"user","menu"}
))
public void listenDirectQueue2(String message){
System.out.println("directQueue2消费者接收到的消息:" + message);
}
}
- 消费者
package com.konglz.publisher;
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class PublisherApplicationTests {
@Autowired
RabbitTemplate rabbitTemplate;
@Test
void direct(){
String exchangeName = "konglz.direct";
String message = "hello i am direct exchange";
//只发送给routingKey为role的队列
//rabbitTemplate.convertAndSend(exchangeName,"role",message);
//只发送给routingKey为user的队列
rabbitTemplate.convertAndSend(exchangeName,"user",message);
}
}
Spring AMQP实现发布、订阅消息模型(Topic)
-
TopicExchange和DirectExchange类似,区别是topic可以带通配符
-
#: 代指0个或多个单词
-
*: 代指一个单词
-
绑定关系
- 消费者
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* @Description
* @Author konglz
* @Data 2022/9/28 14:14
*/
@Component
public class SpringRabbitListener {
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "topicQueue1"),
exchange = @Exchange(name = "konglz.topic", type = ExchangeTypes.TOPIC),
key = {"user.#"}
))
public void listenTopicQueue1(String message){
System.out.println("topicQueue1消费者接收到的消息:" + message);
}
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "topicQueue2"),
exchange = @Exchange(name = "konglz.topic", type = ExchangeTypes.TOPIC),
key = {"#.log"}
))
public void listenTopicQueue2(String message){
System.out.println("topicQueue2消费者接收到的消息:" + message);
}
}
- 生产者
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class PublisherApplicationTests {
@Autowired
RabbitTemplate rabbitTemplate;
@Test
void topic(){
String exchangeName = "konglz.topic";
String message = "模块正在更新!";
//user.# topicQueue1能收到模块正在更新
//rabbitTemplate.convertAndSend(exchangeName,"user.admin", message);
//#.log topicQueue2收到模块正在更新
//rabbitTemplate.convertAndSend(exchangeName,"log", message);
//user.#、#.log topicQueue1、topicQueue2收到模块正在更新
rabbitTemplate.convertAndSend(exchangeName,"user.log", message);
}
}
Spring AMQP消息转换器
-
Spring AMQP发送消息的类型都是Object,底层是jdk实现的有些缺点,一般是哟个json代替
- 性能差
- 存在安全性问题
- 序列化的字符串太长
-
生命一个objectQueue的队列
package com.konglz.consumer.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Description
* @Author konglz
* @Data 2022/9/28 15:32
*/
@Configuration
public class FanoutConfig {
@Bean
public FanoutExchange fanoutExchange(){
return new FanoutExchange("konglz.fanout");
}
@Bean
public Queue fanoutQueue1(){
return new Queue("fanoutQueue1");
}
@Bean
public Binding fanoutBinding1(Queue fanoutQueue1, FanoutExchange fanoutExchange){
return BindingBuilder
.bind(fanoutQueue1)
.to(fanoutExchange);
}
@Bean
public Queue fanoutQueue2(){
return new Queue("fanoutQueue2");
}
@Bean
public Binding fanoutBinding2(Queue fanoutQueue2, FanoutExchange fanoutExchange){
return BindingBuilder
.bind(fanoutQueue2)
.to(fanoutExchange);
}
@Bean
public Queue objectQueue(){
return new Queue("objectQueue");
}
}
- 生产者
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.HashMap;
import java.util.Map;
@SpringBootTest
class PublisherApplicationTests {
@Autowired
RabbitTemplate rabbitTemplate;
@Test
void ObjectQueue(){
Map<String,Object> message = new HashMap<>();
message.put("name","konglz");
message.put("age", "3");
rabbitTemplate.convertAndSend("objectQueue", message);
}
}
-
有上图所知:rabbitmq将我们的对象做了序列化的处理,常见的ObjectInputStream
- 性能差
- 存在安全性问题
- 序列化的字符串太长
-
使用 Json 序列化代替自带的序列化
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-databind.version}</version>
</dependency>
- Json消息转换器注册到spring
@SpringBootApplication
public class PublisherApplication {
public static void main(String[] args) {
SpringApplication.run(PublisherApplication.class, args);
}
@Bean
public MessageConverter messageConverter(){
return new Jackson2JsonMessageConverter();
}
}
- 消费者
//Json消息转换器注册到spring
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
@Bean
public MessageConverter messageConverter(){
return new Jackson2JsonMessageConverter();
}
}
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.Map;
/**
* @Description
* @Author konglz
* @Data 2022/9/28 14:14
*/
@Component
public class SpringRabbitListener {
@RabbitListener(queues = "objectQueue")
public void listenObjectQueue(Map<String,Object> message){
System.out.println("objectQueue接收到消息:" + message);
}
}