简单理解消息队列
- 简单图示
-
把数据放到消息队列叫做生产者
-
从消息队列中获取数据叫做消费者
-
消息队列
- 概念:生产者和消费者之间的一个中间件。本质是一个队列。
-
消息队列能做的事情(为什么)
- 解耦(各个的部分,互不影响)
- 异步处理(每个部分异步处理,缩短时间)
- 削峰/限流(降低服务器的压力)
-
消息队列要注意的问题
- 数据保存
- 高可用性(可以在别的服务器上也可以运行)
- 删除消息
-
一条消息的产生-》消息队列-》消费-》完整的流程
- 用户触发某件事情,发起某个请求,生成一个数据
- 将信息放到消息队列中
- 中间件轮询,直到消费者获取到自己想要的数据
- 使用这条数据进行处理其他事情
-
简单演示,一个生产者对多消费者
- 思路
- 参考代码
server.go
package main
import(
"fmt"
"log"
"net/http"
)
func main(){
mux := http.NewServeMux()
mux.HandleFunc("/Login",Login)
mux.HandleFunc("/Consumer1",Consumer1)
mux.HandleFunc("/Consumer2",Consumer2)
mux.HandleFunc("/Consumer3",Consumer3)
if err:=http.ListenAndServe(":8080",mux);err!=nil{
log.Fatal(err)
}
}
/*一个生产者和多消费者*/
// 假定一个生产者
func Login(w http.ResponseWriter,r *http.Request){
if r.Method != "GET"{
return
}
fmt.Fprint(w,"生产者来了")
}
// 多个消费者
func Consumer1(w http.ResponseWriter,r *http.Request){
if r.Method != "GET"{
return
}
fmt.Fprint(w,"消费者1")
}
func Consumer2(w http.ResponseWriter,r *http.Request){
if r.Method != "GET"{
return
}
fmt.Fprint(w,"消费者2")
}
func Consumer3(w http.ResponseWriter,r *http.Request){
if r.Method != "GET"{
return
}
fmt.Fprint(w,"消费者3")
}
client.go
package main
import(
"fmt"
"sync"
"net/http"
"io/ioutil"
)
type Message struct{
Data string
}
var wg sync.WaitGroup
// 使用切片充当队列
var messages []*Message
func main(){
fmt.Println("客户端这边执行消息队列")
producer()
wg.Add(3)
// 轮询,获取消息
for{
if len(messages)>0{
// 按需获取消息
if messages[0]!=nil{
go comsumer("Consumer1")
go comsumer("Consumer2")
go comsumer("Consumer3")
wg.Wait()
break
}
}
}
fmt.Println("打印结果")
}
// 生产者
func producer()error{
mg := Message{}
res,err := http.Get("http://localhost:8080/Login")
if err!=nil{
fmt.Println("err :",err)
return err
}
defer res.Body.Close()
data,err := ioutil.ReadAll(res.Body)
if err!=nil{
fmt.Println("err:",err)
return err
}
fmt.Println(string(data))
mg.Data = string(data)
messages = append(messages,&mg)
return nil
}
// 消费者
func comsumer(url string)error{
defer wg.Done()
mg := Message{}
res,err := http.Get("http://localhost:8080/"+url)
if err!=nil{
fmt.Println("err :",err)
return err
}
defer res.Body.Close()
data,err := ioutil.ReadAll(res.Body)
if err!=nil{
fmt.Println("err:",err)
return err
}
fmt.Println(string(data))
mg.Data = string(data)
messages = append(messages,&mg)
return nil
}
-
输出结果
客户端这边执行消息队列 生产者来了 消费者2 消费者3 消费者1 打印结果
-
明确观点:本人觉得,消息队列是客户端和服务端的一个中间插件
-
学习资料