grpc-golang入门

摘要:
安装grpc相关服务本文以mac系统为例安装,其他操作系统请参考官网安装。创建golang项目目录结构如下。在product目录下创建ProductInfo.proto文件syntax="proto3";optiongo_package=".;product";serviceProductInfo{//添加商品rpcaddProductreturns;//获取商品rpcgetProductreturns;}messageProduct{stringid=1;stringname=2;stringdescription=3;}messageProductId{stringvalue=1;}文件定义了两个接口,添加商品、获取商品。生成golang语言接口定义在product目录下执行下面命令,创建go语言的接口文件protoc--go_out=.ProductInfo.protoprotoc--go-grpc_out=.ProductInfo.proto执行完成后会生成ProductInfo.pb.go和ProductInfo_grpc.pb.go两个文件。=nil{log.Printlnreturn}}服务端实现了grpc定义的添加商品、获取商品两个接口,并使用50051端口提供服务。创建客户端文件在product/client文件夹下创建main.go文件packagemainimportconstfuncmain(){conn,err:=grpc.Dialiferr!
安装grpc相关服务

本文以mac系统为例安装,其他操作系统请参考官网安装。

brew install protobuf
brew install protoc-gen-go
brew install protoc-gen-go-grpc
protoc --version
libprotoc 3.17.3
protoc-gen-go --version
protoc-gen-go v1.27.1
protoc-gen-go-grpc --version
protoc-gen-go-grpc 1.1.0

本文基于上面的软件版本进行编码,protoc的不同版本差别较大。

创建golang项目

目录结构如下。

项目目录结构

在product目录下创建ProductInfo.proto文件

syntax = "proto3";
option go_package = ".;product";

service ProductInfo {
  //添加商品
  rpc addProduct(Product) returns (ProductId);
  //获取商品
  rpc getProduct(ProductId) returns (Product);
}

message Product {
  string id = 1;
  string name = 2;
  string description = 3;
}

message ProductId {
  string value = 1;
}

文件定义了两个接口,添加商品、获取商品。定义了2个对象Product、ProductId。

生成golang语言接口定义

在product目录下执行下面命令,创建go语言的接口文件

protoc --go_out=. ProductInfo.proto
protoc --go-grpc_out=. ProductInfo.proto

执行完成后会生成ProductInfo.pb.go和ProductInfo_grpc.pb.go两个文件。这两个文件是生成的,不要修改文件内容。

创建服务端文件

在product/server文件夹下创建main.go文件

package main

import (
	"context"
	"github.com/gofrs/uuid"
	"gomicro-quickstart/product"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"log"
	"net"
)

type server struct {
	productMap map[string]*product.Product
	product.UnimplementedProductInfoServer
}

//添加商品
func (s *server) AddProduct(ctx context.Context, req *product.Product) (resp *product.ProductId, err error) {
	resp = &product.ProductId{}
	out, err := uuid.NewV4()
	if err != nil {
		return resp, status.Errorf(codes.Internal, "err while generate the uuid ", err)
	}

	req.Id = out.String()
	if s.productMap == nil {
		s.productMap = make(map[string]*product.Product)
	}

	s.productMap[req.Id] = req
	resp.Value = req.Id
	log.Println("AddProduct req.Id:" + req.Id)
	return
}

//获取商品
func (s *server) GetProduct(ctx context.Context, req *product.ProductId) (resp *product.Product, err error) {
	if s.productMap == nil {
		s.productMap = make(map[string]*product.Product)
	}

	resp = s.productMap[req.Value]
	log.Println("GetProduct ProductName:" + resp.GetName())

	return
}

const (
	address = "localhost:50051"
)

func main() {
	listener, err := net.Listen("tcp", address)
	if err != nil {
		log.Println("net listen err ", err)
		return
	}

	s := grpc.NewServer()
	product.RegisterProductInfoServer(s, &server{})
	log.Println("start gRPC listen on port " + address)
	if err := s.Serve(listener); err != nil {
		log.Println("failed to serve...", err)
		return
	}
}

服务端实现了grpc定义的添加商品、获取商品两个接口,并使用50051端口提供服务。

创建客户端文件

在product/client文件夹下创建main.go文件

package main

import (
   "context"
   "gomicro-quickstart/product"
   "google.golang.org/grpc"
   "log"
)

const (
   address = "localhost:50051"
)

func main() {
   conn, err := grpc.Dial(address, grpc.WithInsecure())
   if err != nil {
      log.Println("did not connect.", err)
      return
   }
   defer conn.Close()

   client := product.NewProductInfoClient(conn)
   ctx := context.Background()

   id := AddProduct(ctx, client)
   GetProduct(ctx, client, id)
}

// 添加一个测试的商品
func AddProduct(ctx context.Context, client product.ProductInfoClient) (id string) {
   aMac := &product.Product{Name: "Mac Book Pro 2019", Description: "From Apple Inc."}
   productId, err := client.AddProduct(ctx, aMac)
   if err != nil {
      log.Println("add product fail.", err)
      return
   }
   log.Println("add product success, id = ", productId.Value)
   return productId.Value
}

// 获取一个商品
func GetProduct(ctx context.Context, client product.ProductInfoClient, id string) {
   p, err := client.GetProduct(ctx, &product.ProductId{Value: id})
   if err != nil {
      log.Println("get product err.", err)
      return
   }
   log.Printf("get prodcut success : %+v
", p)
}

客户端调用添加商品接口后调用获取商品接口。

运行程序

先运行服务端程序

在项目根目录执行

go run product/server/main.go

image-20210929154504708

再运行客户端程序

在项目根目录执行

go run product/client/main.go

image-20210929155100744此时服务端也会有相应的打印输出

image-20210929155151548

本文代码

https://github.com/lts8989/gomicro-quickstart

参考

https://segmentfault.com/a/1190000039717888

https://www.cnblogs.com/hongjijun/p/13724738.html

免责声明:文章转载自《grpc-golang入门》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇zabbix自定义邮件报警内容及邮件分级报警说明Hypertext Transfer Protocol HTTP/1.1 Status Code(HTTP 响应状态代码)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

eureka服务列表刷新设置

服务器:当我们启用服务使用者时,它将向服务注册中心发送一个rest请求,以获取上面注册的服务列表。出于性能原因,eureka服务器将维护一个只读缓存服务列表以返回到客户端。默认情况下,缓存列表将每30秒更新一次。如果关闭UseReadOnlyResponseCache,服务器:#将不会读取只读缓存服务列表,因为每30秒刷新一次很慢,所以读/写缓存过期策略Us...

OSSEC初探

OSSEC的初始概念:OSSEC是一个开源的基于主机的入侵检测系统,可以执行日志分析、完整性检查、windows注册表监视、隐藏检测和实时报警。简单地说,OSSEC在C/S模式下工作。代理监视和收集信息并将其报告给服务器。服务器分析并预处理信息,并通过电子邮件将系统更改发送给管理员。...

解决Maven无法下载fastdfs-client-java依赖,Dependency 'org.csource:fastdfs-client-java:1.27-SNAPSHOT' not found.

然后,您成功地将fastdfs客户端java打包到本地Maven仓库,更新项目Maven,pom.xml文件将不会找不到fastdfs客户机java依赖项。...

DB2字符函数简介及使用

Param2可以是编码单元16-16位UTF-16编码,也就是说,字符串表示为16位UTF-18编码字符串。Codeunits32-32位UTF-32编码,即字符串表示为32位UTF 32编码字符串。请注意,定义为FORBITDATA的字符串不能转换为图形字符。如果length<length,则来自的原始字符串短于结果中的长度。...

winform窗体(六)——DataGridView控件及通过此控件中实现增删改查

“,”Delete Data“,btn)==DialogResult.Yes){}V.多条件查询。如果用户没有输入任何内容或文本框为空,则查询所有内容。//设置两个常量条件stringtj1=”1=1“;stringtj2=”1=1”;//根据用户的输入更改条件。//如果用户输入名称If(name!=”“){tj1=“Namelike@name“;}//如果...

Java 安全之:csrf攻击总结

最近,我在维护一些旧项目。在调试期间,我发现请求被反复拒绝。我仔细查看了项目的源代码,发现存在csrftoken验证。我借此机会了解了csrf攻击,并将其总结成一篇论文。受攻击的网站无法阻止攻击。在整个过程中,攻击者无法获取受害者的登录凭据,只能“冒充”。CSRF攻击成功,因为服务器将攻击者发送的请求误认为是用户的请求。服务器通过验证请求是否携带正确的令牌来...