go-micro examples中broker &event &pubsub 学习(broker发布订阅 & micro api Event + micro 订阅 & )

 

examples/broker :  micro/go-micro/broker  发布订阅;

examples/event :  curl 触发 event   +   micro api --handler=event  +    micro service  RegisterSubscriber

examples/pubsub : rpc client  NewPublisher   +  micro  service  micro.RegisterSubscriber

以下是 examples/broker例子

broker 是  发布订阅  的 一个接口

producer/producer.go 代码如下:

package main

import (
	"fmt"
	"github.com/go-acme/lego/v3/log"
	"github.com/micro/go-micro/broker"
	"github.com/micro/go-micro/config/cmd"
	"time"
	//启用 rabbitmq plugin  疑问:从哪里看出 确实使用了rabbitmq? 没有启动 rabbitmq 服务也可以?
	_ "github.com/micro/go-plugins/broker/rabbitmq"
)

var (
	topic = "go.micro.topic.foo"
)

func pub() {
	tick := time.NewTicker(time.Second)
	i := 0

	for _ = range tick.C {
		msg := &broker.Message{
			Header: map[string]string {
				"id" : fmt.Sprintf("%d", i),
			},
			Body : []byte(fmt.Sprintf("%d: %s", i, time.Now().String())),
		}
		if err := broker.Publish(topic, msg); err != nil {
			log.Printf("[pub] failed: %v", err)
		} else {
			fmt.Println("[pub] pubbed message:", string(msg.Body))
		}
		i++
	}
}

func main() {
	cmd.Init()

	if err := broker.Init(); err != nil {
		log.Fatalf("Broker Init error: %v", err)
	}

	if err := broker.Connect(); err != nil {
		log.Fatalf("Broker Connect error: %v", err)
	}

	pub()
}

consumer/consumer.go 代码如下:

package main

import (
	"fmt"
	"github.com/go-acme/lego/v3/log"
	"github.com/micro/go-micro/broker"
	"github.com/micro/go-micro/config/cmd"
	//启用 rabbitmq plugin
	_ "github.com/micro/go-plugins/broker/rabbitmq"
)

var (
	topic = "go.micro.topic.foo"
)

// ???? Example of a shared subscription which receives a subset of messages
func sharedSub() {
	_, err := broker.Subscribe(topic, func(p broker.Event) error {
		fmt.Println("[sub] received message:", string(p.Message().Body), "header", p.Message().Header)
		return nil
	}, broker.Queue("consumer"))
	if err != nil {
		fmt.Println(err)
	}
}


func sub() {
	_, err := broker.Subscribe(topic, func(p broker.Event) error {
		fmt.Println("[sub] received message:", string(p.Message().Body), "header", p.Message().Header)
		return nil
	})
	if err != nil {
		fmt.Println(err)
	}
}

func main() {
	cmd.Init()

	if err := broker.Init(); err != nil {
		log.Fatalf("Broker Init error : %v", err)
	}

	if err := broker.Connect(); err != nil {
		log.Fatalf("Broker Connect error : %v", err)
	}

	//sub()
	sharedSub()
	select{}
}

broker/main.go 代码如下:

package main

import (
	"fmt"
	"github.com/micro/go-micro/broker"
	"github.com/micro/go-micro/config/cmd"
	"log"
	"time"
)

var (
	topic = "go.micro.topic.foo"
)

func pub() {
	tick := time.NewTicker(time.Second)
	i := 0
	for _ = range tick.C {
		msg := &broker.Message{
			Header: map[string]string{
				"id": fmt.Sprintf("%d", i),
			},
			Body: []byte(fmt.Sprintf("%d: %s", i, time.Now().String())),
		}
		if err := broker.Publish(topic, msg); err != nil {
			log.Printf("[pub] failed: %v", err)
		} else {
			fmt.Println("[pub] pubbed message:", string(msg.Body))
		}
		i++
	}
}

func sub() {
	_, err := broker.Subscribe(topic, func(p broker.Event) error {
		fmt.Println("[sub] received message:", string(p.Message().Body), "header", p.Message().Header)
		return nil
	})
	if err != nil {
		fmt.Println(err)
	}
}

func main() {
	cmd.Init()

	if err := broker.Init(); err != nil {
		log.Fatal("Broker Init error: %v", err)
	}

	if err := broker.Connect(); err != nil {
		log.Fatal("Broker Connect error: %v", err)
	}

	go pub()
	go sub()

	//运行 10s 后结束
	<-time.After(time.Second * 10)
}

go.mod 内容如下:

module broker

go 1.13

require (
	github.com/micro/go-micro v1.18.0 // indirect
	github.com/micro/go-plugins v1.5.1 // indirect
)

运行生产者:

[root@liang broker]# go run producer/producer.go 
[pub] pubbed message: 0: 2020-01-15 14:33:04.480061714 +0800 CST m=+1.004096548
[pub] pubbed message: 1: 2020-01-15 14:33:05.480099439 +0800 CST m=+2.004134292
[pub] pubbed message: 2: 2020-01-15 14:33:06.480700434 +0800 CST m=+3.004735261
[pub] pubbed message: 3: 2020-01-15 14:33:07.481066406 +0800 CST m=+4.005101235

查看微服务  services

[root@liang ~]# micro list services

[root@liang ~]# 

观察 : 并没有;

运行消费者:

[root@liang broker]# go run consumer/consumer.go 
[sub] received message: 0: 2020-01-15 14:32:34.721933081 +0800 CST m=+1.004749552 header map[id:0]
[sub] received message: 1: 2020-01-15 14:32:35.72181215 +0800 CST m=+2.004628603 header map[id:1]
[sub] received message: 2: 2020-01-15 14:32:36.722681592 +0800 CST m=+3.005497988 header map[id:2]
[sub] received message: 3: 2020-01-15 14:32:37.722599445 +0800 CST m=+4.005415862 header map[id:3]

再次 查看 微服务 services

[root@liang ~]# micro list services
go.micro.http.broker

观察: 有 :“go.micro.http.broker” 如何解释???

单独运行 /broker/main.go

root@liang broker]# go run main.go 
[pub] pubbed message: 0: 2020-01-15 14:42:55.741880673 +0800 CST m=+1.011918581
[sub] received message: 0: 2020-01-15 14:42:55.741880673 +0800 CST m=+1.011918581 header map[id:0]
[pub] pubbed message: 1: 2020-01-15 14:42:56.742364591 +0800 CST m=+2.012402518
[sub] received message: 1: 2020-01-15 14:42:56.742364591 +0800 CST m=+2.012402518 header map[id:1]
[pub] pubbed message: 2: 2020-01-15 14:42:57.742303571 +0800 CST m=+3.012341509
[sub] received message: 2: 2020-01-15 14:42:57.742303571 +0800 CST m=+3.012341509 header map[id:2]
[pub] pubbed message: 3: 2020-01-15 14:42:58.742109082 +0800 CST m=+4.012147031
[sub] received message: 3: 2020-01-15 14:42:58.742109082 +0800 CST m=+4.012147031 header map[id:3]
[pub] pubbed message: 4: 2020-01-15 14:42:59.743060533 +0800 CST m=+5.013098463
[sub] received message: 4: 2020-01-15 14:42:59.743060533 +0800 CST m=+5.013098463 header map[id:4]
[pub] pubbed message: 5: 2020-01-15 14:43:00.742296028 +0800 CST m=+6.012333992
[sub] received message: 5: 2020-01-15 14:43:00.742296028 +0800 CST m=+6.012333992 header map[id:5]
[pub] pubbed message: 6: 2020-01-15 14:43:01.743094465 +0800 CST m=+7.013132412
[sub] received message: 6: 2020-01-15 14:43:01.743094465 +0800 CST m=+7.013132412 header map[id:6]
[pub] pubbed message: 7: 2020-01-15 14:43:02.742426186 +0800 CST m=+8.012464104
[sub] received message: 7: 2020-01-15 14:43:02.742426186 +0800 CST m=+8.012464104 header map[id:7]
[pub] pubbed message: 8: 2020-01-15 14:43:03.742289218 +0800 CST m=+9.012327134
[sub] received message: 8: 2020-01-15 14:43:03.742289218 +0800 CST m=+9.012327134 header map[id:8]
[root@liang broker]# 

本例子的还有的疑问 : broker 插件的使用 ? 如 micro/go-plugins/broker/rabbitmq,kafka 等

---------------------------------------------

以下是 examples/event 对应的例子

这个例子 使用 micro api  的 事件网关 的功能。

一个 http 消息 被 格式化 为  一个 事件,并把它 发布 到 go-micro  message broker

目录:

srv :  一个服务, 它订阅了  一些事件

srv/proto/pubsub.proto 代码如下:

syntax = "proto3";

message Event {
    //unique id
    string id = 1;
    //unix timestamp;
    int64 timestamp = 2;
    //message
    string message = 3;
}

srv/main.go 代码如下 

package main

import (
	"context"
	"github.com/micro/go-micro"
	//"log"
	"github.com/micro/go-micro/util/log"
	//proto "github.com/micro/go-micro/api/proto"
	proto "event/srv/proto"
)

//当 一个消息收到时,Event 的所有方法都会被执行
type Event struct {

}

func (e *Event) Process(ctx context.Context, event *proto.Event) error {
	log.Logf("Received event %+v\n", event)

	//使用 event 做一些事情

	return nil
}

func main()  {
	service := micro.NewService(
		micro.Name("user"),
	)

	service.Init()

	//注册 subscriber
	micro.RegisterSubscriber("go.micro.evt.user", service.Server(), new(Event))

	if err := service.Run(); err != nil {
		log.Fatal(err)
	}
}

go.mod 代码如下:

module event

go 1.13

require github.com/micro/go-micro v1.18.0 // indirect

使用:

带着 event handler 的设置,启动 micro api;  设置时 —namespace 参数指定的值 通常 被作为topic 名称的一部分。

micro api --handler=event --namespace=go.micro.evt

运行 服务:

go run srv/main.go

Event 格式

 

在接受到消息的最后,这个消息被格式化如下格式:

// A HTTP event as RPC

message Event {

// e.g login

string name = 1;

// uuid

string id = 2;

// unix timestamp of event

int64 timestamp = 3;

// event headers

        map<string, Pair> header = 4;

// the event data

string data = 5;

}

发布 Event

使用 POST 请求 发送 如:

curl -d '{"name": "john"}' http://localhost:8080/user/login

这个请求 将被发送到 topic  “go.micro.evt.user”  event 名 是 “login” 

接受 Event

 

subscirber 注册时的时候 一定要 带着 micro service

subscriber  它接受 proto.Event 类型

 

收到事件后:事件内容如下:

{

name: "user.login",

id: "go.micro.evt.user-user.login-693116e7-f20c-11e7-96c7-f40f242f6897",

timestamp:1515152077,

header: {...},

data: {"name": "john"} 

}

运行 micro api :

[root@liang event]# micro api --handler=event --namespace=go.micro.evt
2020-01-15 15:56:18.597607 I | [api] Registering API Event Handler at /
2020-01-15 15:56:18.601578 I | [api] HTTP API Listening on [::]:8080
2020-01-15 15:56:18.602579 I | [api] Transport [http] Listening on [::]:55779
2020-01-15 15:56:18.602846 I | [api] Broker [http] Connected to [::]:30945
2020-01-15 15:56:18.613099 I | [api] Registry [mdns] Registering node: go.micro.api-6d1890a6-8210-4062-b047-b0022ecad0e9

查看 微服务:

[root@liang ~]# micro list services
go.micro.api
go.micro.http.broker
[root@liang ~]# 

运行 event service

[root@liang event]# go run srv/main.go
2020-01-15 15:58:32.224459 I | Transport [http] Listening on [::]:60565
2020-01-15 15:58:32.224561 I | Broker [http] Connected to [::]:5481
2020-01-15 15:58:32.232237 I | Registry [mdns] Registering node: user-199d8bd9-6c97-49bc-ae64-80bb81679168
2020-01-15 15:58:32.238025 I | Subscribing user-199d8bd9-6c97-49bc-ae64-80bb81679168 to topic: go.micro.evt.user

再次查看 微服务:

[root@liang ~]# micro list services
go.micro.api
go.micro.http.broker
user
[root@liang ~]# 

curl 测试:

[root@liang ~]# curl -d '{"name": "john"}' http://localhost:8080/user/login
You have mail in /var/spool/mail/root
[root@liang ~]# curl -d '{"name": "john"}' http://localhost:8080/user/suceessOrder
You have mail in /var/spool/mail/root
[root@liang ~]# 

event service 收到消息后 的log 如下:

[root@liang event]# go run srv/main.go
2020-01-15 16:14:30.580379 I | Transport [http] Listening on [::]:16217
2020-01-15 16:14:30.580459 I | Broker [http] Connected to [::]:55245
2020-01-15 16:14:30.588822 I | Registry [mdns] Registering node: user-06d7d81f-589c-4b02-87bb-a3ef2e71337f
2020-01-15 16:14:30.594292 I | Subscribing user-06d7d81f-589c-4b02-87bb-a3ef2e71337f to topic: go.micro.evt.user
^[[A2020-01-15 16:15:41.619493 I | Received event id:"suceessOrder" 2:"go.micro.evt.user-suceessOrder-f94ace32-73ba-4135-8f4a-810f62e24b28" 3:1579076141 4:"\n\fContent-Type\x121\n\fContent-Type\x12!application/x-www-form-urlencoded" 4:"\n\nUser-Agent\x12r\n\nUser-Agent\x12dcurl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3 libidn/1.18 libssh2/1.4.2" 4:"\n\x06Accept\x12\r\n\x06Accept\x12\x03*/*" 4:"\n\x0eContent-Length\x12\x14\n\x0eContent-Length\x12\x0216" 5:"{\"name\": \"john\"}" 
event 整理后:
id:"suceessOrder" 
2:"go.micro.evt.user-suceessOrder-f94ace32-73ba-4135-8f4a-810f62e24b28" 
3:1579076141 
4:"\n\fContent-Type\x121\n\fContent-Type\x12!application/x-www-form-urlencoded" 
4:"\n\nUser-Agent\x12r\n\nUser-Agent\x12dcurl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3 libidn/1.18 libssh2/1.4.2" 4:"\n\x06Accept\x12\r\n\x06Accept\x12\x03*/*" 
4:"\n\x0eContent-Length\x12\x14\n\x0eContent-Length\x12\x0216" 
5:"{\"name\": \"john\"}" 

--------------------------------------------------------

以下是 examples/pubsub 例子:

这是 一个 通过 client/server 接口 来 实现 pubsub 的例子。

pubsub 在 client/server 层面 它 很像 RPC 不同的是,它使用异步通信。它使用broker 来发送消息 而不是 通过使用 transport 接口。

它能够 去 编码 metadata 到conext, messages 的传输 携带 context。

目录:

srv/proto/pubsub.proto 代码如下:

syntax = "proto3";

// Example message
message Event {
    // unique id
    string id = 1;
    // unix timestamp
    int64 timestamp = 2;
    // message
    string message = 3;
}

srv/main.go 代码如下:

package main

import (
	"context"
	"github.com/micro/go-micro/metadata"
	"github.com/micro/go-micro/server"
	"github.com/micro/go-micro/util/log"
	"github.com/micro/go-micro"
	proto "pubsub/srv/proto"
)

type Sub struct {}

func (s *Sub) Process(ctx context.Context, event *proto.Event) error {
	md, _ := metadata.FromContext(ctx)
	log.Logf("[pubsub.1] Received event %+v with metadata %+v\n", event, md)

	//使用 event 做一些事情

	return nil
}

//替代地,也可以使用func
func subEv (ctx context.Context, event *proto.Event) error {
	md, _ := metadata.FromContext(ctx)
	log.Logf("[pubsub.2] Received event %+v with metadata %+v\n", event, md)

	//使用event 做一些事情
	return nil
}

func main() {
	service := micro.NewService(
		micro.Name("go.micro.srv.pubsub"),
	)

	//解析命令行
	service.Init()

	//注册 subscriber
	micro.RegisterSubscriber("example.topic.pubsub.1", service.Server(), new(Sub))

	//使用上 queue 的 subscriber 的注册。
	micro.RegisterSubscriber("example.topic.pubsub.2", service.Server(),subEv, server.SubscriberQueue("queue.pubsub"))

	if err := service.Run(); err != nil {
		log.Fatal(err)
	}


}

cli/main.go 代码如下:

package main

import (
	"context"
	"fmt"
	"github.com/go-log/log"
	"github.com/pborman/uuid"
	"github.com/micro/go-micro"
	"time"
	proto "pubsub/srv/proto"
)

//使用 publisher 发送 events
func sendEv(topic string, p micro.Publisher) {
	t := time.NewTicker(time.Second)

	for _ = range t.C {
		ev := &proto.Event{
			Id : uuid.NewUUID().String(),
			Timestamp: time.Now().Unix(),
			Message: fmt.Sprintf("Message you all day on %s", topic),
		}

		log.Logf("publishing %v", ev)

		//发布 一个 event
		if err := p.Publish(context.Background(), ev); err != nil {
			log.Logf("error publishing: %v", err)
		}
	}
}

func main() {
	//创建服务
	service := micro.NewService(
		micro.Name("go.micro.cli.pubsub"),
	)

	//解析 命令行
	service.Init()

	//创建 发布器
	pub1 := micro.NewPublisher("example.topic.pubsub.1", service.Client())
	pub2 := micro.NewPublisher("example.topic.pubsub.2", service.Client())

	//发布到 topic 1
	go sendEv("example.topic.pubsub.1", pub1)
	//发布到 topic 2
	go sendEv("example.topic.pubsub.2", pub2)

	//阻塞
	select{}

}

go.mod 内容如下:

module pubsub

go 1.13

require (
	github.com/micro/go-micro v1.18.0 // indirect
	github.com/pborman/uuid v1.2.0 // indirect
)

运行: srv/main.go

[root@liang pubsub]# go run srv/main.go 
2020-01-15 17:42:51.544857 I | Transport [http] Listening on [::]:22856
2020-01-15 17:42:51.544991 I | Broker [http] Connected to [::]:51092
2020-01-15 17:42:51.545707 I | Registry [mdns] Registering node: go.micro.srv.pubsub-6e4cb817-9431-4dd1-b2b3-acf0f56fd14a
2020-01-15 17:42:51.555496 I | Subscribing go.micro.srv.pubsub-6e4cb817-9431-4dd1-b2b3-acf0f56fd14a to topic: example.topic.pubsub.1
2020-01-15 17:42:51.557270 I | Subscribing go.micro.srv.pubsub-6e4cb817-9431-4dd1-b2b3-acf0f56fd14a to topic: example.topic.pubsub.2

查看 微服务 

[root@liang ~]# micro list services
go.micro.http.broker
go.micro.srv.pubsub
[root@liang ~]# 

运行 client

[root@liang pubsub]# go run cli/main.go 

再次查看服务:

[root@liang ~]# micro list services
go.micro.http.broker
go.micro.srv.pubsub
[root@liang ~]# 

服务端 的log:

[root@liang pubsub]# go run srv/main.go 
2020-01-15 17:41:21.616840 I | Transport [http] Listening on [::]:65423
2020-01-15 17:41:21.616918 I | Broker [http] Connected to [::]:31354
2020-01-15 17:41:21.625304 I | Registry [mdns] Registering node: go.micro.srv.pubsub-09737d5a-9a08-4c6a-b880-53ea2a49def8
2020-01-15 17:41:21.642703 I | Subscribing go.micro.srv.pubsub-09737d5a-9a08-4c6a-b880-53ea2a49def8 to topic: example.topic.pubsub.1
2020-01-15 17:41:21.644025 I | Subscribing go.micro.srv.pubsub-09737d5a-9a08-4c6a-b880-53ea2a49def8 to topic: example.topic.pubsub.2
2020-01-15 17:41:52.142755 I | [pubsub.1] Received event id:"42429a90-377b-11ea-b33c-000c297458cb" timestamp:1579081312 message:"Message you all day on example.topic.pubsub.1"  with metadata map[Content-Type:application/protobuf Micro-From-Service:go.micro.cli.pubsub Micro-Id:cd98f557-7d3e-43a8-b18b-71f538c6bb14 Micro-Topic:example.topic.pubsub.1]
2020-01-15 17:41:52.143912 I | [pubsub.2] Received event id:"4242a28b-377b-11ea-b33c-000c297458cb" timestamp:1579081312 message:"Message you all day on example.topic.pubsub.2"  with metadata map[Content-Type:application/protobuf Micro-From-Service:go.micro.cli.pubsub Micro-Id:1bf7d975-f483-46dc-9c2e-e4ce0fcff76b Micro-Topic:example.topic.pubsub.2]
2020-01-15 17:41:53.039169 I | [pubsub.1] Received event id:"42db227c-377b-11ea-b33c-000c297458cb" timestamp:1579081313 message:"Message you all day on example.topic.pubsub.1"  with metadata map[Content-Type:application/protobuf Micro-From-Service:go.micro.cli.pubsub Micro-Id:60d343dc-3826-4a59-9c96-fa27a8cd3118 Micro-Topic:example.topic.pubsub.1]

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值