Grpc Quick Start 之协议分析

13 篇文章 1 订阅

技术介绍

gRPC是由 google开发的一个高性能、通用的开源RPC框架,主要面向移动应用开发且基于HTTP/2协议标准而设计,同时支持大多数流行的编程语言。

这里有几个关键词

  • google开发 大公司背景 相对于dubbo2 rpc框架,grpc提供了跨语言的调用 生态更加完整
  • HTTP/2 ,底层基于HTTP2进行数据通信,因此天然支持HTTP REST API 、GRPC接口调用转换

Quick Start

官网Example

  • 下载源码代码
git clone https://github.com/grpc/grpc-go.git 
  • 下载依赖
// cd grcp-go
go mod tidy
  • example 地址

在这里插入图片描述

如图,上面的代码案例 展示grpc的入门以及各种特性应用的demo,后面一个个学习下。今天学下下grpc入门级别的demo。代码谓语helloworld目录下

服务端代码

package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"net"
	"google.golang.org/grpc"
	pb "google.golang.org/grpc/examples/helloworld/helloworld"
)

var (
	port = flag.Int("port", 50051, "The server port")
)

// server is used to implement helloworld.GreeterServer.
type server struct {
	pb.UnimplementedGreeterServer
}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	log.Printf("Received: %v", in.GetName())
	return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}

func main() {
	flag.Parse()
	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	s := grpc.NewServer()
	pb.RegisterGreeterServer(s, &server{})
	log.Printf("server listening at %v", lis.Addr())
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

客户端代码

package main

import (
	"context"
	"flag"
	"log"
	"time"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	pb "google.golang.org/grpc/examples/helloworld/helloworld"
)

const (
	defaultName = "world"
)

var (
	addr = flag.String("addr", "localhost:50051", "the address to connect to")
	name = flag.String("name", defaultName, "Name to greet")
)

func main() {
	flag.Parse()
	// Set up a connection to the server.
	conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()
	c := pb.NewGreeterClient(conn)

	// Contact the server and print out its response.
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	r, err := c.SayHello(ctx, &pb.HelloRequest{Name: *name})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}
	log.Printf("Greeting: %s", r.GetMessage())
}

代码结构如下

AndydeMacBook-Pro:helloworld andy$ tree
.
├── greeter_client
│   └── main.go
├── greeter_server
│   └── main.go
└── helloworld
    ├── helloworld.pb.go
    ├── helloworld.proto
    └── helloworld_grpc.pb.go

执行结果

  • 启动服务器
  • 启动客户端
  • 输出结果

服务端:

在这里插入图片描述

客户端:

在这里插入图片描述

至此,一个简单的grpc远程调用执行完毕, 接下来使用抓包工具Wireshark 分析下如何利用http2进行数据通信,以及http2数据通信的一些细节。关于Wireshark抓包工具的安装这里不做介绍了。

抓包分析

抓包步骤

选择网卡

由于Quick Start的demo只是在本机做远程调用,因此选择 loopback 回环网卡,双击进入

在这里插入图片描述

过滤参数

为了防止其他数据的干扰,过滤来源、目标端口为50051的数据即可。过滤参数为:tcp.dstport50051 or tcp.srcport50051。并重新启动客户端

在这里插入图片描述

如上图,已经抓到了一次grpc调用的完整的数据包,只是上述的数据偏向底层,无法直观的进行分析,幸运的是wireshark支持HTTP2协议,只需要选择合适的编码就可以让数据展示更加直观。

选择HTTP2编码
  • 选中任一数据行,右键选择编码

在这里插入图片描述

  • 选择HTTP2编码

在这里插入图片描述

  • 展示最终结果

在这里插入图片描述

协议分析

在这里插入图片描述

结论:

  1. HTTP2 在TCP链接的基础上多了几次数据交互的过程

  2. 在GRPC中 所有的请求默认都转换为HTTP POST请求

  3. POST请求中的URI对应为protobuf文件中定义/package/class/method

    在这里插入图片描述

  4. 一次HTTP请求 将header、body分开发送

ERROR vs HTTP STATUS CODE

GRPC异常 与 HTTP状态码对应关系如下:

HTTP Status CodeGRPC Status Code
400 Bad RequestINTERNAL
401 UnauthorizedUNAUTHENTICATED
403 ForbiddenPERMISSION_DENIED
404 Not FoundUNIMPLEMENTED
429 Too Many RequestsUNAVAILABLE
502 Bad GatewayUNAVAILABLE
503 Service UnavailableUNAVAILABLE
504 Gateway TimeoutUNAVAILABLE
All other codesUNKNOWN

最佳性能实践

摘自官方文档:

  • 尽可能的重用利用Channel
  • 保持HTTP2底层TCP连接处于活跃状态,即利用心跳检测保持长链接(即C++通道参数 GRPC_arg_keepalive_TIME_MS)
  • 客户端、服务端双向通信使用 streaming RPC
  • 每个gRPC通道使用0个或更多HTTP/2连接,并且每个连接通常对并发流的数量有限制。当连接上的活动RPC数达到此限制时,其他RPC将在客户端中排队,并且必须等待活动RPC完成后才能发送。具有高负载或长寿命流式RPC的应用程序可能会因为这种排队而出现性能问题。有两种可能的解决方案
    • 每个高负载区域创建独立的Channel通道
    • 使用 gRPC 连接池
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值