网易做相册的网站,用xampp搭建wordpress,网页制作工具的选择与网站整体风格,个人网站源码模板RabbitMQ 官网地址: https://www.rabbitmq.com/ 一个遵循AMQP协议#xff0c;开源面向消息的中间件,支持多种编程语言。 Rabbitmq 能做什么? 逻辑解耦#xff0c;异步的消息任务消息持久化#xff0c;重启不影响削峰#xff0c;大规模的消息处理主要的特点 可靠性#xf…RabbitMQ 官网地址: https://www.rabbitmq.com/ 一个遵循AMQP协议开源面向消息的中间件,支持多种编程语言。 Rabbitmq 能做什么? 逻辑解耦异步的消息任务消息持久化重启不影响削峰大规模的消息处理主要的特点 可靠性持久化传输确认发布确认
可扩展性多个节点可以组成一个集群可动态更改
多语言支持多数编程语言
管理界面有常见的用户界面便于管理和监控 常见的应用场景: 并发请求的压力高可用设计(电商秒杀场景)
异步任务处理结果的回调设计(日志订单异步处理)
系统集成与分布式系统设计(各种子系统的消息同步)。 工作原理 简单介绍生产者和消费者会和服务器建立tcp链接在tcp链接之上会建立多个信道channel通过信道来发送消息生产者生产消息后不直接直接发到队列中而是发到一个交换空间Exchange
Exchange会根据Exchange类型和Routing Key来决定发到哪个队列中消费者在从队列中拿到消息 具体工作模式 名词解释 ExChange :消息交换机决定消息按照什么规则路由到那个对列中去
Queue :消息载体每个消息都会被投到一个或多个队列
Binding:绑定把exchange 和 queue按照路由规则绑定起来
Routing Key: 路由关键字exchage根据这关键字来投递消息
Channel :消息通道客户端的每个连接建立多个channel
Producer :消息生产者用户投递消息的程序
Consumer :消息消费者用于就是接收消息的程序 Exchage工作模式 Fanout: 类似广播转发到所有绑定交换机的Queue
Direct: 类似单播RoutingKey 和 BindingKey完全匹配
Topic : 类似组播转发到符合通配符的Queue
headers:请求头与消息头匹配才能接收到消息 环境配置 通过docker环境配置 # /www/rabbitmq目录可自定义主要用于目录挂载
mkdir -p /www/rabbitmq
# 创建容器
docker run -d --hostname rabbit-node1 --name rabbit-node1 -p 5672:5672 -p15672:15672 -v /www/rabbitmq:/var/lib/rabbitmq rabbitmq:management
# 查看容器状态
docker ps | grep rabbit浏览器打开登录rabbitmq, 入口:http://localhost:15672
默认用户名: guest 密码: guest golang实战 简单基本玩法 //下载类库
go get github.com/streadway/amqp 前期准备代码 //连接信息
const MQURL amqp://imoocuser:imoocuser127.0.0.1:5672/imooc//rabbitMQ结构体
type RabbitMQ struct {conn *amqp.Connectionchannel *amqp.Channel//队列名称QueueName string//交换机名称Exchange string//bind Key 名称Key string//连接信息Mqurl string
}//创建结构体实例
func NewRabbitMQ(queueName string,exchange string ,key string) *RabbitMQ {return RabbitMQ{QueueName:queueName,Exchange:exchange,Key:key,Mqurl:MQURL}
}//断开channel 和 connection
func (r *RabbitMQ) Destory() {r.channel.Close()r.conn.Close()
}
//错误处理函数
func (r *RabbitMQ) failOnErr(err error, message string) {if err ! nil {log.Fatalf(%s:%s, message, err)panic(fmt.Sprintf(%s:%s, message, err))}
} 简单模式 简单模式下 Exchange 和 key是为空的不需要设置 //创建简单模式下RabbitMQ实例
func NewRabbitMQSimple(queueName string) *RabbitMQ {//创建RabbitMQ实例rabbitmq : NewRabbitMQ(queueName,,)var err error//获取connectionrabbitmq.conn, err amqp.Dial(rabbitmq.Mqurl)rabbitmq.failOnErr(err, failed to connect rabbitmq!)//获取channelrabbitmq.channel, err rabbitmq.conn.Channel()rabbitmq.failOnErr(err, failed to open a channel)return rabbitmq
}//简单模式队列生产
func (r *RabbitMQ) PublishSimple(message string) {//1.申请队列如果队列不存在会自动创建存在则跳过创建_, err : r.channel.QueueDeclare(r.QueueName,//是否持久化false,//是否自动删除false,//是否具有排他性false,//是否阻塞处理false,//额外的属性nil,)if err ! nil {fmt.Println(err)}//调用channel 发送消息到队列中r.channel.Publish(r.Exchange,r.QueueName,//如果为true根据自身exchange类型和routekey规则无法找到符合条件的队列会把消息返还给发送者false,//如果为true当exchange发送消息到队列后发现队列上没有消费者则会把消息返还给发送者false,amqp.Publishing{ContentType: text/plain,Body: []byte(message),})
}//simple 模式下消费者
func (r *RabbitMQ) ConsumeSimple() {//1.申请队列如果队列不存在会自动创建存在则跳过创建q, err : r.channel.QueueDeclare(r.QueueName,//是否持久化false,//是否自动删除false,//是否具有排他性false,//是否阻塞处理false,//额外的属性nil,)if err ! nil {fmt.Println(err)}//接收消息msgs, err :r.channel.Consume(q.Name, // queue//用来区分多个消费者, // consumer//是否自动应答true, // auto-ack//是否独有false, // exclusive//设置为true表示 不能将同一个Conenction中生产者发送的消息传递给这个Connection中 的消费者false, // no-local//列是否阻塞false, // no-waitnil, // args)if err ! nil {fmt.Println(err)}forever : make(chan bool)//启用协程处理消息go func() {for d : range msgs {//消息逻辑处理可以自行设计逻辑log.Printf(Received a message: %s, d.Body)}}()log.Printf( [*] Waiting for messages. To exit press CTRLC)-forever} 工作模式 一个消息只能被一个消费者获取(场景:生产消息大于消费消息的时候)更简单模式代码一样只是同事开启了多个消费端,起到负载均衡的作用 订阅模式 该模式下队列为空key为空只需设置交换空间即可消息被投递到多个队列中一个消息被多个消费者消费 //订阅模式创建RabbitMQ实例
func NewRabbitMQPubSub(exchangeName string) *RabbitMQ {//创建RabbitMQ实例rabbitmq : NewRabbitMQ(,exchangeName,)var err error//获取connectionrabbitmq.conn, err amqp.Dial(rabbitmq.Mqurl)rabbitmq.failOnErr(err,failed to connect rabbitmq!)//获取channelrabbitmq.channel, err rabbitmq.conn.Channel()rabbitmq.failOnErr(err, failed to open a channel)return rabbitmq
}//订阅模式生产
func (r *RabbitMQ) PublishPub(message string) {//1.尝试创建交换机err : r.channel.ExchangeDeclare(r.Exchange,fanout,true,false,//true表示这个exchange不可以被client用来推送消息仅用来进行exchange和exchange之间的绑定false,false,nil,)r.failOnErr(err, Failed to declare an exchange)//2.发送消息err r.channel.Publish(r.Exchange,,false,false,amqp.Publishing{ContentType: text/plain,Body: []byte(message),})
}//订阅模式消费端代码
func (r *RabbitMQ) RecieveSub() {//1.试探性创建交换机err : r.channel.ExchangeDeclare(r.Exchange,//交换机类型fanout,true,false,//YES表示这个exchange不可以被client用来推送消息仅用来进行exchange和exchange之间的绑定false,false,nil,)r.failOnErr(err, Failed to declare an exchange)//2.试探性创建队列这里注意队列名称不要写q, err : r.channel.QueueDeclare(, //随机生产队列名称false,false,true,false,nil,)r.failOnErr(err, Failed to declare a queue)//绑定队列到 exchange 中err r.channel.QueueBind(q.Name,//在pub/sub模式下这里的key要为空,r.Exchange,false,nil)//消费消息messges, err : r.channel.Consume(q.Name,,true,false,false,false,nil,)forever : make(chan bool)go func() {for d : range messges {log.Printf(Received a message: %s, d.Body)}}()fmt.Println(退出请按 CTRLC\n)-forever
} 路由模式 在路由模式下一个消息可以被多个消费者获取,该模式生产端可以指定消费端;交换机的类型需要设置为direct,并且需要设置bind key。 /路由模式
//创建RabbitMQ实例
func NewRabbitMQRouting(exchangeName string,routingKey string) *RabbitMQ {//创建RabbitMQ实例rabbitmq : NewRabbitMQ(,exchangeName,routingKey)var err error//获取connectionrabbitmq.conn, err amqp.Dial(rabbitmq.Mqurl)rabbitmq.failOnErr(err,failed to connect rabbitmq!)//获取channelrabbitmq.channel, err rabbitmq.conn.Channel()rabbitmq.failOnErr(err, failed to open a channel)return rabbitmq
}//路由模式发送消息
func (r *RabbitMQ) PublishRouting(message string ) {//1.尝试创建交换机err : r.channel.ExchangeDeclare(r.Exchange,//要改成directdirect,true,false,false,false,nil,)r.failOnErr(err, Failed to declare an exchange)//2.发送消息err r.channel.Publish(r.Exchange,//要设置r.Key,false,false,amqp.Publishing{ContentType: text/plain,Body: []byte(message),})
}
//路由模式接受消息
func (r *RabbitMQ) RecieveRouting() {//1.试探性创建交换机err : r.channel.ExchangeDeclare(r.Exchange,//交换机类型direct,true,false,false,false,nil,)r.failOnErr(err, Failed to declare an exchange)//2.试探性创建队列这里注意队列名称不要写q, err : r.channel.QueueDeclare(, //随机生产队列名称false,false,true,false,nil,)r.failOnErr(err, Failed to declare a queue)//绑定队列到 exchange 中err r.channel.QueueBind(q.Name,//需要绑定keyr.Key,r.Exchange,false,nil)//消费消息messges, err : r.channel.Consume(q.Name,,true,false,false,false,nil,)forever : make(chan bool)go func() {for d : range messges {log.Printf(Received a message: %s, d.Body)}}()fmt.Println(退出请按 CTRLC\n)-forever
} Topic模式话题模式 一个消息可以被多个消费者获取消息的目标queue可用BindingKey以通配符的方式指定。 交换的类型设置为 topic,在接受端通过匹配规则匹配(例如:hello.*.world) //话题模式
//创建RabbitMQ实例
func NewRabbitMQTopic(exchangeName string,routingKey string) *RabbitMQ {//创建RabbitMQ实例rabbitmq : NewRabbitMQ(,exchangeName,routingKey)var err error//获取connectionrabbitmq.conn, err amqp.Dial(rabbitmq.Mqurl)rabbitmq.failOnErr(err,failed to connect rabbitmq!)//获取channelrabbitmq.channel, err rabbitmq.conn.Channel()rabbitmq.failOnErr(err, failed to open a channel)return rabbitmq
}
//话题模式发送消息
func (r *RabbitMQ) PublishTopic(message string ) {//1.尝试创建交换机err : r.channel.ExchangeDeclare(r.Exchange,//要改成topictopic,true,false,false,false,nil,)r.failOnErr(err, Failed to declare an exchange)//2.发送消息err r.channel.Publish(r.Exchange,//要设置r.Key,false,false,amqp.Publishing{ContentType: text/plain,Body: []byte(message),})
}
//话题模式接受消息
//要注意key,规则
//其中“*”用于匹配一个单词“#”用于匹配多个单词可以是零个
//匹配 imooc.* 表示匹配 imooc.hello, 但是imooc.hello.one需要用imooc.#才能匹配到
func (r *RabbitMQ) RecieveTopic() {//1.试探性创建交换机err : r.channel.ExchangeDeclare(r.Exchange,//交换机类型topic,true,false,false,false,nil,)r.failOnErr(err, Failed to declare an exchange)//2.试探性创建队列这里注意队列名称不要写q, err : r.channel.QueueDeclare(, //随机生产队列名称false,false,true,false,nil,)r.failOnErr(err, Failed to declare a queue)//绑定队列到 exchange 中err r.channel.QueueBind(q.Name,//在pub/sub模式下这里的key要为空r.Key,r.Exchange,false,nil)//消费消息messges, err : r.channel.Consume(q.Name,,true,false,false,false,nil,)forever : make(chan bool)go func() {for d : range messges {log.Printf(Received a message: %s, d.Body)}}()fmt.Println(退出请按 CTRLC\n)-forever
} 参考: https://www.cnblogs.com/luotianshuai/p/7469365.html#4199652 转载于:https://www.cnblogs.com/nirao/p/11176137.html