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后小伙伴,嘴里还塞着山东的狗不理大蒜包, ...
随机推荐
- TypeScript入门(一)
TypeScript是微软官方的一种语言,是JavaScript的超集.它遵循的ECMA Script 6.0是下一代的JavaScript.浏览器还没有完全支持ES6,而ES5是弱类型的语言,还没有 ...
- Java读取properties文件连接数据库
先说为什么要有这种东西,或者我们为什么要用这种方式来写,先看经常用的方法,我们经常写的 package util; import java.sql.Connection; import java.sq ...
- cloneNode和replaceChild
node.cloneNode(deep) var node=document.getElementById("myList2").lastChild.cloneNode(true) ...
- linux新建用户登录不了
useradd----创建用户命令 简单的创建普通用户(当然得在root登录下执行) useradd username -p password userdel username 删除用户 用上面的命令 ...
- Android_scaleType属性
这里我们重点理解ImageView的属性android:scaleType,即ImageView.setScaleType(ImageView.ScaleType).android:scaleType ...
- django “如何”系列4:如何编写自定义模板标签和过滤器
django的模板系统自带了一系列的内建标签和过滤器,一般情况下可以满足你的要求,如果觉得需更精准的模板标签或者过滤器,你可以自己编写模板标签和过滤器,然后使用{% load %}标签使用他们. 代码 ...
- Angular开发实践(六):服务端渲染
Angular Universal Angular在服务端渲染方面提供一套前后端同构解决方案,它就是 Angular Universal(统一平台),一项在服务端运行 Angular 应用的技术. 标 ...
- java.lang的详细解读
软件包 java.lang 提供java编程语言实现程序设计的基础类 接口摘要 1> appendable 提供被添加char序列和值的对象 2>charSquence char值 ...
- openjudge(二)
强制类型转换的作用:按照规范输出.
- 【数据结构】赫夫曼树的实现和模拟压缩(C++)
赫夫曼(Huffman)树,由发明它的人物命名,又称最优树,是一类带权路径最短的二叉树,主要用于数据压缩传输. 赫夫曼树的构造过程相对比较简单,要理解赫夫曼数,要先了解赫夫曼编码. 对一组出现频率不同 ...