简单理解消息队列

  • 简单图示

  • 把数据放到消息队列叫做生产者

  • 从消息队列中获取数据叫做消费者

  • 消息队列

    • 概念:生产者和消费者之间的一个中间件。本质是一个队列。
  • 消息队列能做的事情(为什么)

    • 解耦(各个的部分,互不影响)
    • 异步处理(每个部分异步处理,缩短时间)
    • 削峰/限流(降低服务器的压力)
  • 消息队列要注意的问题

    • 数据保存
    • 高可用性(可以在别的服务器上也可以运行)
    • 删除消息
  • 一条消息的产生-》消息队列-》消费-》完整的流程

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

    • 思路

    • 参考代码

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

  • 学习资料

posted @ 2019-10-06 00:33  Myuniverse  阅读(352)  评论(0编辑  收藏  举报