Go-GRPC 初体验
grpc 跟常见的client-server模型相似(doubbo)
grpc 编码之前需要准备以下环境:
- 安装protobuf,grpc的client与server之间消息传递使用的protoc格式消息,比起json,xml速度快
- 安装grpc 的源码包
下面开始编写grpc示例代码:
- 首先编写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 初体验的更多相关文章
- .NET Core 微服务之grpc 初体验(干货)
Grpc介绍 GitHub: https://github.com/grpc/grpc gRPC是一个高性能.通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计 ...
- ASP.NET Core 3.0 上的gRPC服务模板初体验(多图)
早就听说ASP.NET Core 3.0中引入了gRPC的服务模板,正好趁着家里电脑刚做了新系统,然后装了VS2019的功夫来体验一把.同时记录体验的过程.如果你也想按照本文的步骤体验的话,那你得先安 ...
- RPC框架基础概念理解以及使用初体验
RPC:Remote Procedure Call(远程服务调用) RPC是做什么的 通过RPC框架机器A某个进程可以通过网络调用机器B上的进程方法,就像在本地上调用一样. RPC可以基于HTTP或者 ...
- .NET WebSockets 核心原理初体验
上个月我写了<.NET gRPC核心功能初体验>, 里面使用gRPC双向流做了一个打乒乓球的Demo, 实时双向这两个标签是不是很熟悉,对, WebSockets也可以做实时双向通信. 本 ...
- .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验
不知不觉,“.NET平台开源项目速览“系列文章已经15篇了,每一篇都非常受欢迎,可能技术水平不高,但足够入门了.虽然工作很忙,但还是会抽空把自己知道的,已经平时遇到的好的开源项目分享出来.今天就给大家 ...
- Xamarin+Prism开发详解四:简单Mac OS 虚拟机安装方法与Visual Studio for Mac 初体验
Mac OS 虚拟机安装方法 最近把自己的电脑升级了一下SSD固态硬盘,总算是有容量安装Mac 虚拟机了!经过心碎的安装探索,尝试了国内外的各种安装方法,最后在youtube上找到了一个好方法. 简单 ...
- Spring之初体验
Spring之初体验 Spring是一个轻量级的Java Web开发框架,以IoC(Inverse of Control 控制反转)和 ...
- Xamarin.iOS开发初体验
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKwAAAA+CAIAAAA5/WfHAAAJrklEQVR4nO2c/VdTRxrH+wfdU84pW0
- 【腾讯Bugly干货分享】基于 Webpack & Vue & Vue-Router 的 SPA 初体验
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57d13a57132ff21c38110186 导语 最近这几年的前端圈子,由于 ...
- 【Knockout.js 学习体验之旅】(1)ko初体验
前言 什么,你现在还在看knockout.js?这货都已经落后主流一千年了!赶紧去学Angular.React啊,再不赶紧的话,他们也要变out了哦.身旁的90后小伙伴,嘴里还塞着山东的狗不理大蒜包, ...
随机推荐
- 神奇的Python
不断学习新的知识,不断掌新的技能是一件非常有趣的事情,其实Python在我学习这门课之前从没听过,刚上第一节课老师给我们讲了一个它的应用比如可以筛选单词,定时放歌等,虽然感觉自己还没有真正理解这门课程 ...
- ACCESS_ONCE
宏定义: #define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) 分解: typeof(x):取x的类型,如果x是int,那typeof(x) ...
- 用C#语言编写:数组分析器
static void Main(string[] args) { #region 创建数组 Console.Write("请输入数 ...
- 【眼见为实】自己动手实践理解READ COMMITTED && MVCC
[眼见为实]自己动手实践理解 READ COMMITTED && MVCC 首先设置数据库隔离级别为读已提交(READ COMMITTED): set global transacti ...
- spring boot — InputStream
@Componentpublic class TextFileDownloadView extends AbstractFileDownloadView { @Override protected I ...
- 关于BufferedReader的readLine方法遇到的坑
今天偶然用到BufferedReader,在读取文本后输出数据的时候遇到了隔行输出的问题. 如: 床前明月光 疑是地上霜 123456 789789 输出的为:疑是地上霜789789 找了一下,最终找 ...
- jdk 环境配置踩坑
其实在网上已经有很多环境配置的介绍了.不过我还是想用切身经历告诉大家这里面可能遇到的坑. 首先,先给大家讲一下JAVA_HOME,path,CLASSPATH JAVA_HOME 指向的是JDK的安装 ...
- SoDiaoEditor电子病历编辑器更新至V3版本,愿与各位一路同行!
简单闲聊两句-- 记得刚参加工作那会儿,去医院实施,信息科不远处就是手术室,门口每天都挤满了人,他们中大多数都是等待手术结果的患者家属,有的还会把折叠床带来,应该是陪床有段时间了.有时路过,还会听到一 ...
- Docker深入浅出系列教程——Docker初体验
我是张飞洪,钻进浩瀚代码,十年有余,人不堪其累,吾不改其乐.我喜欢把玩代码,琢磨词句!代码算法让我穿透规律,文章摘句让我洞察人情.如果你觉得和我的看法不一样,请关注我的头条号,那我们一定合得来. Do ...
- 第一次作业:我与CS的缘分
"既然选择了远方,便只顾风雨兼程" --汪国真 一.结缘计算机 1.1初识计算机 当第一次看到这个作业题目的时候,我的思虑不禁回到了小时候那个对这个世界的一切充满兴趣的纯真年代 ...