简单理解消息队列

  • 简单图示

  • 把数据放到消息队列叫做生产者
  • 从消息队列中获取数据叫做消费者
  • 消息队列
    • 概念:生产者和消费者之间的一个中间件。本质是一个队列。
  • 消息队列能做的事情(为什么)
    • 解耦(各个的部分,互不影响)
    • 异步处理(每个部分异步处理,缩短时间)
    • 削峰/限流(降低服务器的压力)
  • 消息队列要注意的问题
    • 数据保存
    • 高可用性(可以在别的服务器上也可以运行)
    • 删除消息
  • 一条消息的产生-》消息队列-》消费-》完整的流程

    • 用户触发某件事情,发起某个请求,生成一个数据
    • 将信息放到消息队列中
    • 中间件轮询,直到消费者获取到自己想要的数据
    • 使用这条数据进行处理其他事情
  • 简单演示,一个生产者对多消费者

    • 思路

    • 参考代码

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
    打印结果
  • 明确观点:本人觉得,消息队列是客户端和服务端的一个中间插件

  • 学习资料

猜你喜欢

转载自www.cnblogs.com/MyUniverse/p/11626259.html