首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >gRPC: 调整数据传输大小限制

gRPC: 调整数据传输大小限制

原创
作者头像
尹东勋
修改于 2021-12-12 16:25:09
修改于 2021-12-12 16:25:09
5.4K1
举报

介绍

本文介绍如何通过 rk-boot 调整 gRPC 数据传输大小限制。

grpc 的大小限制存在于接收方,也就是说发送多大的数据没有限制,接收默认大小是 4MB。

例子里使用的是 google.golang.org/grpc v1.38.0 版本。

什么是 gRPC 数据传输大小限制?

gRPC 服务端默认最大数据传输大小为 4MB,有些时候,我们需要传输更大的数据,比如大图片。

请访问如下地址获取完整教程:

安装

代码语言:txt
AI代码解释
复制
go get github.com/rookie-ninja/rk-boot
go get github.com/rookie-ninja/rk-grpc

快速开始

rk-boot 支持通过代码 & YAML 文件的方式调整大小限制。

为了完整演示,我们创建一个 greeter API

1.创建 protobuf 相关文件

我们使用 buf 命令行来编译 protobuf,需要创建如下几个文件。

文件名

描述

api/v1/greeter.proto

protobuf 文件

buf.yaml

告诉 buf 命令行在哪里寻找 protobuf 文件

buf.gen.yaml

告诉 buf 命令行如何编译 protobuf 文件

  • api/v1/greeter.proto
代码语言:txt
AI代码解释
复制
syntax = "proto3";

package api.v1;

option go_package = "api/v1/greeter";

service Greeter {
  rpc Greeter (GreeterRequest) returns (GreeterResponse) {}
}

message GreeterRequest {
  bytes msg = 1;
}

message GreeterResponse {}
  • buf.yaml
代码语言:txt
AI代码解释
复制
version: v1beta1
name: github.com/rk-dev/rk-demo
build:
  roots:
    - api
  • buf.gen.yaml
代码语言:txt
AI代码解释
复制
version: v1beta1
plugins:
  # protoc-gen-go needs to be installed, generate go files based on proto files
  - name: go
    out: api/gen
    opt:
     - paths=source_relative
  # protoc-gen-go-grpc needs to be installed, generate grpc go files based on proto files
  - name: go-grpc
    out: api/gen
    opt:
      - paths=source_relative
      - require_unimplemented_servers=false
  • 编译 protobuf 文件
代码语言:txt
AI代码解释
复制
$ buf generate

2.创建 boot.yaml

我们通过 boot.yaml 方式来【取消】大小限制,通过 boot.yaml 我们可以取消限制,但是无法调整限制。

调整限制的话,可以通过代码调整,我们也会在下面介绍。

代码语言:txt
AI代码解释
复制
---
grpc:
  - name: greeter                   # Name of grpc entry
    port: 8080                      # Port of grpc entry
    enabled: true                   # Enable grpc entry
    noRecvMsgSizeLimit: true

3.创建 server.go

我们实现了 greeter 接口。

代码语言:txt
AI代码解释
复制
// Copyright (c) 2021 rookie-ninja
//
// Use of this source code is governed by an Apache-style
// license that can be found in the LICENSE file.
package main

import (
	"context"
	"github.com/rookie-ninja/rk-boot"
	"github.com/rookie-ninja/rk-demo/api/gen/v1"
	"github.com/rookie-ninja/rk-grpc/boot"
	"google.golang.org/grpc"
)

// Application entrance.
func main() {
	// Create a new boot instance.
	boot := rkboot.NewBoot()

	// Get grpc entry with name
	grpcEntry := boot.GetEntry("greeter").(*rkgrpc.GrpcEntry)
	grpcEntry.AddRegFuncGrpc(registerGreeter)

	// Bootstrap
	boot.Bootstrap(context.Background())

	// Wait for shutdown sig
	boot.WaitForShutdownSig(context.Background())
}

func registerGreeter(server *grpc.Server) {
	greeter.RegisterGreeterServer(server, &GreeterServer{})
}

type GreeterServer struct{}

func (server *GreeterServer) Greeter(ctx context.Context, request *greeter.GreeterRequest) (*greeter.GreeterResponse, error) {
	return &greeter.GreeterResponse{}, nil
}

4.创建 client.go

我们试着传输 10MB 的数据。

代码语言:txt
AI代码解释
复制
// Copyright (c) 2021 rookie-ninja
//
// Use of this source code is governed by an Apache-style
// license that can be found in the LICENSE file.
package main

import (
	"context"
	"github.com/rookie-ninja/rk-demo/api/gen/v1"
	"google.golang.org/grpc"
	"log"
)

func main() {
	opts := []grpc.DialOption{
		grpc.WithInsecure(),
		grpc.WithBlock(),
	}

	// 1: Create grpc client
	conn, client := createGreeterClient(opts...)
	defer conn.Close()

	kb := 1024
	mb := 1024*kb

	// 2: Call server with 10mb size of data
	if _, err := client.Greeter(context.Background(), &greeter.GreeterRequest{Msg: make([]byte, 10*mb, 10*mb)}); err != nil {
		panic(err)
	}
}

func createGreeterClient(opts ...grpc.DialOption) (*grpc.ClientConn, greeter.GreeterClient) {
	// 1: Set up a connection to the server.
	conn, err := grpc.DialContext(context.Background(), "localhost:8080", opts...)
	if err != nil {
		log.Fatalf("Failed to connect: %v", err)
	}

	// 2: Create grpc client
	client := greeter.NewGreeterClient(conn)

	return conn, client
}

5.文件夹结构

代码语言:txt
AI代码解释
复制
.
├── api
│   ├── gen
│   │   └── v1
│   │       ├── greeter.pb.go
│   │       └── greeter_grpc.pb.go
│   └── v1
│       └── greeter.proto
├── boot.yaml
├── buf.gen.yaml
├── buf.yaml
├── client.go
├── go.mod
├── go.sum
└── server.go

6.验证

不会出现任何错误。

代码语言:txt
AI代码解释
复制
$ go run server.go
$ go run client.go

因为服务端默认只允许接收 4MB 大小的数据,如果我们在 boot.yaml 里把 noRecvMsgSizeLimit 设置成 false,会得到如下错误。

代码语言:txt
AI代码解释
复制
rpc error: code = ResourceExhausted desc = grpc: received message larger than max (10485765 vs. 4194304)

调整【服务端】传输数据大小

上次的例子中,我们使用 noRecvMsgSizeLimit 选项取消了 gRPC 服务端的大小限制,这次,我们试着调整大小。

还是使用上面的 protobuf 文件。

1.修改 boot.yaml

这次我们把 noRecvMsgSizeLimit 设置成 false。

代码语言:txt
AI代码解释
复制
---
grpc:
  - name: greeter                   # Name of grpc entry
    port: 8080                      # Port of grpc entry
    enabled: true                   # Enable grpc entry
    noRecvMsgSizeLimit: false

2.修改 server.go

我们通过 AddServerOptions() 函数设置服务端接收最大值。

代码语言:txt
AI代码解释
复制
// Copyright (c) 2021 rookie-ninja
//
// Use of this source code is governed by an Apache-style
// license that can be found in the LICENSE file.
package main

import (
	"context"
	"github.com/rookie-ninja/rk-boot"
	"github.com/rookie-ninja/rk-demo/api/gen/v1"
	"github.com/rookie-ninja/rk-grpc/boot"
	"google.golang.org/grpc"
)

// Application entrance.
func main() {
	// Create a new boot instance.
	boot := rkboot.NewBoot()

	// Get grpc entry with name
	grpcEntry := boot.GetEntry("greeter").(*rkgrpc.GrpcEntry)
	grpcEntry.AddRegFuncGrpc(registerGreeter)
	
	// *************************************** //
	// *** Set server receive size to 20MB ***
	// *************************************** //
	kb := 1024
	mb := 1024*kb
	grpcEntry.AddServerOptions(grpc.MaxRecvMsgSize(20*mb))

	// Bootstrap
	boot.Bootstrap(context.Background())

	// Wait for shutdown sig
	boot.WaitForShutdownSig(context.Background())
}

func registerGreeter(server *grpc.Server) {
	greeter.RegisterGreeterServer(server, &GreeterServer{})
}

type GreeterServer struct{}

func (server *GreeterServer) Greeter(ctx context.Context, request *greeter.GreeterRequest) (*greeter.GreeterResponse, error) {
	return &greeter.GreeterResponse{}, nil
}

3.验证

不会出现任何错误。

代码语言:txt
AI代码解释
复制
$ go run server.go
$ go run client.go

如果我们发送的数据大于 20mb,会出现如下错误。

代码语言:txt
AI代码解释
复制
rpc error: code = ResourceExhausted desc = grpc: received message larger than max (31457285 vs. 20971520)

调整【客户端】传输数据大小

如果服务端返回的数据大于 4MB,我们需要在客户端调整大小。

代码语言:txt
AI代码解释
复制
kb := 1024
mb := 1024*kb

opts := []grpc.DialOption{
	grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(20*mb)),
	grpc.WithInsecure(),
	grpc.WithBlock(),
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
1 条评论
热度
最新
专业
专业
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
GRPC: 实现 gRPC 代理
使用 rk-boot 启动的 gRPC 代理有一个限制。只有通过代码形式发送的请求,才可以被代理。grpc-gateway 或者 grpcurl 形式的请求暂时不支持。
尹东勋
2021/11/13
2.7K0
GRPC: 实现 gRPC 代理
gRPC: 使用 Buf 快速编译 protobuf 文件
使用过 gRPC 的用户都应该知道,protocol buffer 文件需要使用相关的命令行,把 .proto 文件编译成 .go 文件。
尹东勋
2021/09/28
2.9K0
gRPC: 使用 Buf 快速编译 protobuf 文件
gRPC: 如何实现分布式日志跟踪?
我们会创建 /api/v1/greeter API 进行验证,同时开启 logging, meta 和 tracing 拦截器以达到目的。
尹东勋
2021/10/20
1.1K2
gRPC: 如何实现分布式日志跟踪?
gRPC: 快速创建静态文件下载 Web 服务
rk-boot 提供了一个方便的方法,让用户快速实现网页【浏览和下载】静态文件的功能。
尹东勋
2021/12/06
8590
gRPC: 快速创建静态文件下载 Web 服务
gRPC: 如何让 gRPC 提供 Restful API 服务?
本文将介绍如何让一个 gRPC 服务,同时提供 gRPC 和 Restful API。
尹东勋
2021/10/08
3.1K2
gRPC: 如何让 gRPC 提供 Restful API 服务?
GoFrame 框架: RPC 错误码设计
本文通过一个完整的例子,介绍如何在 GoFrame 框架下设计合理的 API 错误码。
尹东勋
2021/12/22
8170
GoFrame 框架: RPC 错误码设计
gRPC: gRPC 接口与 Restful API 混合使用
这里我们并不是把 gRPC 接口转换成 Restful API,而是让不同的 gRPC 接口与 Restful API 共存。
尹东勋
2021/10/27
1.6K0
gRPC: gRPC 接口与 Restful API 混合使用
gRPC: 如何优雅关闭进程(graceful shutdown)?
通过 AddShutdownHookFunc() 来添加 shutdownhook 函数。
尹东勋
2021/10/20
2.7K1
gRPC: 如何优雅关闭进程(graceful shutdown)?
GoFrame 框架: 添加调用链(Tracing)中间件
通过一个完整例子,在基于 gogf/gf 微服务中添加调用链(Tracing)中间件。
尹东勋
2022/01/01
8700
GoFrame 框架: 添加调用链(Tracing)中间件
gorilla/mux 框架(rk-boot): 添加调用链(Tracing)中间件
通过一个完整例子,在基于 gorilla/mux 微服务中添加调用链(Tracing)中间件。
尹东勋
2022/02/14
7670
gorilla/mux 框架(rk-boot): 添加调用链(Tracing)中间件
gRPC: 如何让 gRPC 提供 Swagger UI?
为了能提供 Swagger UI,我们首先要让 gRPC 提供 Restful API,然后,Swagger UI 才可以访问后台。
尹东勋
2021/10/10
3.8K0
gRPC: 如何让 gRPC 提供 Swagger UI?
gRPC 安全篇-2: 快速实现服务端 JWT 验证
JSON 网络令牌是一种 Internet 标准,用于创建具有可选签名或可选加密的数据,让两方之间安全地表示声明。令牌使用私有秘密或公共/私有密钥进行签名。
尹东勋
2021/12/08
1.5K0
gRPC 安全篇-2: 快速实现服务端 JWT 验证
gRPC: 如何设计 RPC 错误码?
我们介绍 rk-boot 库,一个快速启动 GRPC 的企业级 golang 微服务框架。
尹东勋
2021/09/28
2.7K0
gRPC: 如何设计 RPC 错误码?
GoFrame 框架:优雅关闭进程
rk-boot 是一个可通过 YAML 启动多种 Web 服务的框架。请参考本文最后章节,了解 rk-boot 细节。
尹东勋
2022/01/05
1.9K0
GoFrame 框架:优雅关闭进程
Gin 框架: RPC 错误码设计
通过 rk-boot ,用户可以轻松搭建 Gin 框架微服务,rk-boot 集成了 Panic 捕捉以及标准错误类型。
尹东勋
2021/10/28
1.5K0
Gin 框架: RPC 错误码设计
gRPC 安全篇-1: 快速配置服务端 CORS
gRPC 协议本身是没有跨域(CORS)问题的,因为无法从浏览器里直接发送 HTTP 请求给 gRPC。
尹东勋
2021/12/07
9990
gRPC 安全篇-1: 快速配置服务端 CORS
gRPC: 如何实现文件上传 Restful API ?
注意,grpcEntry.GwMux.HandlePath() 一定要写到 boot.Bootstrap() 之后,否则会出现 Panic。
尹东勋
2021/10/19
3K0
gRPC: 如何实现文件上传 Restful API ?
gRPC: 快速配置通用 API 获取进程元信息
boot.yaml 会告诉 rk-boot 如何启动 gRPC 服务。为了 Demo,除了开启 commonService,我们还开启了如下服务。
尹东勋
2021/12/16
6420
gRPC: 快速配置通用 API 获取进程元信息
gRPC: 通过 Web 获取服务原信息
除了开启 grpc.tv.enabled,我们还开启了其他服务,这样就可以验证完整 TV 页面。
尹东勋
2021/10/27
8900
gRPC: 通过 Web 获取服务原信息
gRPC: 如何添加 API Tracing(调用链)监控拦截器/中间件?
本文将介绍如何在 gRPC 微服务中添加 API Tracing(调用链)拦截器/中间件。也就是可以在 jaeger 里做的 API 监控。
尹东勋
2021/10/18
1.1K0
gRPC: 如何添加 API Tracing(调用链)监控拦截器/中间件?
相关推荐
GRPC: 实现 gRPC 代理
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档