grpcの使い方

最初のステップは、環境をインストールすることです

公式ウェブサイトのインストールコマンド:

go get -u google.golang.org/grpc

使用されていないようで、サーバーに接続することすらできません。VPNを切断しても役に立たないのです。ラウンドアバウトでインストールする方法はありません。とにかく、githubからコードを入手して、githubから複製するだけです。必要なライブラリにはgrpc-go、golang / net、golang /テキスト、protobuf / proto、protobuf / protoc-gen-go、google / go-genproto

# 如果已经安装了proto(编译proto文件的工具)和protoc-gen-go(proto将proto文件编译成go语言形式的插件)的话就不用安装了
go get -u github.com/golang/protobuf/{proto,protoc-gen-go}

# 下载grpc-go
git clone https://github.com/grpc/grpc-go.git $GOPATH/src/google.golang.org/grpc

# 下载golang/net
git clone https://github.com/golang/net.git $GOPATH/src/golang.org/x/net

# 下载golang/text
git clone https://github.com/golang/text.git $GOPATH/src/golang.org/x/text

# 下载go-genproto
git clone https://github.com/google/go-genproto.git $GOPATH/src/google.golang.org/genproto

# 安装
cd $GOPATH/src/
go install google.golang.org/grpc

 

2番目のステップは、protoファイルを書き込むことです

メッセージを作成します。メッセージはパラメーターです。通常、要求パラメーターと応答パラメーターがあります。

インターフェイスを記述します。インターフェイスのメソッドは、クライアントとサーバーが呼び出しに使用します

$ GOPATH / src / helloworld / helloworld / helloworld.protoコード:

syntax = "proto3";

package helloworld;

//定义服务
service Greeter{ //定义了这么一个接口,protoc这个工具将会生成两个,一个是client一个是server,因为这是一个rpc接口,里面的方法SayHello,客户端会调用这个方法,调用的这个请求会发送给服务端,服务端那边也要实现,服务端那边实现,客户端这边用
    rpc SayHello(HelloRequest) returns(HelloReply){}; //接口中的方法
}
message HelloRequest{ //方法的请求参数
    string name = 1;
}
message HelloReply{ //方法的响应参数
    string message = 1;
}

protocを介してgoコードを生成します。

$ GOPATH / src / helloworld / helloworld / helloworld.pb.go代码

// Code generated by protoc-gen-go. DO NOT EDIT.
// source: helloworld/helloworld.proto

package helloworld

import (
	"context"
	"fmt"
	"github.com/golang/protobuf/proto"
	"google.golang.org/grpc"
	"math"
)

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package

type HelloRequest struct {
	Name                 string   `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *HelloRequest) Reset()         { *m = HelloRequest{} }
func (m *HelloRequest) String() string { return proto.CompactTextString(m) }
func (*HelloRequest) ProtoMessage()    {}
func (*HelloRequest) Descriptor() ([]byte, []int) {
	return fileDescriptor_73149fedf49f4319, []int{0}
}

func (m *HelloRequest) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_HelloRequest.Unmarshal(m, b)
}
func (m *HelloRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_HelloRequest.Marshal(b, m, deterministic)
}
func (m *HelloRequest) XXX_Merge(src proto.Message) {
	xxx_messageInfo_HelloRequest.Merge(m, src)
}
func (m *HelloRequest) XXX_Size() int {
	return xxx_messageInfo_HelloRequest.Size(m)
}
func (m *HelloRequest) XXX_DiscardUnknown() {
	xxx_messageInfo_HelloRequest.DiscardUnknown(m)
}

var xxx_messageInfo_HelloRequest proto.InternalMessageInfo

func (m *HelloRequest) GetName() string {
	if m != nil {
		return m.Name
	}
	return ""
}

type HelloReply struct {
	Message              string   `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *HelloReply) Reset()         { *m = HelloReply{} }
func (m *HelloReply) String() string { return proto.CompactTextString(m) }
func (*HelloReply) ProtoMessage()    {}
func (*HelloReply) Descriptor() ([]byte, []int) {
	return fileDescriptor_73149fedf49f4319, []int{1}
}

func (m *HelloReply) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_HelloReply.Unmarshal(m, b)
}
func (m *HelloReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_HelloReply.Marshal(b, m, deterministic)
}
func (m *HelloReply) XXX_Merge(src proto.Message) {
	xxx_messageInfo_HelloReply.Merge(m, src)
}
func (m *HelloReply) XXX_Size() int {
	return xxx_messageInfo_HelloReply.Size(m)
}
func (m *HelloReply) XXX_DiscardUnknown() {
	xxx_messageInfo_HelloReply.DiscardUnknown(m)
}

var xxx_messageInfo_HelloReply proto.InternalMessageInfo

func (m *HelloReply) GetMessage() string {
	if m != nil {
		return m.Message
	}
	return ""
}

func init() {
	proto.RegisterType((*HelloRequest)(nil), "helloworld.HelloRequest")
	proto.RegisterType((*HelloReply)(nil), "helloworld.HelloReply")
}

func init() { proto.RegisterFile("helloworld/helloworld.proto", fileDescriptor_73149fedf49f4319) }

var fileDescriptor_73149fedf49f4319 = []byte{
	// 144 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xce, 0x48, 0xcd, 0xc9,
	0xc9, 0x2f, 0xcf, 0x2f, 0xca, 0x49, 0xd1, 0x47, 0x30, 0xf5, 0x0a, 0x8a, 0xf2, 0x4b, 0xf2, 0x85,
	0xb8, 0x10, 0x22, 0x4a, 0x4a, 0x5c, 0x3c, 0x1e, 0x20, 0x5e, 0x50, 0x6a, 0x61, 0x69, 0x6a, 0x71,
	0x89, 0x90, 0x10, 0x17, 0x4b, 0x5e, 0x62, 0x6e, 0xaa, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x67, 0x10,
	0x98, 0xad, 0xa4, 0xc6, 0xc5, 0x05, 0x55, 0x53, 0x90, 0x53, 0x29, 0x24, 0xc1, 0xc5, 0x9e, 0x9b,
	0x5a, 0x5c, 0x9c, 0x98, 0x0e, 0x53, 0x04, 0xe3, 0x1a, 0x79, 0x72, 0xb1, 0xbb, 0x17, 0xa5, 0xa6,
	0x96, 0xa4, 0x16, 0x09, 0xd9, 0x71, 0x71, 0x04, 0x27, 0x56, 0x82, 0x75, 0x09, 0x49, 0xe8, 0x21,
	0xb9, 0x00, 0xd9, 0x32, 0x29, 0x31, 0x2c, 0x32, 0x05, 0x39, 0x95, 0x4a, 0x0c, 0x49, 0x6c, 0x60,
	0x97, 0x1a, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0xea, 0x27, 0x0c, 0x07, 0xc8, 0x00, 0x00, 0x00,
}

// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn

// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4

// GreeterClient is the client API for Greeter service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type GreeterClient interface {
	SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error)
}

// greeterClient已经实现了那个接口,到时候调用SayHello直接掉就行了
type greeterClient struct {
	cc *grpc.ClientConn
}

func NewGreeterClient(cc *grpc.ClientConn) GreeterClient { //客户端产生一个新的客户端,这个是给客户端使用的
	return &greeterClient{cc}
}

func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) {
	out := new(HelloReply)
	err := c.cc.Invoke(ctx, "/helloworld.Greeter/SayHello", in, out, opts...) //客户端调用完SayHello自动就会往grpc上发
	if err != nil {
		return nil, err
	}
	return out, nil
}

// GreeterServer is the server API for Greeter service.
type GreeterServer interface {
	//服务端怎么实现这个接口它根本就不知道怎么实现,服务端向让它实现什么它就实现什么,比如接收了SayHello了怎么处理,完了怎么回复,这个工具是不知道,这个是留给我们来实现的,这个是代码的核心逻辑
	SayHello(context.Context, *HelloRequest) (*HelloReply, error)
}

func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) {
	s.RegisterService(&_Greeter_serviceDesc, srv)
}

func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(HelloRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(GreeterServer).SayHello(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/helloworld.Greeter/SayHello",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest))
	}
	return interceptor(ctx, in, info, handler)
}

var _Greeter_serviceDesc = grpc.ServiceDesc{
	ServiceName: "helloworld.Greeter",
	HandlerType: (*GreeterServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "SayHello",
			Handler:    _Greeter_SayHello_Handler,
		},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "helloworld/helloworld.proto",
}

3番目のステップはサーバーを実現することです

最初に構造を定義します。この構造は、上記のインターフェースを実装する必要があります。このインターフェースが実装された後にのみ、外部サービスを提供できます。パラメーター要求

次に、メインプログラムを開始できます

$ GOPATH / src / helloworld / greeter_server / main.goコード:

package main

import (
	"golang.org/x/net/context"
	"google.golang.org/grpc/examples/helloworld/helloworld"
	"fmt"
	"net"
	"log"
	"google.golang.org/grpc"
)

const(
	port = ":5001"
)

type service struct{ //用来实现前面生成的接口

}

//对外提供一个供客户端调用的函数,只要客户端按照我这里要求传参,我就能对外提供一个我这里规定返回数据
func (s *service)SayHello(ctx context.Context, r *helloworld.HelloRequest) (*helloworld.HelloReply, error){ //通过Alt+Enter加入引入的包
	fmt.Println(r.Name)
	return &helloworld.HelloReply{Message:"hello," + r.Name},nil
}

func main(){
	lis,err := net.Listen("tcp", port) //监听请求

	if err != nil{
		log.Fatal("fail to listen")
	}

	s := grpc.NewServer() //NewServer一个grpc
	helloworld.RegisterGreeterServer(s, &service{}) //起到桥梁的作用 把GreaterServer注册到grpc里面去 把前面实现的service服务的结构体注册到grpc里面去,目的是实现的东西要让grpc系统知道
	if err := s.Serve(lis);err != nil{ //启动 这个服务由grpc来完成 死循环永远启动在这里
		log.Fatal("fail to server")
	}
}

4番目のステップは、クライアントを実装することです

最初にサーバーに接続し、次にクライアント構造を生成します

$ GOPATH / src / helloworld / greeter_clinet / main.goコード:

package main

import (
	"google.golang.org/grpc"
	"log"
	"helloworld/helloworld"
	"golang.org/x/net/context"
	"fmt"
)

const(
	address = "127.0.0.1:5001"
)
//在客户端这里就不需要实现接口,客户端只管调用
func main(){
	conn,err := grpc.Dial(address, grpc.WithInsecure())
	if err != nil{
		log.Fatal("didnot connect server")
	}

	defer conn.Close()

	c := helloworld.NewGreeterClient(conn) //创建一个客户端 GreeterClient它内部维护了grpc链接 通过这个grpc链接就具有了远程调用能力

	r,err := c.SayHello(context.Background(), &helloworld.HelloRequest{Name:"xww"})
	if err != nil{
		log.Fatal("could not greet")
	}
	fmt.Println(r.Message)

}

 

25件の元の記事を公開 Like2 20,000以上の訪問

おすすめ

転載: blog.csdn.net/longjuanfengzc/article/details/88183982