grpc学习记录

我用的是golang语言,所以后面的内容全是用golang表示的

1.定义一个proto文件:

    syntax = "proto3";
    package helloworld;

    message UserInfo {
      string name = 1; 
      string sex = 2;
      int32 weight = 3;
    }

    message funcResponse {
        string  r_say = 1;     
        string  r_name= 2;
        string r_sex = 3;
    }

    service UserService {
      rpc Login(UserInfo) returns (funcResponse){};
    }
    这里注意一点:syntax = "proto3"; 一定要放到文件的最开始的位置,否则会报错。

2.什么是protobuf:

一种与语言无关的、平台无关的、可扩展的序列化结构化数据的方式,用于通信协议、数据存储等.

2.1优点:

1,性能好,效率高
2,代码生成机制,数据解析类自动生成
3,支持向后兼容和向前兼容
4,支持多种编程语言(java,c++,python,golang等)

2.2概念:

核心概念
1 .proto文件
相当于确定数据协议,数据结构中存在哪些数据,数据类型是怎么样
2 modifiers
    2-1 required 不可以增加或删除的字段,必须初始化
    2-2 optional 可选字段,可删除,可以不初始化
    2-3 repeated 可重复字段, 对应到java文件里,生成的是List
3 Message
在proto文件里,数据的协议时以Message的形式表现的。

2.3. protobuf环境搭建

  1. 下载protobuf:https://github.com/google/protobuf/releases
    并选择protoc-xxx-win32.zip下载
  2. 将解压出来的protoc.exe放在一全英文路径下,并把其路径名放在windows环境变量下的path下,同时添加proto_path,值为protoc.exe的路径。

2.4. 生成相应的 xxx.pb.xxx:

protoc -I=./ --go_out=plugins=grpc:./  ./service.proto 因为我用的是go所以最终生成的文件是:pbtest.pb.go

生成类似的文件:
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: pbtest.proto

/*
Package helloworld is a generated protocol buffer package.

It is generated from these files:
    pbtest.proto

It has these top-level messages:
    UserInfo
    FuncResponse
*/
package helloworld

import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"

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

// 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.ProtoPackageIsVersion2 // please upgrade the proto package

type UserInfo struct {
    Name   string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
    Sex    string `protobuf:"bytes,2,opt,name=sex" json:"sex,omitempty"`
    Weight int32  `protobuf:"varint,3,opt,name=weight" json:"weight,omitempty"`
}

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

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

func (m *UserInfo) GetSex() string {
    if m != nil {
        return m.Sex
    }
    return ""
}

func (m *UserInfo) GetWeight() int32 {
    if m != nil {
        return m.Weight
    }
    return 0
}

type FuncResponse struct {
    RSay  string `protobuf:"bytes,1,opt,name=r_say,json=rSay" json:"r_say,omitempty"`
    RName string `protobuf:"bytes,2,opt,name=r_name,json=rName" json:"r_name,omitempty"`
    RSex  string `protobuf:"bytes,3,opt,name=r_sex,json=rSex" json:"r_sex,omitempty"`
}

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

func (m *FuncResponse) GetRSay() string {
    if m != nil {
        return m.RSay
    }
    return ""
}

func (m *FuncResponse) GetRName() string {
    if m != nil {
        return m.RName
    }
    return ""
}

func (m *FuncResponse) GetRSex() string {
    if m != nil {
        return m.RSex
    }
    return ""
}

func init() {
    proto.RegisterType((*UserInfo)(nil), "helloworld.UserInfo")
    proto.RegisterType((*FuncResponse)(nil), "helloworld.funcResponse")
}

// 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

// Client API for UserService service

type UserServiceClient interface {
    Login(ctx context.Context, in *UserInfo, opts ...grpc.CallOption) (*FuncResponse, error)
}

type userServiceClient struct {
    cc *grpc.ClientConn
}

func NewUserServiceClient(cc *grpc.ClientConn) UserServiceClient {
    return &userServiceClient{cc}
}

func (c *userServiceClient) Login(ctx context.Context, in *UserInfo, opts ...grpc.CallOption) (*FuncResponse, error) {
    out := new(FuncResponse)
    err := grpc.Invoke(ctx, "/helloworld.UserService/Login", in, out, c.cc, opts...)
    if err != nil {
        return nil, err
    }
    return out, nil
}

// Server API for UserService service

type UserServiceServer interface {
    Login(context.Context, *UserInfo) (*FuncResponse, error)
}

func RegisterUserServiceServer(s *grpc.Server, srv UserServiceServer) {
    s.RegisterService(&_UserService_serviceDesc, srv)
}

func _UserService_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
    in := new(UserInfo)
    if err := dec(in); err != nil {
        return nil, err
    }
    if interceptor == nil {
        return srv.(UserServiceServer).Login(ctx, in)
    }
    info := &grpc.UnaryServerInfo{
        Server:     srv,
        FullMethod: "/helloworld.UserService/Login",
    }
    handler := func(ctx context.Context, req interface{}) (interface{}, error) {
        return srv.(UserServiceServer).Login(ctx, req.(*UserInfo))
    }
    return interceptor(ctx, in, info, handler)
}

var _UserService_serviceDesc = grpc.ServiceDesc{
    ServiceName: "helloworld.UserService",
    HandlerType: (*UserServiceServer)(nil),
    Methods: []grpc.MethodDesc{
        {
            MethodName: "Login",
            Handler:    _UserService_Login_Handler,
        },
    },
    Streams:  []grpc.StreamDesc{},
    Metadata: "pbtest.proto",
}

func init() { proto.RegisterFile("pbtest.proto", fileDescriptor0) }

var fileDescriptor0 = []byte{
    // 209 bytes of a gzipped FileDescriptorProto
    0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x4c, 0x8f, 0x4f, 0x4b, 0x85, 0x40,
    0x14, 0xc5, 0xb3, 0xd7, 0x48, 0xdd, 0xde, 0x22, 0x6e, 0x7f, 0x18, 0x5a, 0x89, 0x2b, 0x57, 0x2e,
    0x6a, 0xd5, 0x37, 0x30, 0x88, 0x02, 0xa5, 0xb5, 0xa8, 0x5d, 0xff, 0x80, 0xcd, 0xc8, 0x9d, 0x29,
    0xf5, 0xdb, 0x87, 0x63, 0xf2, 0xdc, 0x9d, 0x7b, 0x38, 0x9c, 0xf3, 0xbb, 0x70, 0x1c, 0x4a, 0x4b,
    0xc6, 0xc6, 0x03, 0x6b, 0xab, 0x11, 0x5a, 0xea, 0x7b, 0x3d, 0x6a, 0xee, 0xbf, 0xc2, 0x04, 0x2e,
    0x3f, 0x0d, 0xf1, 0xab, 0xaa, 0x35, 0x22, 0x5c, 0xa8, 0xe2, 0x9b, 0xa4, 0x17, 0x78, 0xd1, 0x55,
    0xea, 0x34, 0xde, 0xc0, 0xc1, 0xd0, 0x24, 0xcf, 0x9d, 0xb5, 0x48, 0x7c, 0x00, 0x7f, 0xa4, 0xae,
    0x69, 0xad, 0x3c, 0x04, 0x5e, 0x24, 0xd2, 0xff, 0x2b, 0xfc, 0x80, 0x63, 0xfd, 0xa3, 0xaa, 0x94,
    0xcc, 0xa0, 0x95, 0x21, 0xbc, 0x05, 0xc1, 0xb9, 0x29, 0xe6, 0xad, 0x8e, 0xb3, 0x62, 0xc6, 0x7b,
    0xf0, 0x39, 0x77, 0x23, 0x6b, 0xa3, 0xe0, 0xf7, 0x65, 0x65, 0xcd, 0xd2, 0xe4, 0x2a, 0x5d, 0x96,
    0xa6, 0xa7, 0x04, 0xae, 0x17, 0xb4, 0x8c, 0xf8, 0xb7, 0xab, 0x08, 0x5f, 0x40, 0xbc, 0xe9, 0xa6,
    0x53, 0x78, 0x17, 0x9f, 0xf8, 0xe3, 0x0d, 0xfe, 0x51, 0xee, 0xdd, 0x3d, 0x48, 0x78, 0x56, 0xfa,
    0xee, 0xef, 0xe7, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x29, 0x64, 0x7d, 0x56, 0x07, 0x01, 0x00,
    0x00,
}

3. 下载grpc

用命令安装:go get google.golang.org/grpc

另外在安装插件:
go get -u github.com/golang/protobuf/{proto,protoc-gen-go}

4.编写客户端:

package main

import (
    pb "grpc-hello/helloworld"
    "log"
    "os"

    "golang.org/x/net/context"
    "google.golang.org/grpc"
)

const (
    address = "127.0.0.1:8082"
)

func main() {
    log.SetOutput(os.Stdout)

    conn, err := grpc.Dial(address, grpc.WithInsecure())
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()
    c := pb.NewUserServiceClient(conn)

    userInfo := &pb.UserInfo{
        Name:   "Tome111111", //proto.String("XCL-gRPC"),
        Sex:    "man",
        Weight: 16,
    }

    r, err := c.Login(context.Background(), userInfo)
    if err != nil {
        log.Fatalf("登录失败!  %v", err)
    }
    log.Println(r.RSay, r.RName)
}

5. 编写服务端

package main

import (
    pb "grpc-hello/helloworld"
    "log"
    "net"
    "os"

    "golang.org/x/net/context"
    "google.golang.org/grpc"
)

const (
    port = "127.0.0.1:8082"
)

type server struct{}

func (s *server) Login(ctx context.Context, usr *pb.UserInfo) (*pb.FuncResponse, error) {
    log.Println("Server...... Login() UserInfo:", usr)
    return &pb.FuncResponse{RSay: "hello", RName: usr.Name}, nil

}

func main() {
    log.SetOutput(os.Stdout)
    lis, err := net.Listen("tcp", port)
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    pb.RegisterUserServiceServer(s, &server{})

    log.Println("Server......")
    s.Serve(lis)
}

运行的结果:

你可能感兴趣的:(golang,grpc)