一、参考资料

Volo-GitHub

Volo-Overview

二、开发环境搭建

1、安装脚手架

# 安装 volo-cli
cargo install volo-cli
# 验证安装
volo help

2、编写 IDL

# 文件 volo_demo.protosyntax = "proto3";
package volo.demo;message Item {int64 id = 1;string title = 2;string content = 3;map<string, string> extra = 10;
}message GetItemRequest {int64 id = 1;
}message GetItemResponse {Item item = 1;
}service ItemService {rpc GetItem(GetItemRequest) returns (GetItemResponse);
}

IDL 全称为 Interface Definition Language ,即为 接口定义语言,具体语法参考 proto3。

为什么需要 IDL ?首先我们搞明白 RPC 是个什么概念:Remote Produce Call ,远程过程调用。说白了就是 A 机器从直接调用 B 机器上的某个函数或者方法。例如我在 A 机器用 Java 语言写了一个 Add 函数,返回变量加一后的结果,B 机器的 Go 语言程序想直接调用 A 机器的 Add 函数,就像在调用 B 机器本身程序内的函数一样。因此,需要引入 IDL 来定义这样一套接口标准,让 A、B 机器实现这种交互,就算开发语言不同,也能清楚对应调用哪个函数、什么类型的参数。

3、使用脚手架初始化项目

# 初始化项目,并生成模板代码
volo init --includes=idl volo-demo idl/volo_demo.proto# 如果只需要增加一个 IDL(如 client 的 IDL)而不需要生成模板
volo idl add idl/volo_example.proto
#初始化项目后,项目根文件夹下多出以下内容
$ ls
Cargo.lock  Cargo.toml  idl/  rust-toolchain.toml  src/  target/  volo-gen/

三、实现一个 gRPC Server

1、在 src/lib.rs 下实现一个 get_item 方法。

#![feature(type_alias_impl_trait)]pub struct S;#[volo::async_trait]
impl volo_gen::volo::demo::ItemService for S {// 这部分是我们需要增加的代码async fn get_item(&self,_req: volo_grpc::Request<volo_gen::volo::demo::GetItemRequest>,) -> core::result::Result<volo_grpc::Response<volo_gen::volo::demo::GetItemResponse>, volo_grpc::Status>{Ok(volo_grpc::Response::new(Default::default()))}
}

2、然后执行指令编译二进制程序,生成指定的 volo_gen.rs 文件::

cargo update
cargo build

3、此时,我们就可以执行指令把 server 运行起来 :

cargo run --bin server

可以看到 Server 已经成功运行起来,这里用到了 tracing 日志监控输出,后续再详细介绍。

四、实现一个 Client

1、新增依赖

[package]
name = "volo_demo"
version = "0.1.0"
edition = "2021"# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html[dependencies]
anyhow = "1"
async-trait = "0.1"
lazy_static = "1"
tokio = { version = "1", features = ["full"] }
tracing = "0.1"
prost = "0.11"pilota = "*"      # we recommend to use the latest framework version for new features and bug fixes
volo = "*"        # we recommend to use the latest framework version for new features and bug fixes
volo-grpc = "*"   # we recommend to use the latest framework version for new features and bug fixesvolo-gen = { path = "./volo-gen" }[profile.release]
opt-level = 3
debug = true
debug-assertions = false
overflow-checks = false
lto = true
panic = 'unwind'
incremental = false
codegen-units = 1
rpath = false[workspace]
members = ["volo-gen"]
resolver = "2"

2、新增 client.rs

use lazy_static::lazy_static;
use std::net::SocketAddr;lazy_static! {static ref CLIENT: volo_gen::volo::demo::ItemServiceClient = {let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();volo_gen::volo::demo::ItemServiceClientBuilder::new("volo_demo").address(addr).build()};
}#[volo::main]
async fn main() {let req = volo_gen::volo::demo::GetItemRequest { id: 1024 };let resp = CLIENT.clone().get_item(req).await;match resp {Ok(info) => tracing::info!("{:?}", info),Err(e) => tracing::error!("{:?}", e),}
}

3、Client 请求 Server 测试

cargo run --bin server
cargo run --bin client

可以看到已经成功请求。

五、实现一个日志中间件

1、新增日志依赖

tracing = "0.1"
tracing-subscriber = "0.3"

2、在 lib.rs 中新增中间件服务

#![feature(type_alias_impl_trait)]pub struct S;#[volo::async_trait]
impl volo_gen::volo::demo::ItemService for S {// 这部分是我们需要增加的代码async fn get_item(&self,_req: volo_grpc::Request<volo_gen::volo::demo::GetItemRequest>,) -> core::result::Result<volo_grpc::Response<volo_gen::volo::demo::GetItemResponse>, volo_grpc::Status>{Ok(volo_grpc::Response::new(Default::default()))}
}// 中间件服务,打印出我们收到的请求、返回的响应以及消耗的时间
#[derive(Clone)]
pub struct LogService<S>(S);#[volo::service]
impl<Cx, Req, S> volo::Service<Cx, Req> for LogService<S>
whereReq: Send + 'static,S: Send + 'static + volo::Service<Cx, Req>,Cx: Send + 'static,
{async fn call(&mut self, cx: &mut Cx, req: Req) -> Result<S::Response, S::Error> {let now = std::time::Instant::now();let resp = self.0.call(cx, req).await;tracing::info!("Request took {}ms", now.elapsed().as_millis());resp}
}// 我们给这个 Service 包装一层 Layer ,便于 server 、 client 调用
pub struct LogLayer;impl<S> volo::Layer<S> for LogLayer {type Service = LogService<S>;fn layer(self, inner: S) -> Self::Service {LogService(inner)}
}

3、在 Server/Client 中加入日志中间件

use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt};// 只有注册 subscriber 后, 才能在控制台上看到日志输出
tracing_subscriber::registry().with(fmt::layer()).init();// clientuse lazy_static::lazy_static;
use std::net::SocketAddr;
use volo_demo::LogLayer;
use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt};lazy_static! {static ref CLIENT: volo_gen::volo::demo::ItemServiceClient = {let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();volo_gen::volo::demo::ItemServiceClientBuilder::new("volo_demo").layer_inner(LogLayer).address(addr).build()};
}#[volo::main]
async fn main() {// 只有注册 subscriber 后, 才能在控制台上看到日志输出tracing_subscriber::registry().with(fmt::layer()).init();let req = volo_gen::volo::demo::GetItemRequest { id: 1024 };let resp = CLIENT.clone().get_item(req).await;match resp {Ok(info) => tracing::info!("{:?}", info),Err(e) => tracing::error!("{:?}", e),}
}

 4、自定义函数返回


#[volo::async_trait]
impl volo_gen::volo::demo::ItemService for S {// 这部分是我们需要增加的代码async fn get_item(&self,_req: volo_grpc::Request<volo_gen::volo::demo::GetItemRequest>,) -> core::result::Result<volo_grpc::Response<volo_gen::volo::demo::GetItemResponse>,volo_grpc::Status,> {// 默认返回空// Ok(volo_grpc::Response::new(Default::default()))// 返回自定义数据Ok(volo_grpc::Response::new(volo_gen::volo::demo::GetItemResponse {item: Some(volo_gen::volo::demo::Item {id: 1024,title: "hello".to_string(),content: "just for test.".to_string(),extra: Default::default(),}),},))}
}

5、测试

可以看到 gRPC 调用成功,并且日志输出了自定义的返回值!

六、跨语言通讯

Client : Rust 语言

Server : C# 语言

1、公共 IDL

syntax = "proto3";option csharp_namespace = "PrinterGrpcService";package greet;// The greeting service definition.
service Greeter {// Sends a greetingrpc SayHello (HelloRequest) returns (HelloReply);
}// The request message containing the user's name.
message HelloRequest {string name = 1;
}// The response message containing the greetings.
message HelloReply {string message = 1;
}

2、Client 端

按照上述流程,编写 client.rs

use lazy_static::lazy_static;
use std::net::SocketAddr;
use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt};
use myapp::libs::my_tracing::LogLayer;lazy_static! {static ref CLIENT: volo_gen::greet::GreeterClient = {let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();volo_gen::greet::GreeterClientBuilder::new("greet-client").layer_inner(LogLayer).address(addr).build()};
}#[volo::main]
async fn main() {// 只有注册 subscriber 后, 才能在控制台上看到日志输出tracing_subscriber::registry().with(fmt::layer()).init();let req = volo_gen::greet::HelloRequest { name: "yushanma".to_string() };let resp = CLIENT.clone().say_hello(req).await;match resp {Ok(info) => tracing::info!("{:?}", info),Err(e) => tracing::error!("{:?}", e),}
}

2、Server 端

使用 .Net Core 框架创建模板

生成的代码文件跟 volo 如出一辙:定义 IDL,定义服务函数,启动 Server 监听请求。

启动服务端后再启动客户端测试:请求成功!

Volo - Rust gRPC 框架入门相关推荐

  1. grpc框架_grpc的入门使用

    前言 grpc是一个高性能.通用的开源RPC框架,基于HTTP/2协议标准和Protobuf序列化协议开发,支持众多的开发语言.在对接口具有严格约束或者传递大量数据的场景中得到了广泛的应用.本文作者从 ...

  2. Egg框架入门教程合集之插件/工具/教程/专栏/开源项目

    Egg框架入门教程之示例合集 Awesome Egg.js 很棒的清单,精选了最好的Egg.js插件,工具,教程,文章等.欢迎公关! 内容 博客 文章 讲解 会议活动 外挂程式 应用领域 样板 构架 ...

  3. 『Scrapy』爬虫框架入门

    框架结构 引擎:处于中央位置协调工作的模块 spiders:生成需求url直接处理响应的单元 调度器:生成url队列(包括去重等) 下载器:直接和互联网打交道的单元 管道:持久化存储的单元 框架安装 ...

  4. c++框架有哪些_Java Mybatis框架入门教程_v20200726

    MyBatis 的前身是 Apache 的开源项目 iBatis.MyBatis 几乎可以代替 JDBC,是一个支持普通 SQL 查询,存储过程和高级映射的基于 Java 的优秀持久层框架.MyBat ...

  5. Python Django框架入门第一课

    Python Django框架入门 1.Django简介 Django使用python开发的一个免费的Web框架,几乎囊括了Web应用的方方面面,用于快速搭建高性能.优雅的网站. 2.配Django运 ...

  6. [Python] Django框架入门

    说明:Django框架入门 当前项目环境:python3.5.django-1.11 项目名:test1 应用名:booktest 命令可简写为:python manager.py xxx => ...

  7. grpc框架_分布式RPC框架dubbo、motan、rpcx、gRPC、thrift简介与性能比较

    Dubbo Dubbo 是阿里巴巴公司开源的一个Java高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成.曾有一段时间放弃维护,不过当前 ...

  8. python web 框架例子_最快的 Python Web 框架入门

    原标题:最快的 Python Web 框架入门 来源:Python开发 ID:PythonPush 速度比较 框架 实现基础 每秒请求数 平均时间 Sanic Python 3.5 + uvloop ...

  9. SpringBatch批处理框架入门(二)

    这篇文章接上一篇SpringBatch批处理框架入门(一),继续讲解SpringBatch基础知识. 目录 SpringBatch 核心类介绍 SpringBatch 核心类Job SpringBat ...

最新文章

  1. 《评人工智能如何走向新阶段》后记(再续19)
  2. 揭秘码云:全球第二大代码托管平台的核心架构
  3. 添加linux系统调用的两种方式
  4. Google上面有自己给你标注好的数据集
  5. 数据结构---哈夫曼树
  6. Spring MVC:高级会话
  7. 1.4编程基础之逻辑表达式与条件分支 18 点和正方形的关系
  8. linux-选择输入法
  9. 关于在阅读nnUNet代码中的一些小细节的记录(三)
  10. Java基础——Ajax(一)
  11. python文档中文版下载,python帮助文档中文版
  12. 傅里叶变换的相关实验——matlab实现
  13. MySQL批量插入(使用mybatis实现mysql数据库的批量插入操作)
  14. Qt信号与槽实现方式
  15. 世界的物质性及其发展规律
  16. 理解COM的线程套件(转)
  17. 要来了!国内安卓统一推送标准将于 今年3 月开启测试
  18. 人机融合智能:人工智能3.0。道翰天琼认知智能机器人平台API接口大脑为您揭秘
  19. ubuntu下各服务 重启命令
  20. 中国汽车业发展令决策层喜忧参半

热门文章

  1. 医院计算机系统日常维护记录表,医院计算机信息管理系统维护措施
  2. do{...}while(0)的用法
  3. 《深入理解Elasticsearch(原书第2版)》——第1章  Elasticsearch简介
  4. python39使用pip安装easyocr实现文字识别
  5. IE8常见问题及解决方法
  6. 常用神经网络模型及其应用评述(转载)
  7. 思想的对象-The objects of thought
  8. Word 2013版本管理
  9. 利用手机相机实现表面缺陷检测学习【缺陷检测_01】
  10. Python 教你用OpenCV实现给照片换底色