grpc之发布订阅

  1. 获取docker的pubsub包
go get  github.com/moby/pubsub
  1. 基于之前的golang版基础上实现
  2. 添加proto pubsub.proto
syntax = "proto3";
//option java_package = "com.colobu.rpctest";
package pubsubService;
option go_package = "/";
// The greeting service definition.
service PubSubService {
  // Sends a greeting
  rpc Publish (Info) returns (Info) {}
  rpc Subscribe(Info) returns(stream Info){}
}

message Info {
  string Content = 1;
}

生成文件

protoc --go_out=. --go-grpc_out=. pubsub.proto
  1. 在server文件夹下新建pubsubSeervice.go
package server

import (
	"context"
	"github.com/moby/pubsub"
	psb "grpc-golang/proto/pubsubS"
	"strings"
)

type PubSubService struct {
	pub *pubsub.Publisher
	psb.UnimplementedPubSubServiceServer
}

func (p *PubSubService) Publish(ctx context.Context, in *psb.Info) (*psb.Info, error) {
	p.pub.Publish(in.Content)
	return in, nil
}

func (p *PubSubService) Subscribe(in *psb.Info, stream psb.PubSubService_SubscribeServer) error {
	ch := p.pub.SubscribeTopic(func(v interface{}) bool {
		if key, ok := v.(string); ok {
			if strings.HasPrefix(key, in.Content) {
				return true
			}
		}
		return false
	})

	for v := range ch {
		if err := stream.Send(&psb.Info{Content: v.(string)}); err != nil {
			return err
		}
	}

	return nil
}

  1. register文件添加服务注册
ps := &PubSubService{pub: pubsub.NewPublisher(100*time.Millisecond, 10)}
pubsubS.RegisterPubSubServiceServer(s, ps)
  1. 添加发布和订阅客户端 pubClient.go
package main

import (
	"context"
	"flag"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	rpsb "grpc-golang/proto/pubsubS"
	"log"
)

type PAuth struct {
}

func (c PAuth) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
	//TODO implement me
	return map[string]string{
		"accessToken": "65794a3163325679546d46745a534936496e647463794973496e426863334e5862334a6b496a6f694d54497a4e445532496e303d",
	}, nil
}

func (c PAuth) RequireTransportSecurity() bool {
	return false
}
func main() {
	var addr = flag.String("addr", "192.168.2.127:50051", "the address to connect to")
	flag.Parse()
	var opts []grpc.DialOption
	opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
	opts = append(opts, grpc.WithPerRPCCredentials(new(PAuth)))
	conn, err := grpc.Dial(*addr, opts...)
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()

	client := rpsb.NewPubSubServiceClient(conn)

	_, err = client.Publish(
		context.Background(), &rpsb.Info{Content: "test"},
	)
	if err != nil {
		log.Fatal(err)
	}
	_, err = client.Publish(
		context.Background(), &rpsb.Info{Content: "2342343242"},
	)
	if err != nil {
		log.Fatal(err)
	}
}

subClient.go

package main

import (
	"context"
	"flag"
	"fmt"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	rpsb "grpc-golang/proto/pubsubS"
	"io"
	"log"
)

type SAuth struct {
}

func (c SAuth) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
	//TODO implement me
	return map[string]string{
		"accessToken": "65794a3163325679546d46745a534936496e647463794973496e426863334e5862334a6b496a6f694d54497a4e445532496e303d",
	}, nil
}

func (c SAuth) RequireTransportSecurity() bool {
	return false
}
func main() {
	var addr = flag.String("addr", "192.168.2.127:50051", "the address to connect to")
	flag.Parse()
	var opts []grpc.DialOption
	opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
	opts = append(opts, grpc.WithPerRPCCredentials(new(SAuth)))
	conn, err := grpc.Dial(*addr, opts...)
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()

	client := rpsb.NewPubSubServiceClient(conn)
	stream, err := client.Subscribe(
		context.Background(), &rpsb.Info{Content: ""},
	)
	if err != nil {
		log.Fatal(err)
	}

	for {
		reply, err := stream.Recv()
		if err != nil {
			if err == io.EOF {
				break
			}
			log.Fatal(err)
		}

		fmt.Println(reply.GetContent())
	}
}

  1. 启动测试
go run server.go
go client/subClient.go
go client/pubClient.go

image image 8. postman测试 image image