Rust分布式系统开发库kurtosis-sdk的使用,kurtosis-sdk助力构建可扩展的微服务与云原生应用

Rust分布式系统开发库kurtosis-sdk的使用,kurtosis-sdk助力构建可扩展的微服务与云原生应用

Kurtosis Rust SDK

这是一个基于Kurtosis的SDK,基于可用的protobufs构建。

示例

确保引擎正在运行:

kurtosis engine start

然后你可以使用Kurtosis+Rust运行一个Starlark脚本:

use kurtosis_sdk::{engine_api::{engine_service_client::{EngineServiceClient}, CreateEnclaveArgs}, enclave_api::{api_container_service_client::ApiContainerServiceClient, RunStarlarkScriptArgs}};
use kurtosis_sdk::enclave_api::starlark_run_response_line::RunResponseLine::InstructionResult;

const STARLARK_SCRIPT : &str = "
def main(plan):
    plan.print('Hello World!')
";

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建enclave
    let mut engine = EngineServiceClient::connect("https://[::1]:9710").await?;
    let create_enclave_response = engine.create_enclave(CreateEnclaveArgs{
        enclave_name: "my-rust-test".to_string(),
        api_container_log_level: "info".to_string(),
        // 默认值
        api_container_version_tag: "".to_string(),
        is_partitioning_enabled: false,
    }).await?.into_inner();
    
    // 连接到enclave
    let enclave_port = create_enclave_response.enclave_info.expect("Enclave info必须存在").api_container_host_machine_info.expect("Enclave主机信息必须存在").grpc_port_on_host_machine;
    let mut enclave = ApiContainerServiceClient::connect(format!("https://[::1]:{}", enclave_port)).await?;
    
    // 运行Starlark脚本
    let mut run_result = enclave.run_starlark_script(RunStarlarkScriptArgs{
        serialized_script: STARLARK_SCRIPT.to_string(),
        serialized_params: "{}".to_string(),
        dry_run: Option::Some(false),
        parallelism: Option::None,
        main_function_name: "main".to_string(),
    }).await?.into_inner();
    
    // 获取输出行
    while let Some(next_message) = run_result.message().await? {
        next_message.run_response_line.map(|line| match line {
            InstructionResult(result) => {
                println!("{}", result.serialized_instruction_result)
            }
            _ => (),
        });
    }
    Ok(())
}

完整示例

以下是一个更完整的示例,展示了如何使用kurtosis-sdk构建微服务:

use kurtosis_sdk::{
    engine_api::{
        engine_service_client::EngineServiceClient, 
        CreateEnclaveArgs,
        GetEnclavesArgs
    },
    enclave_api::{
        api_container_service_client::ApiContainerServiceClient,
        RunStarlarkScriptArgs,
        StartServicesArgs,
        ServiceInfo
    }
};
use tokio::time::{sleep, Duration};

const MICROSERVICE_SCRIPT: &str = r#"
def main(plan):
    # 添加Postgres服务
    postgres = plan.add_service(
        name="postgres",
        config=ServiceConfig(
            image="postgres:latest",
            env_vars={
                "POSTGRES_PASSWORD": "password
            },
            ports={
                "postgres": PortSpec(number=5432)
            }
        )
    )
    
    # 添加Redis服务
    redis = plan.add_service(
        name="redis",
        config=ServiceConfig(
            image="redis:latest",
            ports={
                "redis": PortSpec(number=6379)
            }
        )
    )
    
    # 添加应用服务
    app = plan.add_service(
        name="app",
        config=ServiceConfig(
            image="my-app:latest",
            env_vars={
                "DB_HOST": postgres.hostname,
                "DB_PORT": postgres.ports["postgres"].number,
                "REDIS_HOST": redis.hostname,
                "REDIS_PORT": redis.ports["redis"].number
            },
            ports={
                "http": PortSpec(number=8080)
            }
        )
    )
    
    plan.print("所有服务已启动!")
"#;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 连接到Kurtosis引擎
    let mut engine = EngineServiceClient::connect("http://localhost:9710").await?;
    
    // 创建新的enclave
    let create_response = engine.create_enclave(CreateEnclaveArgs {
        enclave_name: "microservices-demo".to_string(),
        api_container_log_level: "info".to_string(),
        api_container_version_tag: "".to_string(),
        is_partitioning_enabled: false,
    }).await?;
    
    let enclave_info = create_response.into_inner().enclave_info.unwrap();
    let port = enclave_info.api_container_host_machine_info.unwrap().grpc_port_on_host_machine;
    
    // 连接到enclave
    let mut enclave = ApiContainerServiceClient::connect(format!("http://localhost:{}", port)).await?;
    
    // 运行Starlark脚本部署微服务
    let mut run_result = enclave.run_starlark_script(RunStarlarkScriptArgs {
        serialized_script: MICROSERVICE_SCRIPT.to_string(),
        serialized_params: "{}".to_string(),
        dry_run: Some(false),
        parallelism: None,
        main_function_name: "main".to_string(),
    }).await?;
    
    // 检查服务状态
    sleep(Duration::from_secs(5)).await;
    
    let services = enclave.start_services(StartServicesArgs {
        service_identifiers: vec!["postgres".to_string(), "redis".to_string(), "app".to_string()],
    }).await?.into_inner().services;
    
    for (name, service) in services {
        println!("服务 {} 运行在 {}", name, service.private_ip);
        for (port_name, port_spec) in service.ports {
            println!("  - {}: {}", port_name, port_spec.number);
        }
    }
    
    Ok(())
}

安装

在项目目录中运行以下Cargo命令:

cargo add kurtosis-sdk

或者在你的Cargo.toml中添加以下行:

kurtosis-sdk = "1.10.3"

许可证

BUSL-1.1


1 回复

Rust分布式系统开发库kurtosis-sdk的使用指南

概述

kurtosis-sdk是一个用于构建可扩展微服务和云原生应用的Rust开发库,它提供了一套工具和抽象来简化分布式系统的开发过程。该SDK特别适合需要高可靠性和可扩展性的云原生应用场景。

主要特性

  • 分布式服务编排能力
  • 微服务生命周期管理
  • 内置服务发现机制
  • 弹性伸缩支持
  • 云原生友好设计

安装方法

在Cargo.toml中添加依赖:

[dependencies]
kurtosis-sdk = "0.5.0"  # 请使用最新版本
tokio = { version = "1.0", features = ["full"] }

基本使用方法

1. 初始化服务

use kurtosis_sdk::prelude::*;

#[tokio::main]
async fn main() -> Result<(), KurtosisError> {
    let kurtosis_context = KurtosisContext::new()?;
    
    // 服务初始化代码...
    
    Ok(())
}

2. 定义微服务

#[derive(Debug, Service)]
pub struct UserService {
    #[port]
    http_port: PortSpec,
    
    #[configuration]
    config: UserServiceConfig,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct UserServiceConfig {
    db_url: String,
    cache_size: usize,
}

3. 服务部署示例

async fn deploy_user_service(context: &KurtosisContext) -> Result<ServiceHandle, KurtosisError> {
    let config = UserServiceConfig {
        db_url: "postgres://user:pass@db:5432".to_string(),
        cache_size: 1024,
    };
    
    let service = UserService::new(
        PortSpec::http(8080),
        config
    );
    
    let handle = context.deploy_service(service).await?;
    Ok(handle)
}

高级功能

服务发现

async fn discover_services(context: &KurtosisContext) -> Result<(), KurtosisError> {
    let services = context.discover_services().await?;
    
    for service in services {
        println!("Discovered service: {:?}", service.name());
        println!("Service endpoints: {:?}", service.endpoints());
    }
    
    Ok(())
}

弹性伸缩

async fn scale_service(handle: ServiceHandle, replicas: u32) -> Result<(), KurtosisError> {
    handle.scale(replicas).await?;
    Ok(())
}

完整示例

以下是一个完整的微服务系统示例,包含用户服务和API服务:

use kurtosis_sdk::prelude::*;
use serde::{Serialize, Deserialize};

// 用户服务定义
#[derive(Debug, Service)]
pub struct UserService {
    #[port]
    http_port: PortSpec,
    
    #[configuration]
    config: UserServiceConfig,
}

// 用户服务配置
#[derive(Debug, Serialize, Deserialize)]
pub struct UserServiceConfig {
    db_url: String,
    cache_size: usize,
}

// API服务定义
#[derive(Debug, Service)]
pub struct ApiService {
    #[port]
    http_port: PortSpec,
    
    #[dependency]
    user_service: ServiceHandle<UserService>,
}

// 部署用户服务函数
async fn deploy_user_service(context: &KurtosisContext) -> Result<ServiceHandle<UserService>, KurtosisError> {
    let config = UserServiceConfig {
        db_url: "postgres://user:pass@db:5432".to_string(),
        cache_size: 1024,
    };
    
    let service = UserService::new(
        PortSpec::http(8080),
        config
    );
    
    context.deploy_service(service).await
}

#[tokio::main]
async fn main() -> Result<(), KurtosisError> {
    // 初始化Kurtosis上下文
    let context = KurtosisContext::new()?;
    
    // 部署用户服务
    let user_service = deploy_user_service(&context).await?;
    
    // 部署API服务
    let api_service = ApiService::new(
        PortSpec::http(8000),
        user_service
    );
    
    let api_handle = context.deploy_service(api_service).await?;
    
    println!("API服务已部署,访问地址: {}", api_handle.endpoint("http_port")?);
    
    // 示例:服务发现
    let services = context.discover_services().await?;
    println!("当前运行的服务数量: {}", services.len());
    
    // 示例:弹性伸缩
    api_handle.scale(3).await?;
    println!("API服务已扩展到3个副本");
    
    Ok(())
}

最佳实践

  1. 服务隔离:每个微服务应有明确的边界和职责
  2. 配置管理:使用SDK提供的配置管理功能而非硬编码
  3. 健康检查:为每个服务实现健康检查端点
  4. 日志聚合:集成分布式日志收集系统
  5. 监控:利用kurtosis-sdk的监控API暴露指标

故障排除

常见问题:

  • 服务启动失败:检查端口冲突和资源配置
  • 服务发现不可用:验证网络配置和服务注册
  • 伸缩操作阻塞:检查资源配额和依赖关系

调试方法:

// 获取服务日志
let logs = handle.logs().await?;
println!("Service logs: {}", logs);

// 检查服务状态
let status = handle.status().await?;
println!("Service status: {:?}", status);
回到顶部