When looking at the company's redis queue
recently, I found that the bottom layer is go-zero
of queue
. In this article, take a look at queue
, and hope to learn about the minimal design practice of mq
use
Combined with other mq
use experience, the basic use process:
- Create
producer
orconsumer
- Start
mq
- Production news/consumption news
Corresponds to queue
, which is roughly this:
Create queue
// 生产者创建工厂
producer := newMockedProducer()
// 消费者创建工厂
consumer := newMockedConsumer()
// 将生产者以及消费者的创建工厂函数传递给 NewQueue()
q := queue.NewQueue(func() (Producer, error) {
return producer, nil
}, func() (Consumer, error) {
return consumer, nil
})
Let's see what build conditions are needed for NewQueue
producer constructor
consumer constructor
Pass the factory functions of both parties to queue
for execution and retry.
The purpose of these two needs is to encapsulate the construction of the producer/consumer and the production/consumption of the message in mq
, and to hand over the entire logic of the producer/consumer to the developer for processing:
type (
// 开发者需要实现此接口
Producer interface {
AddListener(listener ProduceListener)
Produce() (string, bool)
}
...
// ProducerFactory定义了生成Producer的方法
ProducerFactory func() (Producer, error)
)
- In fact, the logic of the producer is handed over to the developer to complete it.
mq
only responsible for the message delivery and scheduling between producers/consumers. - The design of the factory method is to hand over the two tasks of the producer itself and the production message to
queue
for scheduling or retrying.
Production msg
The production news must of course go back to the producer itself:
type mockedProducer struct {
total int32
count int32
// 使用waitgroup来模拟任务的完成
wait sync.WaitGroup
}
// 实现 Producer interface 的方法:Produce()
func (p *mockedProducer) Produce() (string, bool) {
if atomic.AddInt32(&p.count, 1) <= p.total {
p.wait.Done()
return "item", true
}
time.Sleep(time.Second)
return "", false
}
The producer programming in queue
Produce()
: The logic of the production message is written by the developerAddListener()
: Producer
Consume msg
Similar to the producer:
type mockedConsumer struct {
count int32
}
func (c *mockedConsumer) Consume(string) error {
atomic.AddInt32(&c.count, 1)
return nil
}
Start queue
Start, and then verify whether the data transmission between the producer and consumer mentioned above is successful:
func TestQueue(t *testing.T) {
producer := newMockedProducer(rounds)
consumer := newMockedConsumer()
// 创建 queue
q := NewQueue(func() (Producer, error) {
return producer, nil
}, func() (Consumer, error) {
return consumer, nil
})
// 当生产者生产完毕,执行 Stop() 关闭生产端生产
go func() {
producer.wait.Wait()
// mq生产端停止生产,不是mq本身 Stop 运行
q.Stop()
}()
// 启动
q.Start()
// 验证生产消费端是否消息消费完成
assert.Equal(t, int32(rounds), atomic.LoadInt32(&consumer.count))
}
The above is the queue
code for getting started with 0609b51924193a. Developers can freely define the production/consumption logic of the producer/consumer according to the actual situation of their business.
Overall design
The overall process is as shown above:
- All communications are
channel
out by 0609b5192419ca - By adding the listener
listener
and the event triggerevent
, it is equivalent to separating the trigger logic - The producer has
produceone
, this is the logic of producing the message, but theProduce()
is written by the developer [interface
above is exactly this function] - Similarly for consumers,
Consume()
The basic message flow enters the above picture and the above description. We will leave the specific code analysis to the next article. Our analysis, especially how to control channel
is the core of the entire design.
to sum up
This article briefly introduces the design queue
from the use and analysis of the entire architecture. In the next article, we will go into the source code, analyze the internal message flow and channel
control.
go-zero
more design and implementation articles about 0609b519241af0, you can continue to follow us. Welcome everyone to pay attention and use.
project address
https://github.com/tal-tech/go-zero
Welcome to go-zero and star support us!
WeChat Exchange Group
Follow the "microservice practice" official account and reply to the group to get the QR code of the community group.
For the go-zero series of articles, please refer to the "Microservice Practice" public account
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。