Go-GRPC 初体验

peter 等级 791 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 初体验

收藏
评论区

相关推荐

Go-GRPC 初体验
grpc 跟常见的clientserver模型相似(dubbo) grpc 编码之前需要准备以下环境: 安装protobuf,grpc的client与server之间消息传递使用的protoc格式消息,比起json,xml速度快 安装grpc 的源码包下面开始编写grpc示例代码:1. 首先编写proto文件,示例:helloworld
golang 分析调试高阶技巧
layout: post title: “golang 调试高阶技巧” date: 2020603 1:44:09 0800 categories: golang GC 垃圾回收 golang 高阶调试 Golang tools nm compile
Go gRPC进阶
### 前言 上篇介绍了[go-grpc-middleware](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fgrpc-ecosystem%2Fgo-grpc-middleware)的`grpc_zap`、`grpc_auth`和`grpc_recovery`
gRPC学习之五:gRPC
### 欢迎访问我的GitHub > 这里分类和汇总了欣宸的全部原创(含配套源码):[https://github.com/zq2599/blog\_demos](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fzq2599%2Fblog_demos) ###
gRPC学习之六:gRPC
### 欢迎访问我的GitHub > 这里分类和汇总了欣宸的全部原创(含配套源码):[https://github.com/zq2599/blog\_demos](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fzq2599%2Fblog_demos) ###
gRPC学习之四:实战四类服务方法
### 欢迎访问我的GitHub > 这里分类和汇总了欣宸的全部原创(含配套源码):[https://github.com/zq2599/blog\_demos](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fzq2599%2Fblog_demos) ###
gRPC学习以及实践
相信大家都听过RPC、HTTP、Socket等协议,他们均可用于业务中来进行数据通信,又根据各自协议的特点,应用场景也比较多样、复杂,那大家是否听过或者了解gRPC呢?用来做什么呢?我们就来了解一下gRPC以及其用途。 介绍 -- 用官方网站1一句话介绍介绍gRPC A high-performance, open source univers
gRPC官方文档(gRPC基础:C++)
文章来自[gRPC 官方文档中文版](http://doc.oschina.net/grpc?t=56831) 本教程提供了C++程序员如何使用gRPC的指南。 通过学习教程中例子,你可以学会如何: * 在一个 .proto 文件内定义服务. * 用 protocol buffer 编译器生成服务器和客户端代码. * 使用 gRPC 的 C
gRPC应用C++
1.  gRPC简述 ---------- RPC,远程方法调用,就是像调用本地方法一样调用远程方法。 [gRPC](http://www.oschina.net/p/grpc-framework)是Google实现的一种RPC框架,基于HTTP/2标准设计,带来诸如双向流、流控、头部压缩、单 TCP 连接上的多复用请求等特。这些特性使得其在移动设备上表
10.fabric
[2017-11-25 15:23:22] [grpc-default-worker-ELG-2-3] [ERROR] [io.netty.handler.codec.http2.DefaultHttp2Connection:181] Caught Throwable from listener onStreamActive. java.la
Dubbo 接口转化为gRPC服务
公司是多语言研发环境,目前Java项目居多,使用Dubbo进行服务间调用。目前公司Nodejs项目、Golang已经很多,平常也用阿里开源的eggjs框架进行开发。经过技术选型,[gRPC](https://www.oschina.net/action/GoToLink?url=http%3A%2F%2Fgrpc.io)支持跨语言、高性能、HTTP/2,使用
Golang gRPC 使用
一、概念 ---- 1、gRPC默认使用protocol buffers,这是google开源的一套成熟的结构数据序列化机制(当然也可以使用其他数据格式如JSON),可以用proto files创建gRPC服务,用protocol buffers消息类型来定义方法参数和返回类型。 二、安装 ---- 1、yum install autoconf aut
Golang gRPC实践 连载一 gRPC介绍与安装
[gRPC](https://www.oschina.net/action/GoToLink?url=http%3A%2F%2Fwww.grpc.io%2F) 是一个高性能、开源、通用的RPC框架,由Google推出,基于[HTTP/2](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fht
Skywalking源码分析系列文章
目录 1\. Skywalking整体架构 2.Skywalking agent篇 2.1 字节码技术 2.2 Skywalking agent 如何设计 2.3 Skywalking agent  技术细节 3\. Skywalking 通信篇 3.1 GRPC通信原理详解 3.2 Skywal
TiKV 源码解析系列文章(八)grpc
作者: 李建俊 上一篇《[gRPC Server 的初始化和启动流程](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fpingcap.com%2Fblog-cn%2Ftikv-source-code-reading-7%2F)》为大家介绍了 gRPC Server 的初始化和启动流程,本