Serverless Function Library

一个用于简化 Serverless 函数开发和调用的 Rust 库。核心设计理念是让调用 Serverless 函数如同调用普通函数一样简单,通过 Feature 标志灵活控制函数的调用方式(远程调用或本地调用)。
目录
功能特点
- 🎯 简化调用接口 - 提供与普通函数相同的调用语法,隐藏底层网络通信、序列化等复杂性
- 🚀 智能部署策略 - 根据 Feature 标志自动选择部署方式,支持远程调用和本地调用
- 🔧 本地调试友好 - 在本地环境中无需实际部署即可测试
- 🔒 类型安全 - 使用 Rust 的类型系统确保参数和返回值的安全性
- 📦 多种序列化格式 - 支持 JSON 和 Postcard 序列化
- 📊 遥测支持 - 可选的指标收集和分布式追踪功能
快速开始
在 Cargo.toml 中添加依赖:
[dependencies]
serverless-fn = "0.1.0"
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
使用方法
定义 Serverless 函数
use serverless_fn::{serverless, ServerlessError};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
pub struct Post {
pub id: u64,
pub title: String,
pub content: String,
}
#[serverless]
pub async fn read_posts(how_many: usize, query: String) -> Result<Vec<Post>, ServerlessError> {
let posts = (0..how_many)
.map(|i| Post {
id: i as u64,
title: format!("Post {}", i),
content: format!("Content of post {}", i),
})
.collect();
Ok(posts)
}
调用 Serverless 函数
use serverless_fn::{serverless, ServerlessError, config};
#[tokio::main]
async fn main() -> Result<(), ServerlessError> {
let cfg = config::Config::from_env();
cfg.init_logging();
let posts = read_posts(3, "my search".to_string()).await?;
println!("Retrieved {} posts", posts.len());
Ok(())
}
启动服务器
use serverless_fn::server::{FunctionServer, ServerlessError};
#[tokio::main]
async fn main() -> Result<(), ServerlessError> {
FunctionServer::new()
.host("0.0.0.0")
.port(3000)
.start()
.await
.map_err(|e| ServerlessError::RemoteExecution(e.to_string()))?;
Ok(())
}
use serverless_fn::server::{FunctionServer, ServerConfig, ServerlessError};
#[tokio::main]
async fn main() -> Result<(), ServerlessError> {
let config = ServerConfig::new()
.host("0.0.0.0")
.port(3000);
FunctionServer::with_config(config)
.start()
.await
.map_err(|e| ServerlessError::RemoteExecution(e.to_string()))?;
Ok(())
}
优雅关闭
use serverless_fn::server::{FunctionServer, ServerlessError};
use tokio::signal;
#[tokio::main]
async fn main() -> Result<(), ServerlessError> {
FunctionServer::new()
.host("0.0.0.0")
.port(3000)
.start_with_graceful_shutdown(async {
let _ = signal::ctrl_c().await;
})
.await
.map_err(|e| ServerlessError::RemoteExecution(e.to_string()))?;
Ok(())
}
特性标志
| Feature |
描述 |
默认 |
remote_call |
启用远程调用模式 |
✅ |
local_call |
启用本地函数调用模式 |
❌ |
json_serialization |
使用 JSON 进行序列化 |
✅ |
postcard_serialization |
使用 Postcard 进行序列化 |
❌ |
mock_server |
启用模拟服务器用于测试 |
❌ |
telemetry |
启用遥测和监控功能 |
❌ |
配置选项
环境变量
| 变量名 |
描述 |
默认值 |
SERVERLESS_BASE_URL |
远程服务的基础 URL |
http://localhost:3000 |
SERVERLESS_TIMEOUT |
请求超时时间(毫秒) |
30000 |
SERVERLESS_RETRIES |
重试次数 |
3 |
SERVERLESS_LOG_LEVEL |
日志级别 |
info |
编程方式配置
use serverless_fn::config::{Config, DeployStrategy, ConfigBuilder};
use std::time::Duration;
let config = Config::builder()
.base_url("http://api.example.com")
.timeout(Duration::from_secs(60))
.retries(5)
.log_level("debug")
.deploy_strategy(DeployStrategy::Remote)
.build();
let config = Config::from_env();
config.init_logging();
架构模块
| 模块 |
描述 |
client |
客户端运行时,负责发起远程调用 |
server |
服务端运行时,负责处理函数请求 |
transport |
传输层抽象,HTTP 传输实现 |
serializer |
序列化/反序列化模块,支持 JSON 和 Postcard |
config |
配置管理模块 |
error |
统一错误处理模块 |
telemetry |
遥测和监控模块 |
错误处理
ServerlessError 定义了统一的错误类型:
pub enum ServerlessError {
Transport(String), Serialization(String), RemoteExecution(String), Timeout(String), Authentication(String), Generic(String), }
错误处理示例
use serverless_fn::ServerlessError;
async fn handle_request() -> Result<(), ServerlessError> {
let result = read_posts(10, "query".to_string()).await?;
Ok(())
}
match read_posts(10, "query".to_string()).await {
Ok(posts) => println!("Got {} posts", posts.len()),
Err(ServerlessError::Transport(e)) => eprintln!("Network error: {}", e),
Err(ServerlessError::Serialization(e)) => eprintln!("Serialization error: {}", e),
Err(e) => eprintln!("Other error: {}", e),
}
示例
完整示例
运行示例代码:
cargo run --example usage_example -- --serve
cargo run --example usage_example
启用遥测功能
[dependencies]
serverless-fn = { version = "0.1.0", features = ["telemetry"] }
use serverless_fn::telemetry;
#[tokio::main]
async fn main() -> Result<(), ServerlessError> {
telemetry::init_telemetry();
let result = telemetry::telemetry_middleware("read_posts", async {
read_posts(10, "query".to_string()).await
}).await?;
let collector = telemetry::get_metrics_collector();
println!("Total invocations: {}", collector.invocation_count());
println!("Average duration: {}ms", collector.avg_duration_ms());
Ok(())
}
开发
构建要求
运行测试
cargo test
cargo test --lib
cargo clippy --all-targets -- -D warnings
cargo fmt --all
许可证
本项目采用 MIT 许可证。详见 LICENSE 文件。
贡献
欢迎贡献代码、报告问题或提出建议!
- Fork 本仓库
- 创建你的特性分支 (
git checkout -b feature/AmazingFeature)
- 提交你的更改 (
git commit -m 'Add some AmazingFeature')
- 推送到分支 (
git push origin feature/AmazingFeature)
- 开启一个 Pull Request
相关链接