Go实战--golang中使用gRPC和Protobuf实现高性能api(golang/protobuf、google.golang.org/grpc)

生命不止,继续 go go go !!!

号外号外,插播一条广告,通过博客的uv可以看到周五,程序员是不怎么干活的:

本篇博客,使用gRPC和Protobuf,实现所谓的高性能api。

protobuf

golang中的protobuf大家应该不会很陌生,之前也有博客介绍过:
Go实战–go中使用google/protobuf(The way to go)

Protocol Buffers (a.k.a.,protobuf) are Google’s language-neutral,platform-neutral,extensible mechanism for serializing structured data. You can find protobuf’s documentation on the Google Developers site.

获取:

go get -u github.com/golang/protobuf/proto
go get -u github.com/golang/protobuf/protoc-gen-go

Protobuf语法
下面简要介绍Protobuf语法:
参考:http://www.jb51.cc/article/p-fqzbjyww-d.html
官方:
https://developers.google.com/protocol-buffers/
https://developers.google.com/protocol-buffers/docs/gotutorial

Message定义
一个message类型定义描述了一个请求或相应的消息格式,可以包含多种类型字段。例如定义一个搜索请求的消息格式,每个请求包含查询字符串、页码、每页数目。

syntax = "proto3";
package tutorial;

首行声明使用的protobuf版本为proto3

message Person {
  string name = 1;
  int32 id = 2;  // Unique ID number for this person.
  string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    string number = 1;
    PhoneType type = 2;
  }

  repeated PhoneNumber phones = 4;
}

// Our address book file is just one of these.
message AddressBook {
  repeated Person people = 1;
}

生成

protoc -I=$SRC_DIR --go_out=$DST_DIR $SRC_DIR/addressbook.proto

写消息

book := &pb.AddressBook{}
// ...

// Write the new address book back to disk.
out,err := proto.Marshal(book)
if err != nil {
        log.Fatalln("Failed to encode address book:",err)
}
if err := ioutil.WriteFile(fname,out,0644); err != nil {
        log.Fatalln("Failed to write address book:",err)
}

读消息

// Read the existing address book.
in,err := ioutil.ReadFile(fname)
if err != nil {
        log.Fatalln("Error reading file:",err)
}
book := &pb.AddressBook{}
if err := proto.Unmarshal(in,book); err != nil {
        log.Fatalln("Failed to parse address book:",err)
}

grpc

golang中的rpc大家也不会陌生,之前也有介绍过奥:
Go实战–go中使用rpc(The way to go)

什么是rpc
RPC是Remote Procedure CallProtocol的缩写,即—远程过程调用协议。

RPC是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程。如果涉及的软件采用面向对象编程,那么远程过程调用亦可称作远程调用或远程方法调用,信息数据。通过它可以使函数调用模式网络化。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。

net/rpc
Go语言标准库能够自带一个rpc框架还是非常给力的,这可以很大程度的降低写后端网络通信服务的门槛,特别是在大规模的分布式系统中,rpc基本是跨机器通信的标配。rpc能够最大程度屏蔽网络细节,让开发者专注在服务功能的开发上面

什么是grpc
gRPC 是一个高性能、开源、通用的RPC框架,由Google推出,基于HTTP/2协议标准设计开发,默认采用Protocol Buffers数据序列化协议,支持多种开发语言。gRPC提供了一种简单的方法来精确的定义服务,并且为客户端和服务端自动生成可靠的功能库。

在gRPC客户端可以直接调用不同服务器上的远程程序,使用姿势看起来就像调用本地程序一样,很容易去构建分布式应用和服务。和很多RPC系统一样,服务端负责实现定义好的接口并处理客户端的请求,客户端根据接口描述直接调用需要的服务。客户端和服务端可以分别使用gRPC支持的不同语言实现。

grpc-go
github地址:
https://github.com/grpc/grpc-go

Star: 4402

文档地址:
https://godoc.org/google.golang.org/grpc

获取:
go get -u google.golang.org/grpc

应用

文件结构

proto文件
customer.proto

syntax = "proto3";
package customer;


// The Customer service definition.
service Customer {   
  // Get all Customers with filter - A server-to-client streaming RPC.
  rpc GetCustomers(CustomerFilter) returns (stream CustomerRequest) {}
  // Create a new Customer - A simple RPC 
  rpc CreateCustomer (CustomerRequest) returns (CustomerResponse) {}
}

// Request message for creating a new customer
message CustomerRequest {
  int32 id = 1;  // Unique ID number for a Customer.
  string name = 2;
  string email = 3;
  string phone= 4;

  message Address {
    string street = 1;
    string city = 2;
    string state = 3;
    string zip = 4;
    bool isShippingAddress = 5; 
  }

  repeated Address addresses = 5;
}

message CustomerResponse {
  int32 id = 1;
  bool success = 2;
}
message CustomerFilter {    
  string keyword = 1;
}

生成customer.pb.go

protoc --go_out=plugins=grpc:. customer.proto
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: customer.proto

/* Package customer is a generated protocol buffer package. It is generated from these files: customer.proto It has these top-level messages: CustomerRequest CustomerResponse CustomerFilter */
package customer

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

// Request message for creating a new customer
type CustomerRequest struct {
    Id        int32                      `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`
    Name      string                     `protobuf:"bytes,2,name=name" json:"name,omitempty"`
    Email     string                     `protobuf:"bytes,3,name=email" json:"email,omitempty"`
    Phone     string                     `protobuf:"bytes,4,name=phone" json:"phone,omitempty"`
    Addresses []*CustomerRequest_Address `protobuf:"bytes,5,rep,name=addresses" json:"addresses,omitempty"`
}

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

func (m *CustomerRequest) GetId() int32 {
    if m != nil {
        return m.Id
    }
    return 0
}

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

func (m *CustomerRequest) GetEmail() string {
    if m != nil {
        return m.Email
    }
    return ""
}

func (m *CustomerRequest) GetPhone() string {
    if m != nil {
        return m.Phone
    }
    return ""
}

func (m *CustomerRequest) GetAddresses() []*CustomerRequest_Address {
    if m != nil {
        return m.Addresses
    }
    return nil
}

type CustomerRequest_Address struct {
    Street            string `protobuf:"bytes,name=street" json:"street,omitempty"`
    City              string `protobuf:"bytes,name=city" json:"city,omitempty"`
    State             string `protobuf:"bytes,name=state" json:"state,omitempty"`
    Zip               string `protobuf:"bytes,name=zip" json:"zip,omitempty"`
    IsShippingAddress bool   `protobuf:"varint,name=isShippingAddress" json:"isShippingAddress,omitempty"`
}

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

func (m *CustomerRequest_Address) GetStreet() string {
    if m != nil {
        return m.Street
    }
    return ""
}

func (m *CustomerRequest_Address) GetCity() string {
    if m != nil {
        return m.City
    }
    return ""
}

func (m *CustomerRequest_Address) GetState() string {
    if m != nil {
        return m.State
    }
    return ""
}

func (m *CustomerRequest_Address) GetZip() string {
    if m != nil {
        return m.Zip
    }
    return ""
}

func (m *CustomerRequest_Address) GetIsShippingAddress() bool {
    if m != nil {
        return m.IsShippingAddress
    }
    return false
}

type CustomerResponse struct {
    Id      int32 `protobuf:"varint,omitempty"`
    Success bool  `protobuf:"varint,name=success" json:"success,omitempty"`
}

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

func (m *CustomerResponse) GetId() int32 {
    if m != nil {
        return m.Id
    }
    return 0
}

func (m *CustomerResponse) GetSuccess() bool {
    if m != nil {
        return m.Success
    }
    return false
}

type CustomerFilter struct {
    Keyword string `protobuf:"bytes,name=keyword" json:"keyword,omitempty"`
}

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

func (m *CustomerFilter) GetKeyword() string {
    if m != nil {
        return m.Keyword
    }
    return ""
}

func init() {
    proto.RegisterType((*CustomerRequest)(nil),"customer.CustomerRequest")
    proto.RegisterType((*CustomerRequest_Address)(nil),"customer.CustomerRequest.Address")
    proto.RegisterType((*CustomerResponse)(nil),"customer.CustomerResponse")
    proto.RegisterType((*CustomerFilter)(nil),"customer.CustomerFilter")
}

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

type CustomerClient interface {
    // Get all Customers with filter - A server-to-client streaming RPC.
    GetCustomers(ctx context.Context,in *CustomerFilter,opts ...grpc.CallOption) (Customer_GetCustomersClient,error)
    // Create a new Customer - A simple RPC
    CreateCustomer(ctx context.Context,in *CustomerRequest,opts ...grpc.CallOption) (*CustomerResponse,error)
}

type customerClient struct {
    cc *grpc.ClientConn
}

func NewCustomerClient(cc *grpc.ClientConn) CustomerClient {
    return &customerClient{cc}
}

func (c *customerClient) GetCustomers(ctx context.Context,error) {
    stream,err := grpc.NewClientStream(ctx,&_Customer_serviceDesc.Streams[0],c.cc,"/customer.Customer/GetCustomers",opts...)
    if err != nil {
        return nil,err
    }
    x := &customerGetCustomersClient{stream}
    if err := x.ClientStream.SendMsg(in); err != nil {
        return nil,err
    }
    if err := x.ClientStream.CloseSend(); err != nil {
        return nil,err
    }
    return x,nil
}

type Customer_GetCustomersClient interface {
    Recv() (*CustomerRequest,error)
    grpc.ClientStream
}

type customerGetCustomersClient struct {
    grpc.ClientStream
}

func (x *customerGetCustomersClient) Recv() (*CustomerRequest,error) {
    m := new(CustomerRequest)
    if err := x.ClientStream.RecvMsg(m); err != nil {
        return nil,err
    }
    return m,nil
}

func (c *customerClient) CreateCustomer(ctx context.Context,error) {
    out := new(CustomerResponse)
    err := grpc.Invoke(ctx,"/customer.Customer/CreateCustomer",in,err
    }
    return out,nil
}

// Server API for Customer service

type CustomerServer interface {
    // Get all Customers with filter - A server-to-client streaming RPC.
    GetCustomers(*CustomerFilter,Customer_GetCustomersServer) error
    // Create a new Customer - A simple RPC
    CreateCustomer(context.Context,*CustomerRequest) (*CustomerResponse,error)
}

func RegisterCustomerServer(s *grpc.Server,srv CustomerServer) {
    s.RegisterService(&_Customer_serviceDesc,srv)
}

func _Customer_GetCustomers_Handler(srv interface{},stream grpc.ServerStream) error {
    m := new(CustomerFilter)
    if err := stream.RecvMsg(m); err != nil {
        return err
    }
    return srv.(CustomerServer).GetCustomers(m,&customerGetCustomersServer{stream})
}

type Customer_GetCustomersServer interface {
    Send(*CustomerRequest) error
    grpc.ServerStream
}

type customerGetCustomersServer struct {
    grpc.ServerStream
}

func (x *customerGetCustomersServer) Send(m *CustomerRequest) error {
    return x.ServerStream.SendMsg(m)
}

func _Customer_CreateCustomer_Handler(srv interface{},ctx context.Context,dec func(interface{}) error,interceptor grpc.UnaryServerInterceptor) (interface{},error) {
    in := new(CustomerRequest)
    if err := dec(in); err != nil {
        return nil,err
    }
    if interceptor == nil {
        return srv.(CustomerServer).CreateCustomer(ctx,in)
    }
    info := &grpc.UnaryServerInfo{
        Server:     srv,FullMethod: "/customer.Customer/CreateCustomer",}
    handler := func(ctx context.Context,req interface{}) (interface{},error) {
        return srv.(CustomerServer).CreateCustomer(ctx,req.(*CustomerRequest))
    }
    return interceptor(ctx,info,handler)
}

var _Customer_serviceDesc = grpc.ServiceDesc{
    ServiceName: "customer.Customer",HandlerType: (*CustomerServer)(nil),Methods: []grpc.MethodDesc{
        {
            MethodName: "CreateCustomer",Handler:    _Customer_CreateCustomer_Handler,},Streams: []grpc.StreamDesc{
        {
            StreamName:    "GetCustomers",Handler:       _Customer_GetCustomers_Handler,ServerStreams: true,Metadata: "customer.proto",}

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

var fileDescriptor0 = []byte{
    // 326 bytes of a gzipped FileDescriptorProto
    0x1f, 0x8b, 0x08, 0x00, 0x02, 0xff, 0x74, 0x92, 0xef, 0x4a, 0xc3, 0x30, 0x10, 0xc0, 0x97, 0x6e, 0xdd, 0x9f, 0x53, 0xea, 0x0c, 0x22, 0xb1, 0x6a, 0x3f, 0x15, 0x91, 0x21, 0xf3, 0xab, 0x20, 0x32, 0x70, 0xf8, 0xb5, 0x3e, 0x41, 0x6d, 0x0f, 0x17, 0xdc, 0xda, 0x9a, 0xcb, 0x90, 0xf9, 0x0a, 0xbe, 0x83, 0xcf, 0xe0, 0x23, 0xd2, 0x66, 0x03, 0xe7, 0x72, 0x77, 0xe5, 0x04, 0x42, 0x35, 0xa9, 0x55, 0xa5, 0x2b, 0x1c, 0x78, 0x6b, 0xc5, 0xf7, 0xe6, 0x01, 0xb2, 0x2c, 0x62, 0x89, 0x7a, 0x65, 0xb6, 0xe1, 0x45, 0x19, 0x36, 0x67, 0xe3, 0x2a, 0x93, 0x4b, 0xd1, 0xc9, 0x06, 0x4c, 0x5e, 0x54, 0x25, 0x8a, 0x61, 0x94, 0x85, 0x24, 0x47, 0xe4, 0x68, 0x39, 0xd9, 0x1a, 0xfd, 0xb9, 0x7d, 0xf2, 0xd0, 0xa6, 0xbb, 0x9e, 0xf0, 0xc1, 0xa0, 0x4d, 0x73, 0xe8, 0x56, 0x88, 0x8e, 0x96, 0x8c, 0x64, 0x2e, 0xf5, 0xc6, 0x49, 0xd8, 0xce, 0x34, 0x3a, 0x0b, 0x7c, 0x4f, 0x59, 0xb7, 0x26, 0xd7, 0xe9, 0x79, 0xeb, 0x5a, 0xaf, 0xed, 0xc2, 0x8f, 0x58, 0xe2, 0x3b, 0x18, 0x9c, 0xae, 0xbd, 0x95, 0x09, 0xcd, 0x71, 0x5f, 0xba, 0x1f, 0x52, 0xa3, 0x6f, 0xb8, 0xa8, 0xf4, 0x9b, 0x51, 0xf6, 0x57, 0x2f, 0x0e, 0x37, 0xee, 0xfe, 0xfa, 0x43, 0xd4, 0x3c, 0xbc, 0x0d, 0xde, 0xd3, 0x60,}

server/main.go

package main

import (
    "log"
    "net"
    "strings"

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

    pb "go_grpc_protobuf/customer"
)

const (
    port = ":50051"
)

// server is used to implement customer.CustomerServer.
type server struct {
    savedCustomers []*pb.CustomerRequest
}

// CreateCustomer creates a new Customer
func (s *server) CreateCustomer(ctx context.Context,in *pb.CustomerRequest) (*pb.CustomerResponse,error) {
    s.savedCustomers = append(s.savedCustomers,in)
    return &pb.CustomerResponse{Id: in.Id,Success: true},nil
}

// GetCustomers returns all customers by given filter
func (s *server) GetCustomers(filter *pb.CustomerFilter,stream pb.Customer_GetCustomersServer) error {
    for _,customer := range s.savedCustomers {
        if filter.Keyword != "" {
            if !strings.Contains(customer.Name,filter.Keyword) {
                continue
            }
        }
        if err := stream.Send(customer); err != nil {
            return err
        }
    }
    return nil
}

func main() {
    lis,err := net.Listen("tcp",port)
    if err != nil {
        log.Fatalf("failed to listen: %v",err)
    }
    // Creates a new gRPC server
    s := grpc.NewServer()
    pb.RegisterCustomerServer(s,&server{})
    s.Serve(lis)
}

client/main.go

package main

import (
    "io"
    "log"

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

    pb "go_grpc_protobuf/customer"
)

const (
    address = "localhost:50051"
)

// createCustomer calls the RPC method CreateCustomer of CustomerServer
func createCustomer(client pb.CustomerClient,customer *pb.CustomerRequest) {
    resp,err := client.CreateCustomer(context.Background(),customer)
    if err != nil {
        log.Fatalf("Could not create Customer: %v",err)
    }
    if resp.Success {
        log.Printf("A new Customer has been added with id: %d",resp.Id)
    }
}

// getCustomers calls the RPC method GetCustomers of CustomerServer
func getCustomers(client pb.CustomerClient,filter *pb.CustomerFilter) {
    // calling the streaming API
    stream,err := client.GetCustomers(context.Background(),filter)
    if err != nil {
        log.Fatalf("Error on get customers: %v",err)
    }
    for {
        customer,err := stream.Recv()
        if err == io.EOF {
            break
        }
        if err != nil {
            log.Fatalf("%v.GetCustomers(_) = _,%v",client,err)
        }
        log.Printf("Customer: %v",customer)
    }
}
func main() {
    // Set up a connection to the gRPC server.
    conn,err := grpc.Dial(address,grpc.WithInsecure())
    if err != nil {
        log.Fatalf("did not connect: %v",err)
    }
    defer conn.Close()
    // Creates a new CustomerClient
    client := pb.NewCustomerClient(conn)

    customer := &pb.CustomerRequest{
        Id:    101,Name:  "Shiju Varghese",Email: "shiju@xyz.com",Phone: "732-757-2923",Addresses: []*pb.CustomerRequest_Address{
            &pb.CustomerRequest_Address{
                Street:            "1 Mission Street",City:              "San Francisco",State:             "CA",Zip:               "94105",IsShippingAddress: false,&pb.CustomerRequest_Address{
                Street:            "Greenfield",City:              "Kochi",State:             "KL",Zip:               "68356",IsShippingAddress: true,}

    // Create a new customer
    createCustomer(client,customer)

    customer = &pb.CustomerRequest{
        Id:    102,Name:  "Irene Rose",Email: "irene@xyz.com",Phone: "732-757-2924",customer)
    // Filter with an empty Keyword
    filter := &pb.CustomerFilter{Keyword: ""}
    getCustomers(client,filter)
}

运行server,运行client,输出:

2017/12/07 11:55:59 A new Customer has been added with id: 101
2017/12/07 11:55:59 A new Customer has been added with id: 102
2017/12/07 11:55:59 Customer: id:101 name:"Shiju Varghese" email:"shiju@xyz.com" phone:"732-757-2923" addresses:<street:"1 Mission Street" city:"San Francisco" state:"CA" zip:"94105" > addresses:<street:"Greenfield" city:"Kochi" state:"KL" zip:"68356" isShippingAddress:true >
2017/12/07 11:55:59 Customer: id:102 name:"Irene Rose" email:"irene@xyz.com" phone:"732-757-2924" addresses:<street:"1 Mission Street" city:"San Francisco" state:"CA" zip:"94105" isShippingAddress:true >

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


gRPC 前言 为什么使用gRPC 传输协议 传输效率 性能消耗 gRPC入门 gRPC流 证书认证 使用根证书 gRPC实现token认证 和Web服务共存 验证器 REST接口 grpcurl工具
参考文章: 1.&#160;https://www.cnblogs.com/kaixinyufeng/p/9651513.html 2.&#160;http://jia-shun.cn/2018/08
今天给大家翻译一篇由ASP.NET首席开发工程师 &quot;James Newton King&quot; 前几天发表的一篇博客,文中带来了一个实验性的产品gRPC Web。大家可以点击文末的讨论帖
上一篇文章我带着大家体验了一把《 &quot;ASP.NET Core 3.0 上的gRPC服务模板初体验(多图)&quot; 》,如果有兴趣的可以点击链接进行查看,相信跟着做的你,也是可以跑起来的。
早就听说ASP.NET Core 3.0中引入了gRPC的服务模板,正好趁着家里电脑刚做了新系统,然后装了VS2019的功夫来体验一把。同时记录体验的过程。如果你也想按照本文的步骤体验的话,那你得先安
这篇笔记主要是记录学习历程而不是怎么用~,以及protobuffers 和 gprc 各种文档的地址,等过上大半年后通过这篇笔记帮助自己快速重新掌握这个技术点 一、Protocolbuffers 关于
最近GRPC很火,感觉整RPC不用GRPC都快跟不上时髦了。 gRPC设计 gRPC是一种与语言无关的高性能远程过程调用 (RPC) 框架。刚好需要使用一个的RPC应用系统,自然而然就盯上了它,但是它
   gRPC是google开源提供的一个RPC软件框架,它的特点是极大简化了传统RPC的开发流程和代码量,使用户可以免除许多陷阱并聚焦于实际应用逻辑中。作为一种google的最新RPC解决方案,gRPC具备了以下这些强项: 1、gRPC在HTTP/2协议上用protobuf取代了json实现了最佳效率 2、用IDL(Interface Definition Language),一种简单的描述语言
  接着上期讨论的gRPC unary服务我们跟着介绍gRPC streaming,包括: Server-Streaming, Client-Streaming及Bidirectional-Streaming。我们首先在.proto文件里用IDL描述Server-Streaming服务: /* * responding stream of increment results */ servi
我已经设法通过GRPC使用流媒体模式的服务帐户为我的 Android应用程序运行Google Cloud Speech.但是,根据我所读到的内容,出于安全原因,我不应该在其中部署具有这些凭据的Android应用程序(当前存储为资源中的JSON文件).正确的是创建一个API密钥,如下所述: https://cloud.google.com/speech/docs/common/auth 这允许我限制
  安装protobuf go get -u github.com/golang/protobuf/proto go get -u github.com/golang/protobuf/protoc-gen-go 此时会生成protoc-gen-go,protoc一般是获取已经编译好的可执行文件(https://github.com/google/protobuf/releases)   安装gR
一、grpc安装 将 https://github.com/google/go-genproto 放到 $GOPATH/src/google.golang.org/genproto 将 https://github.com/grpc/grpc-go 放到 $GOPATH/src/google.golang.org/grpc 将 https://github.com/golang/t
参考URL: https://segmentfault.com/a/1190000015220713?utm_source=channel-hottest gRPC 是一个高性能、开源和通用的 RPC 框架,面向移动和 HTTP/2 设计。目前提供 C、Java 和 Go 语言版本,分别是:grpc, grpc-java, grpc-go. 其中 C 版本支持 C, C++, Node.js, P
我试图在电子应用程序中要求grpc,但我收到以下错误: Error: dlopen(/srv/node_modules/grpc/src/node/extension_binary/grpc_node.node, 1): Symbol not found: _GENERAL_NAME_free Referenced from: /srv/node_modules/grpc/src/node/e
我试图调用GRPC端点,但我想提供客户身份验证标头.我在哪里指定这个? var client = new proto.Publisher('127.0.0.1:50051', grpc.credentials.createInsecure()); var customHeader = { 'authorization': 'secret' } client.publish(d
我正在尝试创建一个 java grpc客户端来与go中的服务器通信.我是grpc的新手所以遵循本教程 gRPC Java Tutorial.在这些示例中,它们指的是阻塞和非阻塞存根,它们似乎是从 github的其他地方导入的. import io.grpc.examples.routeguide.RouteGuideGrpc.RouteGuideBlockingStub; import io.gr
我正在尝试做类似下面的事情(即使用流式grpc调用从客户端向服务器发送数据).代码参考取自官方网站上给出的grpc示例,用于解释目的: 客户端代码: ClientContext context; context.AddMetadata("authorization", "abcd"); context.set_deadline(...); std::unique_ptr<ClientWriter
什么是gRPC gRPC是google开源的一个高性能、跨语言的RPC框架,基于HTTP2协议,采用ProtoBuf 定义的IDL。 gRPC 的主要优点是: 现代高性能轻量级 RPC 框架。 协定优先 API 开发,默认使用协议缓冲区,允许与语言无关的实现。 可用于多种语言的工具,以生成强类型服务器和客户端。 支持客户端、服务器和双向流式处理调用。 使用 Protobuf 二进制序列化减少对网络
一.简介 gRPC 是一个由Google开源的,跨语言的,高性能的远程过程调用(RPC)框架。 gRPC使客户端和服务端应用程序可以透明地进行通信,并简化了连接系统的构建。它使用HTTP/2作为通信协议,使用 Protocol Buffers 作为序列化协议。 它的主要优点: 现代高性能轻量级 RPC 框架。 约定优先的 API 开发,默认使用 Protocol Buffers 作为描述语言,允许
目录 ASP.NET Core 3.0 使用gRPC ASP.NET Core 3.0 gRPC 双向流 ASP.NET Core 3.0 gRPC 认证授权 一.前言 在前一文 《ASP.NET Core 3.0 使用gRPC》中有提到 gRPC 支持双向流调用,支持实时推送消息,这也是 gRPC的一大特点,且 gRPC 在对双向流的控制支持上也是非常强大的。 二. 什么是 gRPC 流 gRP