使用go micro开发异步微服务

概述

使用go micro不仅可以开发传统模式的同步调用的微服务,也可以基于事件实现异步调用模式的微服务。
在基于事件的模式下,服务端和客户端可以通过事件进行通信,而不必等待另外一端完成调用,才能进行下一步的工作。
发布/订阅是一种基于事件的架构模型。go micor使用一个消息代理接口来实现发布/订阅这种模型。
一个go micro客户端可以订阅一个主题,一个go micro服务端可以向这个主题发布消息。在这种情况下,事件流是从右向左的:
事件流
go micro有个默认的消息代理,我们也可以很容易的使用现在比较流行的消息服务器:RabbitMQ、Kafka等替换这个默认的消息代理。在这里我们使用的是默认的消息代理。

开发

在这里我们会简单的开发一个例子:服务端每15秒发送一个通知。在同步调用的场景下,这个服务是需要客户端调用的。但在发布/订阅模式下,服务会把通知发送到一个客户端可订阅的主题上,然后客户端会处理这些主题上的通知;

服务端开发

安装依赖

go get github.com/golang/protobuf
go get github.com/micro/go-micro

定义服务

和所有gRpc服务一样,我们需要首先使用protocol buffers,对我们的服务和需要发布到主题上的事件进行定义:

syntax = "proto3";

option go_package =  "protofiles";

message Event {
  string city = 1;
  int64 timestamp = 2;
  int64 temperature = 3;
}

编译服务

在我们完成服务定义后,需要使用protoc对protocol buffers文件进行编译形成服务端桩文件:

protoc -I=. --micro_out=. --go_out=. protofiles/weather.proto

开发服务

一个事件发布者实例可以通过micro.NewPublisher方法进行创建。这个方法需要两个参数:一个是主题名称,另一个是service.Client(),代码如下:

func main() {
	service := micro.NewService(micro.Name("weather"))
	p := micro.NewPublisher("alerts", service.Client())
	go func() {
		for now := range time.Tick(15 * time.Second) {
			log.Println("Publishering weather alerts to topic: alerts")
			p.Publish(context.TODO(), &protofiles.Event{
				City: "beijing",
				Timestamp: now.UTC().Unix(),
				Temperature: 28,
			})
		}
	}()
	if err := service.Run(); err != nil {
		log.Fatalln(err.Error())
	}
}

运行服务

在我们编写完服务端代码后,就可以运行服务了,在出现下列内容时,就可以判断服务端已经正常运行了,并向主题发送了消息:
正常运行

客户端开发

在初始阶段,客户端开发过程与服务端开发相同,需要进行编译和桩代码的生成。具体内容可参考服务端开发相应部分。
下面我们主要看看具体的开发是如何实现的。

开发客户端

开发客户端的具体步骤如下

实现处理逻辑

为了实现具体的逻辑,我们需要先实现一个消息的处理函数:

func processEvent(ctx context.Context, event *protofiles.Event) error {
	log.Println("Got alert:", event)
	return nil
}

在这里我们实现逻辑比较简单,只是把接到的消息打印到控制台上。这个函数在接收到消息后就会执行。

编排处理逻辑

在我们编写完处理逻辑后,我们需要把这个逻辑与主题关联起来。使用micro.RegisterSubscriber可以达到这个目的:

func main() {
	service := micro.NewService(micro.Name("weather_client"))
	service.Init()
	micro.RegisterSubscriber("alerts", service.Server(), processEvent)
	if err := service.Run(); err != nil {
		log.Fatalln(err.Error())
	}
}

运行客户端

在我们运行客户端代码时,我们从下面的信息中可以看到,我们客户端运行正常,并可以正常处理消息:
正常运行

代码参考

全部的代码下载

发布了6 篇原创文章 · 获赞 6 · 访问量 593

猜你喜欢

转载自blog.csdn.net/qq_20996551/article/details/105771821
今日推荐