1. 前言

之前学习的go的微服务之间还是通过REST API的方式互相调用的,但既然要学习微服务,gRPC肯定是一个绕不过去的需要学习的技术, 所以就开搞吧

2. gRPC与Protobuf简介

gRPC是一款语言中立平台中立、开源的远程过程调用系统

即:gRPC客户端和服务端可以在多种环境中运行和交互,例如用java写一个服务端,可以用go语言写客户端调用

微服务架构中,由于每个服务对应的代码库是独立运行的,无法直接调用,彼此间的通信就是个大问题.

gRPC可以实现将大的项目拆分为多个小且独立的业务模块,也就是服务。各服务间使用高效的protobuf协议进行RPC调用,gRPC默认使用protocol buffers,这是google开源的一套成熟的结构数据序列化机制

当然也可以使用其他数据格式如JSON

可以用proto files创建gRPC服务,用message类型来定义方法参数和返回类型

3. 安装

  • 第一步:下载grpc通用编译器

如下图,解压出来因平台而异会是一个protoc或者protoc.exe

https://github.com/protocolbuffers/protobuf/releases

  • 第二步:把下载的二进制文件路径添加到环境变量中(为了能全局访问protoc)

    • 这里以为mac为例子
# 打开这个
vim ./.bash_profile # 添加如下,后面是路径
alias protoc="/Users/emm/others/protoc-3.12.4-osx-x86_64/bin/protoc" # 刷新环境变量
source ./.bash_profile
  • 第三步: 安装go专用的protoc的生成器

go get github.com/golang/protobuf/protoc-gen-go

安装后会在GOPATH目录下生成可执行文件,protobuf的编译器插件protoc-gen-go,等下执行protoc命令会自动调用这个插件

4. 中间文件演示

4.1 编写中间文件

这里新建一个pbfiles文件夹用于存放protoc文件

// 这个就是protobuf的中间文件

// 指定的当前proto语法的版本,有2和3
syntax = "proto3"; // 指定等会文件生成出来的package
package service; // 定义request
message ProductRequest{
int32 prod_id = 1; // 1代表顺序
} // 定义response
message ProductResponse{
int32 prod_stock = 1; // 1代表顺序
}

4.2 运行protoc命令编译成go中间文件

然后运行以下的命令来生成.go结尾的文件

  • 下面的命令就是我们刚刚下的protoc包以及protoc-gen-go插件的作用
# 编译Product.proto之后输出到service文件夹
protoc --go_out=../service Product.proto

如下就在service文件夹自动生成了一个go文件,并且它提示我们不要去修改它

5. 创建gRPC服务端

5.1 新建Product.protoc

这个protoc文件比上面的多出了一个service的定义和里面的一个方法的定义

// 这个就是protobuf的中间文件

// 指定的当前proto语法的版本,有2和3
syntax = "proto3"; // 指定等会文件生成出来的package
package service; // 定义request model
message ProductRequest{
int32 prod_id = 1; // 1代表顺序
} // 定义response model
message ProductResponse{
int32 prod_stock = 1; // 1代表顺序
} // 定义服务主体
service ProdService{
// 定义方法
rpc GetProductStock(ProductRequest) returns(ProductResponse);
}

5.2 运行protoc命令

注意

  • 这里的protoc命令和之前的命令相比有点不一样
protoc --go_out=plugins=grpc:../service Product.proto

然后还是会在service文件夹下生成一个.go的文件

有两个比较需要注意的

  1. RegisterProdServiceServer

后面需要在server中调用这个来注册

  1. ProdServiceServer的接口定义

我们需要继承这个接口,即实现它所有的方法

5.3 实现RegisterProdServiceServer接口

上面我们在protoc文件中定义了一个ProdService中包含了一个GetProductStock的方法

这里我们要实现自动生成的go文件中的接口

package service

import "context"

type ProdService struct {
} func (ps *ProdService) GetProductStock(ctx context.Context, request *ProductRequest) (*ProductResponse, error) {
return &ProductResponse{ProdStock: request.ProdId}, nil
}

5.4 准备工作完成,创建main函数将服务端跑起来

前面的都是准备工作,这里是真正把服务端跑起来的操作

下面是服务端代码:

package main

import (
"gomicro-quickstart/grpc_demo/service"
"google.golang.org/grpc"
"log"
"net"
) func main() {
// 1. new一个grpc的server
rpcServer := grpc.NewServer() // 2. 将刚刚我们新建的ProdService注册进去
service.RegisterProdServiceServer(rpcServer, new(service.ProdService)) // 3. 新建一个listener,以tcp方式监听8082端口
listener, err := net.Listen("tcp", ":8082")
if err != nil {
log.Fatal("服务监听端口失败", err)
} // 4. 运行rpcServer,传入listener
_ = rpcServer.Serve(listener)
}

排坑

  • 如果遇见类似undefined: grpc.SupportPackageIsVersion6undefined: grpc.ClientConnInterface的错误,可以修改go.mod将grpc版本改到1.27.0


6. 创建gRPC客户端

  • 新建一个grpc_client文件夹存放客户端相关的
  • 并在grpc_client文件夹下再新建一个service文件夹

6.1 拷贝Product.pb.go到客户端service文件夹下

6.2 编写client的main函数

package main

import (
"context"
"fmt"
"gomicro-quickstart/grpc_client/service"
"google.golang.org/grpc"
"log"
) func main() {
// 1. 新建连接,端口是服务端开放的8082端口
// 并且添加grpc.WithInsecure(),不然没有证书会报错
conn, err := grpc.Dial(":8082", grpc.WithInsecure())
if err != nil {
log.Fatal(err)
} // 退出时关闭链接
defer conn.Close() // 2. 调用Product.pb.go中的NewProdServiceClient方法
productServiceClient := service.NewProdServiceClient(conn) // 3. 直接像调用本地方法一样调用GetProductStock方法
resp, err := productServiceClient.GetProductStock(context.Background(), &service.ProductRequest{ProdId: 233})
if err != nil {
log.Fatal("调用gRPC方法错误: ", err)
} fmt.Println("调用gRPC方法成功,ProdStock = ", resp.ProdStock)
}

6.3 运行并显示结果

  • 先把服务端运行起来
  • 再把客户端运行起来

然后客户端输出正确的结果,第一个go的gRPC调用运行成功

go微服务系列(四) - gRPC入门的更多相关文章

  1. go微服务系列(四) - http api中引入protobuf

    1. protobuf相关依赖安装 2. 改造之前的client 2.1 新建proto文件 2.2 运行protoc命令生成go文件 2.3 然后把原来的map修改成具体的类型就可以了 3. 处理j ...

  2. 微服务系列(二)GRPC的介绍与安装

    微服务系列(二)GRPC的介绍与安装 1.GPRC简介 GRPC是Google公司基于Protobuf开发的跨语言的开源RPC框架.GRPC基于HTTP/2协议设计,可以基于一个HTTP/2链接提供多 ...

  3. Spring Cloud微服务系列文,服务调用框架Feign

    之前博文的案例中,我们是通过RestTemplate来调用服务,而Feign框架则在此基础上做了一层封装,比如,可以通过注解等方式来绑定参数,或者以声明的方式来指定请求返回类型是JSON.    这种 ...

  4. 【CHRIS RICHARDSON 微服务系列】微服务架构中的进程间通信-3

    编者的话 |本文来自 Nginx 官方博客,是微服务系列文章的第三篇,在第一篇文章中介绍了微服务架构模式,与单体模式进行了比较,并且讨论了使用微服务架构的优缺点.第二篇描述了采用微服务架构的应用客户端 ...

  5. 【CHRIS RICHARDSON 微服务系列】事件驱动的数据管理-5

    编者的话 |本文来自 Nginx 官方博客,是「Chris Richardson 微服务」系列的第五篇文章.第一篇文章介绍了微服务架构模式,并且讨论了使用微服务的优缺点:第二和第三篇描述了微服务架构模 ...

  6. Dubbo 微服务系列(03)服务注册

    Dubbo 微服务系列(03)服务注册 [TOC] Spring Cloud Alibaba 系列目录 - Dubbo 篇 1. 背景介绍 图1 Dubbo经典架构图 注:本图来源 Dubbo官方架构 ...

  7. 带你十天轻松搞定 Go 微服务系列(一)

    本文开始,我们会出一个系列文章跟大家详细展示一个 go-zero 微服务示例,整个系列分十篇文章,目录结构如下: 环境搭建(本文) 服务拆分 用户服务 产品服务 订单服务 支付服务 RPC 服务 Au ...

  8. 【微服务】之二:从零开始,轻松搞定SpringCloud微服务系列--注册中心(一)

    微服务体系,有效解决项目庞大.互相依赖的问题.目前SpringCloud体系有强大的一整套针对微服务的解决方案.本文中,重点对微服务体系中的服务发现注册中心进行详细说明.本篇中的注册中心,采用Netf ...

  9. 从零开始,轻松搞定SpringCloud微服务系列

    本系列博文目录 [微服务]之一:从零开始,轻松搞定SpringCloud微服务系列–开山篇(spring boot 小demo) [微服务]之二:从零开始,轻松搞定SpringCloud微服务系列–注 ...

随机推荐

  1. Java应用服务器之tomcat基础配置(二)

    前文我们聊了下tomcat的配置文件相关格式和组件简介以及webapp目录结构,manger部署和host managera部署,回顾请参考https://www.cnblogs.com/qiuhom ...

  2. Lua骚操作——三元条件运算符

    本文地址:https://www.cnblogs.com/oberon-zjt0806/p/13337577.html 本文参考了这篇文章 三元运算符 (如果您已经了解什么是三元运算符,请大胆第前往下 ...

  3. STL源码剖析:序

    STL源码包含哪些内容 容器:STL的核心 适配器:容器都是在一种最底层的基础容器上使用适配器实现 空间配置器:提供内存的管理 迭代器:由于遍历容器中的数据 算法:由于操作容器中的数据,如排序,拷贝, ...

  4. Makefile中的一个坑

    问题描述:Makefile中,我想将一个变量的后缀全部进行替换,如将所有的.c后缀变成.d后缀 方法:$(CUR_SOURCE: .c = .d ) 说明:查阅相关资料,了解到上述这种语法就可以将所有 ...

  5. Shell基本语法---case语句

    case语句 格式 case 变量 in 值1 ) 执行动作1 ;; 值2 ) 执行动作2 ;; 值3 ) 执行动作3 ;; .... * ) 如果变量的值都不是以上的值,则执行此程序 ;; esac ...

  6. 解决win10安装flask-mysqldb报错 Python2.7

    win10上安装的pycharm,在pycharm创建的py2.7虚拟环境中安装flask-sqlalchemy 执行pip install flask-mysqldb报错 error: Micros ...

  7. python如何编写win程序

    python可以编写win程序.win程序的格式是exe,下面我们就来看一下使用python编写exe程序的方法. 编写好python程序后py2exe模块即可将其打包为exe程序. 实际操作过程: ...

  8. 你的JavaBean是否真的需要实现Serializable

    众所周知 如果一个对象需要进行网络传输,那么该对象就需要实现Serializable接口,为了防止反序列失败,该对象需提供一个默认的serialVersionUID(该值在反序列化的时候会进行校验校验 ...

  9. 第33课 C++中的字符串

    1. 历史遗留问题及解决方案 (1)历史遗留问题 ①C语言不支持真正意义上的字符串------c语言是用字符数组实现字符串 ②C语言用字符数组和一组函数模拟字符串操作 ③C语言不支持自定义类型,因此无 ...

  10. link小图标以及表格的用法基础

    一.网页小图标的实现 实例: 实现方式: 效果: 二.表格基础 1.表格的组合标签 常用: table tr td caption ①table属性 border  边框 width  宽度 默认按照 ...