订阅消息
首先,我们定义消息处理程序,./subscriber/micro.go:
package subscriber
import (
"context"
log "github.com/micro/go-micro/v2/logger"
"micro-hello/proto/hello"
)
type Micro struct{}
func (e *Micro) Handle(ctx context.Context, msg *hello.Message) error {
log.Info("Handler Received message: ", msg.Say)
return nil
}
func Handler(ctx context.Context, msg *hello.Message) error {
log.Info("Function Received message: ", msg.Say)
return nil
}
方法与结构体都可以用来进行消息,只要标志是func(context.Context, v interface{}) error
方法的第二个参数是*hello.Message,micro会自动将消息解码,所以我们可以直接在方法中使用。
在准备好消息处理程序,我们要注册它,相关代码在./main.go:
// Register Struct as Subscriber
micro.RegisterSubscriber("go.micro.service.micro", service.Server(), new(subscriber.Micro))
// RegisterSubscriber is syntactic sugar for registering a subscriber
func RegisterSubscriber(topic string, s server.Server, h interface{}, opts ...server.SubscriberOption) error {
return s.Subscribe(s.NewSubscriber(topic, h, opts...))
}
消息队列的topic是go.micro.service.micro
如果想设置订阅者的属性,可以添加参数,共有4总参数:
- 1 server.DisableAutoAck() 禁用消息自动确认
// DisableAutoAck will disable auto acking of messages
// after they have been handled.
func DisableAutoAck() SubscriberOption {
return func(o *SubscriberOptions) {
o.AutoAck = false
}
- 2 server.SubscriberContext(ctx context.Context) 设置上下文信息
// SubscriberContext set context options to allow broker SubscriberOption passed
func SubscriberContext(ctx context.Context) SubscriberOption {
return func(o *SubscriberOptions) {
o.Context = ctx
}
}
- 3 server.InternalSubscriber(b bool) 指定不将订阅者发布到服务发现系统中
// Internal Subscriber options specifies that a subscriber is not advertised
// to the discovery system.
func InternalSubscriber(b bool) SubscriberOption {
return func(o *SubscriberOptions) {
o.Internal = b
}
- 4 server.SubscriberQueue(n string) 在分布式消息定义中共享队列名称
// Shared queue name distributed messages across subscribers
func SubscriberQueue(n string) SubscriberOption {
return func(o *SubscriberOptions) {
o.Queue = n
}
}
如果存在多个订阅者,并且队列名称不同,那么,每个队列都可以接收到全部信息
micro 会默认给每个队列创建唯一名称,如果想多个订阅者共享一个消息,则需要指定队列名称
// Register Struct as Subscriber
micro.RegisterSubscriber("go.micro.service.micro", service.Server(), new(subscriber.Micro),
server.SubscriberQueue("foo_bar"))
考虑到分布式系统中的各种情况,我的建议是:最好指定队列名称,就算只有一个实例
消息发布
我们创建发布消息的项目,结构如下:
luslin@local:~/go/workspace/tools/micro-hello-pub$ tree
.
├── go.mod
├── go.sum
├── main.go
├── plugin.go
└── proto
└── hello
├── micro.pb.go
├── micro.pb.micro.go
└── micro.proto
其中main.go:
扫描二维码关注公众号,回复:
11273221 查看本文章
package main
import (
"context"
"github.com/micro/go-micro/v2"
"log"
hello "micro-hello-pub/proto/hello"
"time"
)
func main() {
// New Service
service := micro.NewService(
micro.Name("com.foo.service.micro.pub"),
micro.Version("latest"),
)
service.Init()
pub := micro.NewEvent("com.foo.service.hello", service.Client())
// publish message every second
for now := range time.Tick(time.Second) {
if err := pub.Publish(context.TODO(), &hello.Message{Say: now.String()}); err != nil {
log.Fatal("publish err:", err)
}
}
}
注意pub中的topic要与service中的相同。
启动pub与server后,可以看到server中:
2020-05-25 08:54:14 file=micro.go:12 level=info Handler Received message: 2020-05-25 08:54:14.587265804 +0800 CST m=+55.031197081
2020-05-25 08:54:15 file=micro.go:12 level=info Handler Received message: 2020-05-25 08:54:15.587557674 +0800 CST m=+56.031488942
2020-05-25 08:54:16 file=micro.go:12 level=info Handler Received message: 2020-05-25 08:54:16.587294378 +0800 CST m=+57.031225677
2020-05-25 08:54:17 file=micro.go:12 level=info Handler Received message: 2020-05-25 08:54:17.587242906 +0800 CST m=+58.031174190