gRPC 学习笔记(grpc实战)
ccwgpt 2024-10-13 01:31 46 浏览 0 评论
1. 问题描述
我们认为是从 DevOps 盛行之后,运维也开始写代码(应该说比以前写的更多),诞生运维开发岗位(应该说越来越多)。比如说,开发 Prometheus Exporter 成为运维的工作(其实以前都是现有的,工作都是别人做好的,基本不用开发,或者简单配置即可实现)。
现在,我们需要为我们自己的应用开发 Prometheus Exporter,但是应用提供 gRPC 接口,所以运维就要看学习如何使用 gRPC 框架。
该笔记将记录:gRPC 的快速入门方法、学习笔记,以及相关问题处理(该笔记是我们对 gRPC 的学习笔记,因此仅记录基础入门相关的内容)。
2. 解决方案
我们通过学习 gRPC 的使用流程,来理解它是如何工作的:
1)编写 .proto 文件:该文件包含 RPC 方法、数据结构等等信息
2)生成桩代码:使用命令 protoc 生成桩代码(能够生成多种语言,比如 Go C++ Java Python C# 等等)。“桩代码”类似于“类库”。
3)编写服务端:在程序中,使用这些类库,编写服务端,实现 RPC 方法。然后,运行该服务端,监听 TCP 端口,等待请求;
4)编写客户端:在程序中,使用这些类库,编写客户端,该客户端连接服务端,并调用这些 RPC 方法,接收服务端返回结果;
在调用时,各个部分之间的关系,可以使用下图解释:
我们使用 Python 语言,因此重点使用 Python 示例。但是,使用其他语言也是可以的,并且只要使用 gRPC 框架,鉴于 gRPC 也是网络通信,所以多个语言之间是互通的。
2.1. 学习路线图
官方文档已经提供详细的示例,是最好的教程。跟着官方文档,一边学习,一边练习,已经足够。
对于 Python 使用 gRPC 框架,如果需要快速入门,建议按照以下顺序阅读文档:
1)针对 gRPC 介绍:Introduction to gRPC | gRPC(https://grpc.io/docs/what-is-grpc/introduction/ )
2)使用 gRPC 框架的入门示例(Python):Quick start | Python | gRPC(https://grpc.io/docs/languages/python/quickstart/ )
3)使用 gRPC 框架的完整示例(Python):Basics tutorial | Python | gRPC(https://grpc.io/docs/languages/python/basics/ )
常用文档(Python):
1)Welcome to gRPC Python’s documentation! — gRPC Python 1.36.1 documentation(https://grpc.github.io/grpc/python/ )
2)Language Guide | Protocol Buffers | Google Developers(https://developers.google.com/protocol-buffers/docs/overview )
3)关于 gRPC 概念及术语:Core concepts, architecture and lifecycle | gRPC(https://grpc.io/docs/what-is-grpc/core-concepts/ )
3. 入门案例
因为我们使用 Python 语言,所以这里的示例使用 Python 环境。虽然与其他语言不同,但是流程是类似的。
3.1. 准备工作(安装环境)
# 为了不影响主机环境,我们选择在 Virtual Environment 中操作
# 既然大家已经开始学习 gRPC 框架,我们相信虚拟环境等工具应该信手拈来,所以该笔记未进一步介绍虚拟环境
mkvirtualenv "grpc"
workon "grpc"
# 安装 gRPC 及工具
pip install grpcio grpcio-tools
3.2. 第一阶段、定义服务
定义 helloworld.proto 文件:
syntax = "proto3";
package helloworld;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
该文件定义“客户端与服务端的通信协议”:
1)站在服务端的角度:届时服务端将实现 Greeter 服务,该服务提供 SayHello 方法,参数为 HelloRequest 结构,返回 HelloReply 结构;
2)站在客户端的角度:届时客户端将调用 Greeter 服务的 SayHello 方法,传入 HelloRequest 结构,获得 HelloReply 结构的响应;
3.3. 第二阶段、创建桩代码
helloworld.proto 文件定义协议,但是无法直接使用,需要生成桩代码(类库)。
使用已有的 Protocal Buffers 定义来创建桩代码:
# 创建桩代码
python -m grpc_tools.protoc \
--proto_path=./ \
--python_out=. --grpc_python_out=. \
./helloworld.proto
当如上命令执行后,将生成如下文件:
1)helloworld_pb2.py:该文件包含我们在“协议”中定义的数据结构、服务信息等等(多用于客户端)。
2)helloworld_pb2_grpc.py:该文件包含 gRPC 相关的方法(多用于服务端)
命令行参数的说明:
1)--proto_path:指定 .proto 查找路径(类似于 Java 的 CLASSPATH,Python 的 PYTHONPATH)。代码通常会写在不同文件中,然后相互引用(import、include),所以需要指定搜索路径,这就是该选项的作用。当然,我们的示例只使用 helloworld.proto,未使用其他文件,所以在这里是多余的。
2)--python_out:helloworld_pb2.py 的输出路径
3)--grpc_python_out:文件 helloworld_pb2_grpc.py 的输出路径
4)helloworld.proto:我们的协议文件
3.4. 第三阶段、编写服务端
定义 helloworld_server.py 文件:
from concurrent import futures
import grpc
import helloworld_pb2
import helloworld_pb2_grpc
class Greeter(helloworld_pb2_grpc.GreeterServicer):
def SayHello(self, request, context):
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)
if __name__ == '__main__':
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
server.add_insecure_port('[::]:50051')
server.start()
server.wait_for_termination()
class Greeter(helloworld_pb2_grpc.GreeterServicer):
1)服务端应该提供服务,所以它要实现 Greeter 服务,继承自 GreeterServicer 类(这基本是固定格式)。然后,实现 SayHello 方法。
2)SayHello 方法的 request 参数则为 HelloRequest 结构,通过 request.name 获取 name 属性;
3)正如协议的定义,该方法返回 HelloReply 结构,该结构包含 message 参数。从代码上看:HelloReply 以方法的形式出现;它的属性以方法参数形式出现;而不是直接传入 HelloReply 结构。
然后,main 方法启动 gRPC 服务,监听 50051 端口,等待客户端的访问。
最后,我们需要启动这个服务端,否则后面的客户端无法连接:python ./helloworld_server.py
3.5. 第四阶段、编写客户端
定义 helloworld_client.py 文件:
from __future__ import print_function
import grpc
import helloworld_pb2
import helloworld_pb2_grpc
from google.protobuf.json_format import MessageToJson
if __name__ == '__main__':
with grpc.insecure_channel('localhost:50051') as channel:
stub = helloworld_pb2_grpc.GreeterStub(channel)
response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'))
print("Greeter client received: " + response.message)
print(MessageToJson(response, including_default_value_fields=True))
MessageToJson():将返回转为 Json 字符串类型
including_default_value_fields=True:如果字段为默认值,是不会在 Client 和 Server 之间传递的。需要该属性,才能显示默认字段。
该示例代码的流程(基本都是这样的流程):
1)连接 gRPC 服务;
2)设置桩代码使用该连接;
3)发送请求,调用那 SayHello 方法,并传入 HelloRequest 结构(当然,这里依旧是以方法的形式来体现数据结构);
运行该客户端,将获取到服务端的输出:
# python3 helloworld_client.py
Greeter client received: Hello, you!
{
"message": "Hello, you!"
}
至此,一个简单的 gRPC 示例就运行成功了。
4. 常见问题处理
4.1. ModuleNotFoundError: No module named 'common_pb2'
ImportError: No module named 'InternalMessage_pb2' · Issue #3430 · protocolbuffers/protobuf(https://github.com/protocolbuffers/protobuf/issues/3430 )
问题描述:
Traceback (most recent call last):
File "agent.py", line 22, in <module>
import controller_pb2 as Controller
File "/srv/http/agent/controller_pb2.py", line 14, in <module>
import common_pb2 as common__pb2
ModuleNotFoundError: No module named 'common_pb2'
问题原因:所有的 .proto 都要参与桩代码的生成。
解决方案:注意在创建桩代码时,我们使用 *.proto 就是为了将所有 .proto 定义参与桩代码的生成。
5. 参考文献
Introduction to gRPC | gRPC(https://grpc.io/docs/what-is-grpc/introduction/ )
Quick start | Python | gRPC(https://grpc.io/docs/languages/python/quickstart/ )
Protobuf to json in python - Stack Overflow(https://stackoverflow.com/questions/19734617/protobuf-to-json-in-python )
python - Protobuf doesn't serialize default values - Stack Overflow(https://stackoverflow.com/questions/31021797/protobuf-doesnt-serialize-default-values )
python - Getting all field names from a protocol buffer? - Stack Overflow(https://stackoverflow.com/questions/24639562/getting-all-field-names-from-a-protocol-buffer )
相关推荐
- 十分钟让你学会LNMP架构负载均衡(impala负载均衡)
-
业务架构、应用架构、数据架构和技术架构一、几个基本概念1、pv值pv值(pageviews):页面的浏览量概念:一个网站的所有页面,在一天内,被浏览的总次数。(大型网站通常是上千万的级别)2、u...
- AGV仓储机器人调度系统架构(agv物流机器人)
-
系统架构层次划分采用分层模块化设计,分为以下五层:1.1用户接口层功能:提供人机交互界面(Web/桌面端),支持任务下发、实时监控、数据可视化和报警管理。模块:任务管理面板:接收订单(如拣货、...
- 远程热部署在美团的落地实践(远程热点是什么意思)
-
Sonic是美团内部研发设计的一款用于热部署的IDEA插件,本文其实现原理及落地的一些技术细节。在阅读本文之前,建议大家先熟悉一下Spring源码、SpringMVC源码、SpringBoot...
- springboot搭建xxl-job(分布式任务调度系统)
-
一、部署xxl-job服务端下载xxl-job源码:https://gitee.com/xuxueli0323/xxl-job二、导入项目、创建xxl_job数据库、修改配置文件为自己的数据库三、启动...
- 大模型:使用vLLM和Ray分布式部署推理应用
-
一、vLLM:面向大模型的高效推理框架1.核心特点专为推理优化:专注于大模型(如GPT-3、LLaMA)的高吞吐量、低延迟推理。关键技术:PagedAttention:类似操作系统内存分页管理,将K...
- 国产开源之光【分布式工作流调度系统】:DolphinScheduler
-
DolphinScheduler是一个开源的分布式工作流调度系统,旨在帮助用户以可靠、高效和可扩展的方式管理和调度大规模的数据处理工作流。它支持以图形化方式定义和管理工作流,提供了丰富的调度功能和监控...
- 简单可靠高效的分布式任务队列系统
-
#记录我的2024#大家好,又见面了,我是GitHub精选君!背景介绍在系统访问量逐渐增大,高并发、分布式系统成为了企业技术架构升级的必由之路。在这样的背景下,异步任务队列扮演着至关重要的角色,...
- 虚拟服务器之间如何分布式运行?(虚拟服务器部署)
-
在云计算和虚拟化技术快速发展的今天,传统“单机单任务”的服务器架构早已难以满足现代业务对高并发、高可用、弹性伸缩和容错容灾的严苛要求。分布式系统应运而生,并成为支撑各类互联网平台、企业信息系统和A...
- 一文掌握 XXL-Job 的 6 大核心组件
-
XXL-Job是一个分布式任务调度平台,其核心组件主要包括以下部分,各组件相互协作实现高效的任务调度与管理:1.调度注册中心(RegistryCenter)作用:负责管理调度器(Schedule...
- 京东大佬问我,SpringBoot中如何做延迟队列?单机与分布式如何做?
-
京东大佬问我,SpringBoot中如何做延迟队列?单机如何做?分布式如何做呢?并给出案例与代码分析。嗯,用户问的是在SpringBoot中如何实现延迟队列,单机和分布式环境下分别怎么做。这个问题其实...
- 企业级项目组件选型(一)分布式任务调度平台
-
官网地址:https://www.xuxueli.com/xxl-job/能力介绍架构图安全性为提升系统安全性,调度中心和执行器进行安全性校验,双方AccessToken匹配才允许通讯;调度中心和执...
- python多进程的分布式任务调度应用场景及示例
-
多进程的分布式任务调度可以应用于以下场景:分布式爬虫:importmultiprocessingimportrequestsdefcrawl(url):response=re...
- SpringBoot整合ElasticJob实现分布式任务调度
-
介绍ElasticJob是面向互联网生态和海量任务的分布式调度解决方案,由两个相互独立的子项目ElasticJob-Lite和ElasticJob-Cloud组成。它通过弹性调度、资源管控、...
- 分布式可视化 DAG 任务调度系统 Taier 的整体流程分析
-
Taier作为袋鼠云的开源项目之一,是一个分布式可视化的DAG任务调度系统。旨在降低ETL开发成本,提高大数据平台稳定性,让大数据开发人员可以在Taier直接进行业务逻辑的开发,而不用关...
- SpringBoot任务调度:@Scheduled与TaskExecutor全面解析
-
一、任务调度基础概念1.1什么是任务调度任务调度是指按照预定的时间计划或特定条件自动执行任务的过程。在现代应用开发中,任务调度扮演着至关重要的角色,它使得开发者能够自动化处理周期性任务、定时任务和异...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- MVC框架 (46)
- spring框架 (46)
- 框架图 (58)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- jpa框架 (47)
- laravel框架 (46)
- springmvc框架 (49)
- 分布式事务框架 (65)
- scrapy框架 (56)
- shiro框架 (61)
- 定时任务框架 (56)
- java日志框架 (61)
- JAVA集合框架 (47)
- grpc框架 (55)
- ppt框架 (48)
- 内联框架 (52)
- winform框架 (46)
- gui框架 (44)
- cad怎么画框架 (58)
- ps怎么画框架 (47)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)
- oracle提交事务 (47)