5 个版本 (1 个稳定版本)
1.0.0 | 2023 年 6 月 26 日 |
---|---|
0.1.3 | 2023 年 5 月 26 日 |
0.1.2 | 2023 年 5 月 26 日 |
0.1.1 | 2023 年 5 月 25 日 |
0.1.0 | 2023 年 5 月 25 日 |
#1307 在 异步
每月下载量 52 次
33KB
234 行
Glommio 消息框架 (GMF)
GMF 库是一个强大而创新的框架,旨在简化 Rust 中的远程过程调用 (RPC)。它利用了 Glommio 和 Tonic 库的效率和性能能力。
我们的库巧妙地将 Glommio 的现代协作线程模型与 Tonic 的基于 gRPC 的协议处理相结合,提供了一个异步、高性能的 RPC 工具,适用于现代微服务架构。
GMF 允许您以高效、轻量级和强大的方式管理您的 RPC,同时从头到尾保持完全异步。通过实现基于 Glommio 协作线程模型的执行器,该库提供了低延迟、高吞吐量操作和优异的资源利用。
请注意,GMF 专门为 Linux 设计,利用了几个 Linux 特定的功能来提供其功能。
利用 Glommio 实现高性能网络
Glommio 通过优化网络操作的处理方式,旨在提供高性能的网络功能。它使用围绕无共享设计、单线程执行和绕过传统网络层的技巧。让我们深入了解这些技巧
-
无共享设计:Glommio 是围绕无共享架构设计的,这意味着每个 CPU 核心独立于其他核心操作。这种架构最大限度地减少了线程同步可能引起的竞争和开销,从而提高了性能和效率。每个核心都有自己的私有内存,并且不需要锁来访问共享数据。这种方法特别有利于处理高并发级别和实现高吞吐量网络服务。
-
单线程执行:每个核心运行一个线程,以异步、非阻塞的方式处理所有分配给它的任务。这种模型进一步降低了线程之间上下文切换相关的开销,并能够高效地执行大量并发任务。
-
使用 io_uring 进行高效的 I/O 操作:Glommio 设计用于充分利用 Linux 内核最新版本中引入的强大接口 io_uring,它允许进行高度高效的异步 I/O 操作。
与传统的模型不同,传统的模型在每次I/O操作时都会进行系统调用,这导致由于上下文切换和中断而产生的性能开销,io_uring允许应用程序使用用户空间中的环形缓冲区来入队和出队I/O操作。这些操作可以成批处理,显著减少系统调用和上下文切换的需求。
Glommio利用io_uring直接管理和优化网络和文件I/O操作,绕过了传统的内核网络层。这导致了更低的延迟、更高的吞吐量和更具可扩展性的I/O操作。
io_uring和Glommio的异步编程模型的组合是GMF高性能设计的核心。有了这些特性,GMF能够提供卓越的I/O性能和可扩展性,使其成为网络密集型应用的优秀选择。
当涉及到处理gRPC服务时,这些技术允许高效处理大量的RPC调用。使用异步、事件驱动的模型,入站请求可以在到达时进行处理,而不需要阻塞线程或进行上下文切换。结果是,gRPC服务不仅性能高,而且资源效率高,使微服务架构能够更好地扩展。
系统要求
重要:本项目仅适用于Linux系统。请在安装或使用此软件包之前确保您正在运行兼容的Linux发行版。
入门指南
要使用gmf
,请将以下内容添加到您的Cargo.toml
[dependencies]
gmf = "1.0.0"
然后您可以将它包含到项目中
use gmf::GmfServer;
use std::net::SocketAddr;
use tower::Service;
用法
定义完您的服务(如MyGreeter
)后,只需几行代码即可使用GmfServer
来提供服务
let greeter: MyGreeter = MyGreeter::default();
let tonic: GreeterServer<MyGreeter> = GreeterServer::new(greeter);
use hyper::service::service_fn;
let gmf = GmfServer::new(
service_fn(move |req| {
let mut tonic = tonic.clone();
tonic.call(req)
}),
10240, // max_connections
);
let addr: SocketAddr = "0.0.0.0:50051".parse().unwrap();
gmf.serve(addr).unwrap_or_else(|e| panic!("failed {e}"));
有关完整的工作示例,请参阅示例源代码
使用Nix设置开发环境
如果您的机器上没有安装所需的工具,Nix提供了一个简单且一致的方法来设置开发环境。此设置过程假定您的机器上已安装Nix。如果没有,您可以从官方Nix网站安装它。
1. 定义您的环境
在项目的根目录下创建一个名为shell.nix
的文件,并定义您项目所需的项目。例如,您的shell.nix
文件可能看起来像这样
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
buildInputs = [
pkgs.rustc
pkgs.cargo
pkgs.protobuf
];
}
此shell.nix
文件告诉Nix您需要rustc
、cargo
和protobuf
为您的项目。您可以根据项目的需求添加或删除包。
2. 进入Nix Shell
您现在可以通过在项目的根目录中运行以下命令来进入开发环境
nix-shell
Nix将下载并安装您在shell.nix
中定义的包,然后它会将您放入一个包含这些包的shell中。
3. 开始开发
您现在可以像平常一样运行您的构建命令。您在shell.nix
中定义的工具将可用在您的路径中。
请注意,Nix shell仅影响您当前的控制台会话。如果您打开一个新的终端,您需要再次运行nix-shell
来进入开发环境。此外,Nix安装的包不会影响您的系统全局状态,而是被隔离在Nix shell中。
请始终在尽可能接近生产环境的环境中测试您的应用程序,以确保它按预期工作。
在非Linux环境中测试和运行示例
本项目利用了特定的Linux特性,因此不与MacOS或Windows等非Linux环境直接兼容。但是,我们提供了一种使用Docker构建、测试和运行示例的方法。Docker允许您在容器内创建Linux环境。
先决条件
- 在你的机器上安装Docker。
构建Docker镜像
在运行项目之前,你需要构建一个包含Rust工具链和protoc
的Docker镜像。我们已经为此创建了一个Dockerfile和一个简化构建过程的脚本。
步骤 1:构建Docker镜像
-
导航到项目目录
cd /path/to/your/project
-
使构建脚本可执行
chmod +x build_docker_image.sh
-
运行构建脚本
./build_docker_image.sh
此脚本默认构建一个名为
rust-protoc:nightly-bookworm
的Docker镜像。如果构建成功,你将看到以下消息Docker Image rust-protoc:nightly-bookworm has been built successfully.
步骤 2:使用Docker镜像运行项目
构建Docker镜像后,你可以使用它来编译和运行你的Rust项目。
-
确保运行脚本可执行
chmod +x cargo-docker.sh
-
使用脚本运行你的Cargo命令。例如,要运行
cargo check
命令./cargo-docker.sh check
脚本自动处理Docker容器生命周期,根据需要创建或启动容器,并在其中运行你的Cargo命令。
运行示例
要运行Docker容器内的示例,你可以使用cargo-docker.sh
脚本,后跟run --package examples --bin <example_name> --features <feature-name>
。用示例的名称和你要运行的所需特性替换example_name
和feature-name
./cargo-docker.sh run --package examples --bin helloworld-gmf-server --features hyper-warp
测试
要运行Docker容器内的测试,你可以使用cargo-docker.sh
脚本,后跟test
./cargo-docker.sh test
使用grpcurl
与gRPC服务交互
grpcurl
是一个命令行工具,让你可以与gRPC服务器交互。它就像curl
,但用于gRPC!
以下是使用grpcurl
向本项目定义的gRPC服务发送请求的方法
-
安装
grpcurl
:如果你还没有安装grpcurl
,你可以在这里找到安装说明here。 -
准备你的请求:例如,如果你正在调用
Greeter
服务的SayHello
方法,你的请求可能看起来像这样{ "name":"John" }
-
调用服务:你可以使用
grpcurl
将此请求发送到你的运行中的gRPC服务grpcurl -plaintext -d '{"name":"John"}' -proto examples/proto/helloworld/helloworld.proto 0.0.0.0:50051 helloworld.Greeter/SayHello
在这个命令中
-plaintext
告诉grpcurl
使用HTTP/2明文而不是TLS。-d '{"name":"John"}'
是要与你请求一起发送的数据。-proto examples/proto/helloworld/helloworld.proto
告诉grpcurl
在哪里查找 protobuf 服务定义。0.0.0.0:50051
是您 gRPC 服务运行地址和端口号。helloworld.Greeter/SayHello
是您调用的方法的完整名称。
注意:如果 gRPC 服务运行在 Docker 容器中,请确保 Docker 容器的端口已正确映射到主机的端口。
在您的 IDE 中使用远程开发功能
IntelliJ IDEA 通过名为“远程开发”的功能支持远程开发。此功能需要 IntelliJ IDEA 的“终极”版本。
以下是设置 IntelliJ IDEA 远程开发环境的常规步骤
-
配置远程 SDK:
- 转到“文件” > “项目结构” > “SDKs”(在左侧面板)。
- 点击顶部栏上的“+”按钮 > 选择“远程”或“Docker”。
- 然后,您需要提供您的远程环境或 Docker 的详细信息。
-
配置项目 SDK:
- 在同一“项目结构”窗口中,点击左侧面板上的“项目”。
- 在“项目 SDK”下,选择您刚刚配置的远程 SDK。
- 点击“应用”。
-
配置运行/调试配置:
- 转到“运行” > “编辑配置”。
- 在您想要远程运行的配置中,在“使用模块类路径”下选择远程 SDK。
- 点击“应用”。
现在,当您运行应用程序时,它将在远程环境中运行,但您仍然可以使用本地计算机上 IntelliJ IDEA 的所有功能。
请注意,具体步骤可能会根据您使用的 IntelliJ IDEA 版本以及您是否使用 Docker 或其他类型的远程环境而略有不同。
如果您想使用远程开发环境,但您使用的是 IntelliJ IDEA 的“社区”版,一种解决方案是使用带有“远程 - SSH”或“远程 - 容器”扩展的 Visual Studio Code,这些扩展提供类似的功能,且免费使用。
最后,请记住,尽管您可以在远程环境中运行应用程序,但若要使用 IntelliJ IDEA 的代码导航和其他功能,源代码本身仍然需要存储在本地。如果您目前只将代码存储在 Docker 容器中,您可能需要更改设置,将代码存储在本地计算机上,并将其作为卷挂载到 Docker 容器中。
基准测试
使用 ghz
基准测试 gRPC 服务
您可以使用像 ghz
这样的基准测试工具,这是一个用 Go 编写的性能 gRPC 基准测试工具。
首先,您需要安装 ghz
。如果您已安装 Go,可以使用
brew install ghz
或者您可以从 ghz
的 发布页面 下载预编译的二进制文件。
一旦安装了 ghz
,您可以使用以下命令运行基准测试
ghz --insecure --proto examples/proto/helloworld/helloworld.proto --call helloworld.Greeter.SayHello -d '{"name":"Test"}' -c 200 -n 2000 0.0.0.0:50051
在这个命令中
--insecure
:禁用 TLS。--proto /path/to/helloworld.proto
:服务协议缓冲定义的路径。--call helloworld.Greeter.SayHello
:要调用的服务方法的完全限定名称。-d '{"name":"Test"}'
: 请求中要发送的数据。-c 200
: 要发出的并发请求数量。-n 2000
: 要发出的总请求数量。0.0.0.0:50051
: 要基准测试的服务地址和端口。
您需要根据您的服务需要调整--proto
、--call
、--d
、--c
、--n
和服务器地址参数。
请注意,如果测试的服务器使用TLS,您需要使用--cacert
标志将证书文件提供给ghz
工具。您还需要移除--insecure
标志。
性能比较:Tonic与GMF
我们比较了基于Tonic的GRPC服务器和客户端实现与我们的增强型Glommio消息框架(GMF)实现的性能。以下是结果摘要
指标 | 基于Tonic的实现 | 基于GMF的实现 |
---|---|---|
每秒请求数 | 6512.01 | 12009.70 |
最快 | 7.71毫秒 | 1.58毫秒 |
最慢 | 62.15毫秒 | 45.71毫秒 |
平均 | 28.00毫秒 | 16.54毫秒 |
每秒请求数:数值越高越好。此指标表示服务器每秒可以处理的请求数量。
我们发现,基于GMF的实现比基于Tonic的实现每秒可以处理大约84%更多的请求数。
使用Criterion.rs基准测试GMF实现
我们使用Criterion.rs库进行基准测试。以下是运行此项目基准测试的方法
./cargo-docker.sh bench -p examples -- --verbose
这将运行项目中的所有基准测试。
基准测试的输出将保存到target/criterion
目录。您可以通过在您的网络浏览器中打开target/criterion/report/index.html
来查看详细报告。
依赖项
~23–39MB
~621K SLoC