实现跨语言通信:Rust 和 Thrift 的最佳实践

前言

在分布式系统中,服务之间高效且安全的通信至关重要。Apache Thrift 是一个被广泛应用的跨语言 RPC(远程过程调用)框架,它支持多种编程语言,包括 Rust。Rust 以其卓越的性能和内存安全保障,成为越来越多开发者的首选语言。
本文将深入探讨如何在 Rust 项目中集成 Thrift,帮助开发者实现跨服务的高效通信,并且探讨异步编程和 TLS 安全通信的高级实现方式。

什么是 Thrift?

Thrift 是由 Facebook 开发并开源的一个高效的服务框架。它允许你定义数据类型和服务接口,然后生成跨多种编程语言的代码。简单来说,Thrift 提供了一个统一的接口来实现不同语言之间的通信。

集成步骤

你可以通过以下命令安装 Thrift 编译器:

# For macOS using Homebrew
brew install thrift# For Ubuntu
sudo apt-get install thrift-compiler

1. 定义 Thrift 文件

首先,你需要定义一个 .thrift 文件,描述你的数据结构和服务接口。创建一个文件 example.thrift:

namespace rs examplestruct User {1: i32 id,2: string name,3: i32 age
}service UserService {User getUser(1: i32 id),void saveUser(1: User user)
}

这个文件描述了一个 User 结构体和一个 UserService 服务。

2. 生成 Rust 代码

使用 Thrift 编译器生成 Rust 代码:

thrift --gen rs example.thrift

这将会在当前目录下生成一个 gen-rs 目录,里面包含了 Thrift 为 Rust 生成的代码。

3. 在 Rust 项目中使用 Thrift

创建一个新的 Rust 项目:

cargo new rust_thrift_example
cd rust_thrift_example

编辑 Cargo.toml 文件,添加 Thrift 依赖:

[dependencies]
thrift = "0.14.1"

将生成的 gen-rs 文件夹复制到 src 目录下,以便在项目中使用。

接下来,我们编写一个简单的客户端和服务器。

服务器端代码

在 src 目录下创建一个新文件 server.rs,编写服务器端代码:

use thrift::protocol::{TBinaryInputProtocol, TBinaryOutputProtocol};
use thrift::server::{TServer, TSimpleServer};
use thrift::transport::{TBufferedReadTransport, TBufferedWriteTransport, TIoChannel, TTcpChannel, TTcpListener, TTransport};mod gen_rs {pub mod example;
}use gen_rs::example::{User, UserServiceSyncProcessor};struct UserServiceHandler;impl UserServiceSyncProcessor for UserServiceHandler {fn getUser(&self, id: i32) -> thrift::Result<User> {Ok(User { id, name: format!("User{}", id), age: 30 })}fn saveUser(&self, user: User) -> thrift::Result<()> {println!("User saved: {:?}", user);Ok(())}
}fn main() -> thrift::Result<()> {let listener = TTcpListener::new("127.0.0.1:9090")?;let server = TSimpleServer::new(UserServiceHandler,TBinaryInputProtocol::new,TBinaryOutputProtocol::new,TBufferedReadTransport::new,TBufferedWriteTransport::new,listener,);println!("Starting the server...");server.serve()?;Ok(())
}
客户端代码

在 src 目录下创建一个新文件 client.rs,编写客户端代码:

use thrift::protocol::{TBinaryInputProtocol, TBinaryOutputProtocol};
use thrift::transport::{TBufferedReadTransport, TBufferedWriteTransport, TTcpChannel, TTransport};mod gen_rs {pub mod example;
}use gen_rs::example::{UserServiceSyncClient};fn main() -> thrift::Result<()> {let mut transport = TTcpChannel::new();transport.open("127.0.0.1:9090")?;let (i_prot, o_prot) = (TBinaryInputProtocol::new(TBufferedReadTransport::new(transport.try_clone()?)),TBinaryOutputProtocol::new(TBufferedWriteTransport::new(transport)),);let client = UserServiceSyncClient::new(i_prot, o_prot);let user = client.getUser(1)?;println!("Got user: {:?}", user);client.saveUser(user)?;Ok(())
}

4. 运行服务器和客户端

首先,编译并运行服务器:

cargo run --bin server

然后,在另一个终端窗口中运行客户端:

cargo run --bin client

你应该会看到客户端从服务器获取到用户信息并将其保存。

实际应用

在上面的教程中,我们已经成功地实现了一个基础的 Thrift 服务和客户端。但是,在实际应用中,我们可能会遇到更多的需求和挑战。接下来,我们将深入探讨一些常见的需求和解决方案。

异步编程

随着现代应用对性能和并发的要求越来越高,异步编程变得越来越重要。Rust 提供了强大的异步编程支持,我们可以利用这些特性来提升 Thrift 服务的性能。

使用 tokio 和 async 实现异步 Thrift 服务

tokio 是一个用于异步编程的强大框架。我们可以结合 tokio 和 Rust 的 async 特性来实现异步 Thrift 服务。

首先,确保在 Cargo.toml 文件中添加 tokio 依赖:

[dependencies]
thrift = "0.14.1"
tokio = { version = "1", features = ["full"] }然后,修改服务器端代码以支持异步:
use thrift::protocol::{TBinaryInputProtocol, TBinaryOutputProtocol};
use thrift::server::TServer;
use thrift::transport::{TBufferedReadTransport, TBufferedWriteTransport, TIoChannel, TTcpChannel, TTcpListener};
use tokio::net::TcpListener;
use tokio::sync::Mutex;
use std::sync::Arc;mod gen_rs {pub mod example;
}use gen_rs::example::{User, UserServiceAsyncProcessor};struct UserServiceHandler;#[async_trait::async_trait]
impl UserServiceAsyncProcessor for UserServiceHandler {async fn getUser(&self, id: i32) -> thrift::Result<User> {Ok(User { id, name: format!("User{}", id), age: 30 })}async fn saveUser(&self, user: User) -> thrift::Result<()> {println!("User saved: {:?}", user);Ok(())}
}#[tokio::main]
async fn main() -> thrift::Result<()> {let listener = TcpListener::bind("127.0.0.1:9090").await?;let handler = Arc::new(Mutex::new(UserServiceHandler));loop {let (socket, _) = listener.accept().await?;let handler = handler.clone();tokio::spawn(async move {let (i_prot, o_prot) = (TBinaryInputProtocol::new(TBufferedReadTransport::new(TTcpChannel::new(socket))),TBinaryOutputProtocol::new(TBufferedWriteTransport::new(TTcpChannel::new(socket))),);let processor = UserServiceAsyncProcessor::new(handler);let mut server = TServer::new(i_prot, o_prot, processor);server.serve().await.unwrap();});}
}

在这个示例中,我们使用 tokio::net::TcpListener 来异步监听连接,并使用 tokio::spawn 来处理每个连接,从而实现并发处理。

使用 TLS 加密通信

在生产环境中,安全性是极为重要的考量。我们可以使用 TLS (传输层安全) 来加密 Thrift 服务的通信。

配置 TLS
首先,确保在 Cargo.toml 文件中添加 tokio-rustls 依赖:

[dependencies]
thrift = "0.14.1"
tokio = { version = "1", features = ["full"] }
tokio-rustls = "0.22"
rustls = "0.20"

然后,生成自签名证书或使用受信任的证书。为了简化演示,我们使用自签名证书:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes

接着,修改服务器端代码以支持 TLS:

use thrift::protocol::{TBinaryInputProtocol, TBinaryOutputProtocol};
use thrift::server::TServer;
use thrift::transport::{TBufferedReadTransport, TBufferedWriteTransport, TIoChannel, TTcpChannel};
use tokio::net::TcpListener;
use tokio::sync::Mutex;
use tokio_rustls::rustls::{ServerConfig, NoClientAuth, Certificate, PrivateKey};
use tokio_rustls::TlsAcceptor;
use tokio_rustls::rustls::internal::pemfile::{certs, rsa_private_keys};
use std::sync::Arc;
use std::fs::File;
use std::io::{BufReader, self};mod gen_rs {pub mod example;
}use gen_rs::example::{User, UserServiceAsyncProcessor};struct UserServiceHandler;#[async_trait::async_trait]
impl UserServiceAsyncProcessor for UserServiceHandler {async fn getUser(&self, id: i32) -> thrift::Result<User> {Ok(User { id, name: format!("User{}", id), age: 30 })}async fn saveUser(&self, user: User) -> thrift::Result<()> {println!("User saved: {:?}", user);Ok(())}
}#[tokio::main]
async fn main() -> thrift::Result<()> {let mut config = ServerConfig::new(NoClientAuth::new());let cert_file = &mut BufReader::new(File::("cert.pem")?);let key_file = &mut BufReader::new(File::open("key.pem")?);let cert_chain = certs(cert_file).map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid cert"))?;let mut keys = rsa_private_keys(key_file).map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid key"))?;config.set_single_cert(cert_chain, keys.remove(0)).map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid key"))?;let acceptor = TlsAcceptor::from(Arc::new(config));let listener = TcpListener::bind("127.0.0.1:9090").await?;let handler = Arc::new(Mutex::new(UserServiceHandler));loop {let (socket, _) = listener.accept().await?;let handler = handler.clone();let acceptor = acceptor.clone();tokio::spawn(async move {let tls_socket = acceptor.accept(socket).await.unwrap();let (i_prot, o_prot) = (TBinaryInputProtocol::new(TBufferedReadTransport::new(TTcpChannel::new(tls_socket))),TBinaryOutputProtocol::new(TBufferedWriteTransport::new(TTcpChannel::new(tls_socket))),);let processor = UserServiceAsyncProcessor::new(handler);let mut server = TServer::new(i_prot, o_prot, processor);server.serve().await.unwrap();});}
}

使用 TLS 的客户端代码类似,只需在创建连接时使用 tokio-rustls 的 TlsConnector 来进行加密连接。

总结

本文详细介绍了如何在 Rust 项目中集成 Apache Thrift,以及如何通过异步编程和 TLS 实现更高效和安全的服务通信。Rust 和 Thrift 的结合为开发者提供了一种可靠的跨语言通信解决方案,能够满足现代分布式系统的高性能和高安全性需求。希望通过本文的教程,开发者能够更好地理解和应用 Rust 和 Thrift,实现高效的分布式系统开发。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/62216.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序按字母顺序渲染城市 功能实现详细讲解

在微信小程序功能搭建中&#xff0c;按字母渲染城市会用到多个ES6的方法&#xff0c;如reduce&#xff0c;map&#xff0c;Object.entries()&#xff0c;Object.keys() &#xff0c;需要组合熟练掌握&#xff0c;才能优雅的处理数据完成渲染。 目录 一、数据分析 二、数据处理 …

前端JavaScript(一)---基本介绍

Javascript是一种由Netscape(网景)的LiveScript发展而来的原型化继承的面向对象的动态类型的区分大小写的客户端脚本语言&#xff0c;主要目的是为了解决服务器端语言&#xff0c;比如Perl&#xff0c;遗留的速度问题&#xff0c;为客户提供更流畅的浏览效果。当时服务端需要对…

git的使用(简洁版)

什么是 Git&#xff1f; Git 是一个分布式版本控制系统 (DVCS)&#xff0c;用于跟踪文件的更改并协调多人之间的工作。它由 Linus Torvalds 在 2005 年创建&#xff0c;最初是为了管理 Linux 内核的开发。Git 的主要目标是提供高效、易用的版本控制工具&#xff0c;使得开发者…

vscode可以编译通过c++项目,但头文件有红色波浪线的问题

1、打开 VSCode 的设置&#xff0c;可以通过快捷键 Ctrl Shift P 打开命令面板&#xff0c;然后搜索并选择 “C/C: Edit Configurations (JSON)” 命令&#xff0c;这将在 .vscode 文件夹中创建或修改 c_cpp_properties.json 文件 {"configurations": [{"name…

VS Code前端常用插件

通用类 auto close tag auto rename tag beautify class autocomplete for html Code Runner css peek dash JavaScript Debugger document this eslint font-awesome codes for html filesize git history gitlens html css support HTMLHint htmltagwrap indenticator Intel…

Android 16 开发者预览版抢先使用

Android 16 开发者预览版 获取 Android 16在 Google Pixel 设备上获取 Android 16设置 Android 模拟器 设置 Android 16 SDK获取 Android Studio安装 SDK更新应用的 build 配置 获取 Android 16 你可以通过以下任一方式获取 Android 16 在 Google Pixel 设备上获取 Android 1…

解析生成对抗网络(GAN):原理与应用

目录 一、引言 二、生成对抗网络原理 &#xff08;一&#xff09;基本架构 &#xff08;二&#xff09;训练过程 三、生成对抗网络的应用 &#xff08;一&#xff09;图像生成 无条件图像生成&#xff1a; &#xff08;二&#xff09;数据增强 &#xff08;三&#xff…

docker 安装mysql8.4.0

1、拉取mysql8.4.0镜像 docker pullmysql:8.4.0-oraclelinux8查看镜像 docker images2、新建宿主机本地目录&#xff1a;用来挂载MySQL容器所产生的数据的目录 mkdir -p /home/admin/data/mysql /home/admin/logs/mysql /home/admin/conf/mysql3、在/home/admin/conf/mysql目…

ABAP OOALV模板

自用模板&#xff0c;可能存在问题 一、主程序 *&---------------------------------------------------------------------* *& Report ZVIA_OO_ALV *&---------------------------------------------------------------------* REPORT ZVIA_OO_ALV.INCLUDE ZVI…

DeepSpeed-chat RLHF实战

轩辕-6bRLHF落地实战 模型介绍&#xff1a;轩辕-6B 模型库 (modelscope.cn) 1.1偏好数据集构建 ​ 1.1.1Prompt构建 1.1.2 Response生成 保证RM训练数据和测试数据分布一致 使用模型来生成response&#xff0c;为了评价response的质量&#xff0c;可以提高采样参数中的…

通过抓包,使用frida定位加密位置

首先我们抓取一下我们要测试的app的某一个目标api&#xff0c;通过抓api的包&#xff0c;得到关键字。 例如&#xff1a;关键字&#xff1a;x-sap-ri 我们得到想要的关键字后&#xff0c;通过拦截 类&#xff0c;寻找我们的关键字&#xff0c;及找到发包收包的位置&#xff0c…

无线WiFi网络版毫米波雷达人体传感器,智能家居节能减排照明有人无人识别

在这个科技日新月异的时代&#xff0c;智能家居已经不再是遥不可及的未来概念&#xff0c;而是悄然融入了我们的日常生活&#xff0c;为我们的生活带来了未有的便捷与舒适。今天&#xff0c;让我们一起探索一项创新性的智能家居技术——飞睿智能无线WiFi网络版毫米波雷达人体传…

Linux介绍与安装指南:从入门到精通

1. Linux简介 1.1 什么是Linux&#xff1f; Linux是一种基于Unix的操作系统&#xff0c;由Linus Torvalds于1991年首次发布。Linux的核心&#xff08;Kernel&#xff09;是开源的&#xff0c;允许任何人自由使用、修改和分发。Linux操作系统通常包括Linux内核、GNU工具集、图…

26.100ASK_T113-PRO 测试摄像头 输出信息

1.测试代码 读到摄象头参数 输出 video_test.c #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/ioctl.h> #include <unistd.h> #include <stdio.h> #include <string.h> #include <linux/type…

Qt读写Usb设备的数据

Qt读写Usb设备的数据 问题:要读取usb设备进行通讯&#xff0c;qt好像没有对应的库支持。解决&#xff1a;libusbwindow下载 :Linux下载: QtUsb 开源的第三方库库里面的函数说明&#xff1a;window版本&#xff1a;Linux中也提供的直接下载测试代码&#xff1a;库下载&#xff1…

2024最新python使用yt-dlp

2024最新python使用yt-dlp下载YT视频 1.获取yt的cookie1&#xff09;google浏览器下载Get cookies.txt LOCALLY插件2&#xff09;导出cookie 2.yt-dlp下载[yt-dlp的GitHub地址](https://github.com/yt-dlp/yt-dlp?tabreadme-ov-file)1&#xff09;使用Pycharm(2024.3)进行代码…

python学opencv|读取图像

【1】引言 前序学习了使用matplotlib模块进行画图&#xff0c;今天开始我们逐步尝试探索使用opencv来处理图片。 【2】学习资源 官网的学习链接如下&#xff1a; OpenCV: Getting Started with Images 不过读起来是英文版&#xff0c;可能略有难度&#xff0c;所以另推荐一…

27加餐篇:gRPC框架的优势与不足之处

gRPC作为一个现代的、开源的远程过程调用(RPC)框架,在多个方面都展现了其优雅之处,同时也存在一些不足之处。这篇文章我们就相对全面的分析一下gRPC框架那些优雅的地方和不足的地方。 优雅的地方 gRPC作为一个RPC框架,在编码、传输协议已经支持多语言方面都比较高效,下…

linux模拟HID USB设备及wireshark USB抓包配置

文章目录 1. 内核配置2. 设备配置附 wireshark USB抓包配置 linux下模拟USB HID设备的简单记录&#xff0c;其他USB设备类似。 1. 内核配置 内核启用USB Gadget&#xff0c;使用fs配置usb device信息。 Device Drivers ---> [*] USB support ---><*> USB …

Ubuntu20.04运行R-VIO2

目录 1.环境配置2.构建项目3. 运行 VIO 模式4.结果图 1.环境配置 CMakeLists.txt中 C 使用 14、opencv使用4 2.构建项目 克隆代码库&#xff1a; 在终端中执行以下命令克隆项目&#xff1a;git clone https://github.com/rpng/R-VIO2.git编译项目&#xff1a; 使用 catkin_m…