Go-GRPC 初体验

peter 等级 409 0 0

grpc 跟常见的client-server模型相似(dubbo)
grpc 编码之前需要准备以下环境:

  • 安装protobuf,grpc的client与server之间消息传递使用的protoc格式消息,比起json,xml速度快
  • 安装grpc 的源码包

下面开始编写grpc示例代码:

  1. 首先编写proto文件,示例:helloworld
syntax = "proto3";

option objc\_class\_prefix = "HLW";

package helloworld;

// 定义一个Greeter服务,其中API为SayHello
// 形式参数: HelloRequest
// 返回参数:HelloReply
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}

  // rpc 借口的类型分为一下四种: A为接受参数,B为返回参数
  // 1. rpc GetFeature(Point) returns (Feature) {} 普通调用:A-B
  // 2. rpc ListFeatures(Rectangle) returns (stream Feature) {} 单向流:A - B(流)
  // 3. rpc RecordRoute(stream Point) returns (RouteSummary) {} 单向流:A(流) - B
  // 4. rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} 双向流:A(流) - B(流)
}

// 请求参数-根据自己的需求定义
message HelloRequest {
  string name = 1;
}

// 返回参数-根据自己的需求定义
message HelloReply {
  string message = 1;
}

  2.  将helloworld.proto转化为helloworld.proto.go

命令:protoc --go_out=plugins=grpc:. helloworld.proto 结果如下:

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

/\*
Package helloworld is a generated protocol buffer package.

It is generated from these files:
    helloworld.proto

It has these top-level messages:
    HelloRequest
    HelloReply
\*/
package myblogproto

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 HelloRequest struct {
    Name string \`protobuf:"bytes,1,opt,name=name" json:"name,omitempty"\`
}

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

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

// 返回参数-根据自己的需求定义
type HelloReply struct {
    Message string \`protobuf:"bytes,1,opt,name=message" json:"message,omitempty"\`
}

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

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")
}

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

type GreeterClient interface {
    // Sends a greeting
    SayHello(ctx context.Context, in \*HelloRequest, opts ...grpc.CallOption) (\*HelloReply, error)
}

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 := grpc.Invoke(ctx, "/helloworld.Greeter/SayHello", in, out, c.cc, opts...)
    if err != nil {
        return nil, err
    }
    return out, nil
}

// Server API for Greeter service

type GreeterServer interface {
    // Sends a greeting
    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.proto",
}

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

var fileDescriptor0 = \[\]byte{
    // 149 bytes of a gzipped FileDescriptorProto
    0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0x48, 0xcd, 0xc9,
    0xc9, 0x2f, 0xcf, 0x2f, 0xca, 0x49, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x42, 0x88,
    0x28, 0x29, 0x71, 0xf1, 0x78, 0x80, 0x78, 0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x42, 0x42,
    0x5c, 0x2c, 0x79, 0x89, 0xb9, 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x60, 0xb6, 0x92,
    0x1a, 0x17, 0x17, 0x54, 0x4d, 0x41, 0x4e, 0xa5, 0x90, 0x04, 0x17, 0x7b, 0x6e, 0x6a, 0x71, 0x71,
    0x62, 0x3a, 0x4c, 0x11, 0x8c, 0x6b, 0xe4, 0xc9, 0xc5, 0xee, 0x5e, 0x94, 0x9a, 0x5a, 0x92, 0x5a,
    0x24, 0x64, 0xc7, 0xc5, 0x11, 0x9c, 0x58, 0x09, 0xd6, 0x25, 0x24, 0xa1, 0x87, 0xe4, 0x02, 0x64,
    0xcb, 0xa4, 0xc4, 0xb0, 0xc8, 0x14, 0xe4, 0x54, 0x2a, 0x31, 0x38, 0xb1, 0x2d, 0x62, 0x62, 0xf6,
    0xf0, 0x09, 0x4f, 0x62, 0x03, 0xbb, 0xd8, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xbe, 0xde, 0x1d,
    0x2e, 0xc5, 0x00, 0x00, 0x00,
}

  3. 编写grpc服务端,伪代码:

package main

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

    pb "unicontract-validate/tests/grpcStudy/mybloggrpc/myblogproto"
)

const port = ":50051"

// 定义struct实现我们自定义的helloworld.proto对应的服务
type myServer struct {
}

func (m \*myServer) SayHello(ctx context.Context, in \*pb.HelloRequest) (\*pb.HelloReply, error) {
    return &pb.HelloReply{"请求server端成功!"}, nil
}

/\*\*
    1. 首先我们必须实现我们自定义rpc服务,例如:rpc SayHello()-在此我们可以实现我们自己的逻辑
    2. 创建监听listener
    3. 创建grpc的服务
    4. 将我们的服务注册到grpc的server中
    5. 启动grpc服务,将我们自定义的监听信息传递给grpc服务器
 \*/

func main() {

    //    创建server端监听端口
    list, err := net.Listen("tcp", port)
    if err != nil {
        fmt.Println(err)
    }

    //    创建grpc的server
    server := grpc.NewServer()
    //    注册我们自定义的helloworld服务
    pb.RegisterGreeterServer(server, &myServer{})

    //    启动grpc服务
    fmt.Println("grpc 服务启动... ...")
    server.Serve(list)
}

  4. 编写client端代码,伪代码如下:

package main

import (
    "google.golang.org/grpc"
    "fmt"
    "context"

    pb "unicontract-validate/tests/grpcStudy/mybloggrpc/myblogproto"
)

// 此处应与服务器端对应
const address  = "127.0.0.1:50051"

/\*\*
    1. 创建groc连接器
    2. 创建grpc客户端,并将连接器赋值给客户端
    3. 向grpc服务端发起请求
    4. 获取grpc服务端返回的结果
 \*/
func main()  {

    // 创建一个grpc连接器
    conn, err := grpc.Dial(address, grpc.WithInsecure())
    if err != nil{
        fmt.Println(err)
    }
    // 当请求完毕后记得关闭连接,否则大量连接会占用资源
    defer conn.Close()

    // 创建grpc客户端
    c := pb.NewGreeterClient(conn)

    name := "我是客户端,正在请求服务端!!!"
    // 客户端向grpc服务端发起请求
    result, err := c.SayHello(context.Background(), &pb.HelloRequest{Name:name})
    fmt.Println(name)
    if err != nil{
        fmt.Println("请求失败!!!")
        return
    }
    // 获取服务端返回的结果
    fmt.Println(result.Message)
}

  服务端结果:

Go-GRPC 初体验

  客户端请求之后结果:

Go-GRPC 初体验

收藏
评论区

相关推荐

关于Golang的那些事(一) -- Node.js和Golang对比
之前一直用Node.js作为开发语言,用了差不多4年的Node.js,涉及前端和后端,最近看到Golang这个新兴之秀挺火的,于是想探究探究一下这门语言,对比了一下他们的Github repo,截止现在Node.js的repo有72.5K星, issue数量是859个,Golang的repo有75.7K星,issue数量是5K个。从趋势来看,Golang来势
golang 中神奇的 slice
声明:本文仅限于简书发布,其他第三方网站均为盗版,原文地址: golang 中神奇的 slice(https://links.jianshu.com/go?tohttps%3A%2F%2Fliqiang.io%2Fpost%2Fimagesliceingolang) 在 golang 中,似乎人们都不太喜欢使用 Linked List,甚至于原
godoc 命令和 golang 代码文档管理
介绍 godoc 是 golang 自带的文档查看器,更多的提供部署服务 go doc 和 godoc 在 golang 1.13 被移除了,可以自行安装 golang.org go1.13 godoc(https://links.jianshu.com/go?tohttps%3A%2F%2Fgolang.org%2Fdoc%2Fg
Mac安装Golang和vscode
Mac第一次安装golang和vscode一起使用,遇到了不少的坑,下面介绍一下正确的安装方式。 1、使用brew安装Golang 如果不知道brew是什么,或怎么安装请看这里 brew官网(https://brew.sh/index_zhcn) brew install golang 安装完成后可以使用
【Golang】GoWeb框架之Gin-简明教程
Gin 简介 Gin is a HTTP web framework written in Go (Golang). It features a
Go-GRPC 初体验
grpc 跟常见的clientserver模型相似(dubbo) grpc 编码之前需要准备以下环境: 安装protobuf,grpc的client与server之间消息传递使用的protoc格式消息,比起json,xml速度快 安装grpc 的源码包下面开始编写grpc示例代码:1. 首先编写proto文件,示例:helloworld
Golang中常用的字符串操作
Golang中常用的字符串操作 一、标准库相关的Package go import( "strings" ) 二、常用字符串操作 1. 判断是否为空字符串 1.1 使用“”进行判断 思路:直接判断是否等于""空字符串,由于Golang中字符串不能为 nil,且为值类型,所以直接与空字符串比较即可。 举例: go
golang 分析调试高阶技巧
layout: post title: “golang 调试高阶技巧” date: 2020603 1:44:09 0800 categories: golang GC 垃圾回收 golang 高阶调试 Golang tools nm compile
深入理解 Go Slice
(https://imghelloworld.osscnbeijing.aliyuncs.com/0ce8a8773a658d4b843e5796a0dbf001.png) image 原文地址:深入理解 Go Slice(https://github.com/EDDYCJY/blog/blob/master/golang/pkg/20
golang包循环引用的几种解决方案
golang包循环引用的几种解决方案 发表于2020年11月2日2020年11月3日(https://libuba.com/2020/11/02/golang%e5%8c%85%e5%be%aa%e7%8e%af%e5%bc%95%e7%94%a8%e7%9a%84%e5%87%a0%e7%a7%8d%e8%a7%
GO开发[一]:golang语言初探
一.Golang的安装 1.https://dl.gocn.io/ (国内下载地址) (https://imghelloworld.osscnbeijing.aliyuncs.com/658c5d13c377
golang - DES加密ECB(模式)
Java默认DES算法使用DES/ECB/PKCS5Padding,而golang认为这种方式是不安全的,所以故意没有提供这种加密方式,那如果我们还是要用到怎么办?下面贴上golang版的DES ECB加密解密代码(默认对密文做了base64处理)。
聊聊golang的DDD项目结构
序本文主要研究一下golang的DDD项目结构interfacesfoodappserver/interfacesinterfaces git:(master) tree.|____fileupload| |____fileformat.go| |____fileupload.go|____food_handler.go|__
TensorFlow Serving
可以快速部署 Tensorflow 模型,上线 gRPC 或 REST API。官方推荐 Docker 部署,也给了训练到部署的完整教程:。本文只是遵照教程进行的练习,有助于了解 TensorFlow 训练到部署的整个过程。 准备环境准备好 ,导入依赖:pyimport sys Confirm that we're using Python 3assert
go get下载包失败问题
关于我由于某些不可抗力的原因,国内使用go get命令安装包时会经常会出现timeout的问题。本文介绍几个常用的解决办法。 从github克隆golang在github上建立了一个镜像库,如https://github.com/golang/net就对应是 https://golang.org/x/net的镜像库。 要下载golang.org/x/net包