golang微服务框架go-micro使用 (四) Pub/Sub

订阅消息

首先,我们定义消息处理程序,./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

猜你喜欢

转载自blog.csdn.net/luslin1711/article/details/106325360