gRPC是什么

官方介绍:

https://grpc.io/docs/what-is-grpc/introduction/

“A high-performance, open-source universal RPC framework”

  • 多语言:语言中立,支持多种语言。
  • 轻量级、高性能:序列化支持 PB(Protocol Buffer)和 JSON,PB 是一种语言无关的高性能序列化框架。
  • IDL:基于文件定义服务,通过 proto3 工具生成指定语言的数据结构、服务端接口以及客户端 Stub。
  • 设计理念
  • 移动端:基于标准的 HTTP2 设计,支持双向流、消息头压缩、单 TCP 的多路复用、服务端推送等特性,这些特性使得 gRPC 在移动端设备上更加省电和节省网络流量。
  • 服务而非对象、消息而非引用:促进微服务的系统间粗粒度消息交互设计理念。
  • 负载无关的:不同的服务需要使用不同的消息类型和编码,例如 protocol buffers、JSON、XML 和 Thrift。
  • 流:Streaming API。
  • 阻塞式和非阻塞式:支持异步和同步处理在客户端和服务端间交互的消息序列。
  • 元数据交换:常见的横切关注点,如认证或跟踪,依赖数据交换。
  • 标准化状态码:客户端通常以有限的方式响应 API 调用返回的错误。

小结

  • grpc是个协议,对应的是proto文件
  • protobuf 是将jrpc转化为代码的工具

安装

grpc包

  1. go get -u google.golang.org/grpc

protobuf

  1. go install google.golang.org/grpc/cmd/protoc-gen-go-grpc

protoc语法

  • -I 参数:指定import路径,可以指定多个-I参数,编译时按顺序查找,不指定时默认查找当前目录
  • --go_out :golang编译支持,支持以下参数
    • plugins=plugin1+plugin2 - 指定插件,目前只支持grpc,即:plugins=grpc
    • M 参数 - 指定导入的.proto文件路径编译后对应的golang包名(不指定本参数默认就是.proto文件中import语句的路径)
    • import_prefix=xxx - 为所有import路径添加前缀,主要用于编译子目录内的多个proto文件,这个参数按理说很有用,尤其适用替代一些情况时的M参数,但是实际使用时有个蛋疼的问题导致并不能达到我们预想的效果,自己尝试看看吧
    • import_path=foo/bar - 用于指定未声明package或go_package的文件的包名,最右面的斜线前的字符会被忽略
    • 末尾 :编译文件路径 .proto文件路径(支持通配符
  1. protoc --go_out=. example.proto
  2. protoc --go-grpc_out=. example.proto

demo

demo git地址

proto文件

  1. syntax = "proto3";
  2. # 定义了包名
  3. package helloworld;
  4. // The greeting service definition.
  5. service Greeter {
  6. // Sends a greeting
  7. rpc SayHello (HelloRequest) returns (HelloReply) {}
  8. }
  9. // The request message containing the user's name.
  10. message HelloRequest {
  11. string name = 1;
  12. }
  13. // The response message containing the greetings
  14. message HelloReply {
  15. string message = 1;
  16. }

生成

  1. protoc --go_out=. helloworld.proto
  2. protoc --go-grpc_out=. helloworld.proto

会多了两个文件

服务端

  1. package main
  2. import (
  3. "context"
  4. "log"
  5. "net"
  6. "google.golang.org/grpc"
  7. pb "google.golang.org/grpc/examples/helloworld/helloworld"
  8. )
  9. const (
  10. port = ":50051"
  11. )
  12. // server is used to implement helloworld.GreeterServer.
  13. type server struct {
  14. pb.UnimplementedGreeterServer
  15. }
  16. // SayHello implements helloworld.GreeterServer
  17. func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
  18. log.Printf("Received: %v", in.GetName())
  19. return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
  20. }
  21. func main() {
  22. lis, err := net.Listen("tcp", port)
  23. if err != nil {
  24. log.Fatalf("failed to listen: %v", err)
  25. }
  26. s := grpc.NewServer()
  27. pb.RegisterGreeterServer(s, &server{})
  28. if err := s.Serve(lis); err != nil {
  29. log.Fatalf("failed to serve: %v", err)
  30. }
  31. }

注意

服务端其实是实现协议中的接口,即实现所有方法

  1. type HelloServer interface {
  2. // 定义SayHello方法
  3. SayHello(context.Context, *HelloRequest) (*HelloResponse, error)
  4. mustEmbedUnimplementedHelloServer()
  5. }

很多教程实现了mustEmbedUnimplementedHelloServer 这个方法,但是由于是小写, 同目录下是好的,跨了目录就会有问题。

应该直接:

  1. type server struct {
  2. pb.UnimplementedGreeterServer
  3. }

客户端

  1. package main
  2. import (
  3. "context"
  4. "log"
  5. "os"
  6. "time"
  7. "google.golang.org/grpc"
  8. pb "google.golang.org/grpc/examples/helloworld/helloworld"
  9. )
  10. const (
  11. address = "localhost:50051"
  12. defaultName = "world"
  13. )
  14. func main() {
  15. // Set up a connection to the server.
  16. conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
  17. if err != nil {
  18. log.Fatalf("did not connect: %v", err)
  19. }
  20. defer conn.Close()
  21. c := pb.NewGreeterClient(conn)
  22. // Contact the server and print out its response.
  23. name := defaultName
  24. if len(os.Args) > 1 {
  25. name = os.Args[1]
  26. }
  27. ctx, cancel := context.WithTimeout(context.Background(), time.Second)
  28. defer cancel()
  29. r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
  30. if err != nil {
  31. log.Fatalf("could not greet: %v", err)
  32. }
  33. log.Printf("Greeting: %s", r.GetMessage())
  34. }

常见的坑

  • grpc版本和protoc的版本不一致,如果是第一次用,就都用最新的就好了,后面就一直用这个版本。或者换最新版本重新生成代码文件。

结语

  • 如果有不对的地方欢迎指正。
  • 如果有不理解的地方欢迎指出我来加栗子。
  • 如果感觉OK可以点赞让更多人看到它。

【微服务落地】服务间通信方式: gRPC的入门的更多相关文章

  1. .NET Core微服务之路:基于gRPC服务发现与服务治理的方案

    重温最少化集群搭建,我相信很多朋友都已经搭建出来,基于Watch机制也实现了出来,相信也有很多朋友有了自己的实现思路,但是,很多朋友有个疑问,我API和服务分离好了,怎么通过服务中心进行发现呢,这个过 ...

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

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

  3. 干货|基于 Spring Cloud 的微服务落地

    转自 微服务架构模式的核心在于如何识别服务的边界,设计出合理的微服务.但如果要将微服务架构运用到生产项目上,并且能够发挥该架构模式的重要作用,则需要微服务框架的支持. 在Java生态圈,目前使用较多的 ...

  4. 基于Spring Cloud的微服务落地

    微服务架构模式的核心在于如何识别服务的边界,设计出合理的微服务.但如果要将微服务架构运用到生产项目上,并且能够发挥该架构模式的重要作用,则需要微服务框架的支持. 在Java生态圈,目前使用较多的微服务 ...

  5. [转]系统架构演变--集中式架构-垂直拆分-分布式服务-SOA(服务治理)-微服务

    一.系统架构演变 1.1. 集中式架构 当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本.此时,用于简化增删改查工作量的数据访问框架(ORM)是影响项目开发的关键. 存在的 ...

  6. .net core grpc consul 实现服务注册 服务发现 负载均衡(二)

    在上一篇 .net core grpc 实现通信(一) 中,我们实现的grpc通信在.net core中的可行性,但要在微服务中真正使用,还缺少 服务注册,服务发现及负载均衡等,本篇我们将在 .net ...

  7. SOA、微服务与服务网格

    SOA架构解析 SOA 全称是: Service Oriented Architecture,中文释义为 “面向服务的架构”,它是一种设计理念,其中包含多个服务, 服务之间通过相互依赖最终提供一系列完 ...

  8. 微服务, 架构, 服务治理, 链路跟踪, 服务发现, 流量控制, Service Mesh

    微服务, 架构, 服务治理, 链路跟踪, 服务发现, 流量控制, Service Mesh 微服务架构   本文将介绍微服务架构和相关的组件,介绍他们是什么以及为什么要使用微服务架构和这些组件.本文侧 ...

  9. [Abp vNext微服务实践] - 服务通讯

    简介 服务通讯是微服务架构中必不可少的功能,服务通讯的效率决定了微服务架构的优略.常用的微服务通讯策略有两种,分别是rpc.http,其中rpc以gRpc框架为代表使用者最多.abp vNext微服务 ...

随机推荐

  1. 一个完整的SEO优化方案

    一个完整的SEO优化方案主要由四个小组组成: 一.前端/页编人员 二.内容编辑人员 三.推广人员 四.数据分析人员 接下来,我们就对这四个小组分配工作. 首先,前端/页编人员主要负责站内优化,主要从四 ...

  2. EcShop首页显示特定分类的精品新品热销特价等推荐商品

    EcShop首页显示特定分类的精品新品热销特价等推荐商品 很多大型的B2C商城都有特定分类专区,该分类下的[分类名称].[推荐子分类 或 推荐品牌].[大图片/推荐单品].[推荐商品].[促销商品]. ...

  3. Docker系列(6)- 常用命令(2) | 镜像命令

    准备工作 知道查看官方文档,官方文档描述的很详细,并且每一种类型.每一个命令的选项都有例子 会使用docker --help查看 镜像命令 docker images 查看所有本地主机上的镜像 [ro ...

  4. 常用的excel技巧

    隐藏 冻结 设置下拉选项 复制.移动sheet 自动求和

  5. python学习笔记(九)-函数2

    交换两个变量的值 a = 2 b = 1 b = 1 a = 2 #方式一: b,a = a,b #交换两个变量的值 print(a,b) #方式二: a = a + b #3 b = a - b # ...

  6. 防刷功能的实现(thinkphp5)

    $seconds = '3'; //时间段[秒] $refresh = '3';//最大次数 $cur_time = time(); if(Session::get('refresh_times')) ...

  7. WPF进阶技巧和实战03-控件(5-列表、树、网格04)

    ListView控件 ListView继承自简单的没有特色的ListBox,增加了对基于列显示的支持,并增加了快速切换视图或显示模式的能力,而不需要重新绑定数据以重新构建列表. ListView类继承 ...

  8. vue+element UI 使用select元素动态的从后台获取到

    VUE select元素动态的从后台获取到 <el-form-item label="选择店铺"> <el-select v-model="value& ...

  9. 学习Tomcat(七)之Spring内嵌Tomcat

    前面的文章中,我们介绍了Tomcat容器的关键组件和类加载器,但是现在的J2EE开发中更多的是使用SpringBoot内嵌的Tomcat容器,而不是单独安装Tomcat应用.那么Spring是怎么和T ...

  10. electron-builder进行DEBUG输出的正确方式

    前言 使用Electron进行打包通常会用到electron-builder或者electron-packager两种工具.在使用electron-builder的时候,由于对机制的不熟悉,我们在打包 ...