Rust网络测试工具toxiproxy_rust的使用:模拟网络延迟、故障和混沌测试的代理库

Rust网络测试工具toxiproxy_rust的使用:模拟网络延迟、故障和混沌测试的代理库

Toxiproxy - Rust客户端

Build Status

Rust客户端用于Toxiproxy。

使用

填充代理:

let proxies = TOXIPROXY.populate(vec![
  Proxy::new(
    "socket_service".into(),
    "localhost:2001".into(),
    "localhost:2000".into(),
  ),
  Proxy::new(
    "redis".into(),
    "localhost:6000".into(),
    "localhost:6379".into(),
  )
])?;

测试不可用的连接:

TOXIPROXY.find_and_reset_proxy("redis")?.with_down(|| {
  // 调用所需的服务...
})?;

测试有毒代理:

TOXIPROXY.find_and_reset_proxy("redis")?.with_latency("downstream".into(), 2000, 0, 1.0).apply(|| {
  // 调用所需的服务...
})?;

或者不使用安全的lambda(负责重置代理):

TOXIPROXY.find_proxy("redis")?.with_latency("downstream".into(), 2000, 0, 1.0)
// 调用所需的服务...

TOXIPROXY.find_proxy("redis")?.disable();
// 测试不可用性
TOXIPROXY.find_proxy("redis")?.enable();

支持的有毒代理:

  • 延迟
  • 下线
  • 带宽
  • 慢关闭
  • 超时
  • 切片器
  • 数据限制

使用自定义的Toxiproxy服务器地址:

let toxiclient: Client = toxiproxy_rust::Client::new("1.2.3.4:5678");

开发

测试:

$> cargo test -- --test-threads 1

完整示例代码

use toxiproxy_rust::Client;
use toxiproxy_rust::proxy::Proxy;
use redis::Commands;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建客户端连接
    let toxiclient: Client = toxiproxy_rust::Client::new("http://localhost:8474");
    
    // 创建代理配置
    let proxies = toxiclient.populate(vec![
        Proxy::new(
            "redis_proxy".into(),
            "localhost:6000".into(),
            "localhost:6379".into(),
        )
    ]).await?;
    
    // 测试延迟场景
    toxiclient.find_and_reset_proxy("redis_proxy")?
        .with_latency("downstream".into(), 2000, 0, 1.0)
        .apply(|| {
            // 连接Redis并测试延迟
            let client = redis::Client::open("redis://localhost:6000")?;
            let mut con = client.get_connection()?;
            let start = std::time::Instant::now();
            let _: () = con.set("test_key", "test_value")?;
            println!("操作耗时: {:?}", start.elapsed());
            Ok(())
        })?;
    
    // 测试连接断开场景
    toxiclient.find_and_reset_proxy("redis_proxy")?
        .with_down(|| {
            // 测试Redis连接失败的情况
            match redis::Client::open("redis://localhost:6000") {
                Ok(client) => {
                    if let Err(e) = client.get_connection() {
                        println!("连接失败,符合预期: {}", e);
                    }
                },
                Err(e) => println!("客户端创建失败: {}", e)
            }
            Ok(())
        })?;
    
    // 测试带宽限制
    toxiclient.find_and_reset_proxy("redis_proxy")?
        .with_bandwidth("downstream".into(), 100) // 100KB/s
        .apply(|| {
            // 测试数据传输速度
            let client = redis::Client::open("redis://localhost:6000")?;
            let mut con = client.get_connection()?;
            
            // 测试大数据传输
            let large_data = vec![0u8; 1024 * 1024]; // 1MB数据
            let start = std::time::Instant::now();
            let _: () = con.set("large_data", large_data)?;
            println!("1MB数据传输耗时: {:?}", start.elapsed());
            
            Ok(())
        })?;
    
    Ok(())
}

安装

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

cargo add toxiproxy_rust

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

toxiproxy_rust = "0.1.6"

1 回复

Rust网络测试工具toxiproxy_rust的使用指南

简介

toxiproxy_rust是Rust实现的Toxiproxy客户端库,允许开发者模拟各种网络条件进行测试。它是原始Toxiproxy(用Go编写)的Rust版本实现,专门用于测试网络服务在不可靠网络条件下的表现。

主要功能包括:

  • 模拟网络延迟
  • 注入网络故障
  • 进行混沌测试
  • 创建网络代理服务器
  • 动态修改网络条件

安装方法

在Cargo.toml中添加依赖:

[dependencies]
toxiproxy_rust = "0.3"
tokio = { version = "1", features = ["full"] }  # 需要tokio运行时
rand = "0.8"  # 混沌测试需要

完整示例代码

use toxiproxy_rust::{ToxiproxyClient, ToxicKind};
use std::time::Duration;
use tokio::time;
use rand::Rng;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. 创建Toxiproxy客户端
    let client = ToxiproxyClient::new("http://localhost:8474");
    
    // 2. 创建基础代理
    println!("创建基础代理...");
    let proxy = client.create_proxy(
        "example_proxy",
        "localhost:8080",
        "example.com:80"
    ).await?;
    
    // 3. 添加基本毒性
    println!("添加基础网络毒性...");
    // 添加200ms延迟,抖动50ms
    proxy.toxic()
        .latency("base_latency", 200, 50)
        .await?;
    
    // 添加5%丢包率
    proxy.toxic()
        .bandwidth("base_loss", "downstream", 5)
        .await?;
    
    // 4. 模拟复杂网络条件
    println!("模拟复杂网络条件...");
    proxy.toxic()
        .with_name("complex_network")
        .with_kind(ToxicKind::Latency {
            latency: 500,  // 500ms延迟
            jitter: 100,   // 100ms抖动
        })
        .with_attribute("toxicity", 0.6)  // 60%的请求受影响
        .with_stream("upstream")          // 只影响上游流量
        .create()
        .await?;
    
    // 5. 混沌测试演示
    println!("开始混沌测试(10轮)...");
    for i in 1..=10 {
        let mut rng = rand::thread_rng();
        
        // 随机延迟(100-800ms)
        let latency = rng.gen_range(100..800);
        let jitter = latency / 10;
        
        // 随机丢包率(0-15%)
        let loss = rng.gen_range(0..15);
        
        println!("轮次 {}: 延迟 {}ms, 丢包率 {}%", i, latency, loss);
        
        proxy.toxic()
            .latency("chaos_latency", latency, jitter)
            .await?;
            
        proxy.toxic()
            .bandwidth("chaos_loss", "downstream", loss)
            .await?;
            
        time::sleep(Duration::from_secs(3)).await;
    }
    
    // 6. 清理工作
    println!("清理测试环境...");
    proxy.reset().await?;  // 重置代理状态
    client.delete_proxy("example_proxy").await?;  // 删除代理
    
    println!("测试完成!");
    Ok(())
}

代码说明

  1. 初始化客户端:连接到本地运行的Toxiproxy服务器(默认端口8474)

  2. 创建代理:在本地8080端口创建代理,转发到example.com的80端口

  3. 基础毒性设置

    • 固定200ms延迟+50ms抖动
    • 5%的下游流量丢包
  4. 复杂网络条件

    • 500ms延迟+100ms抖动
    • 只影响60%的上游流量
  5. 混沌测试

    • 随机生成延迟(100-800ms)
    • 随机生成丢包率(0-15%)
    • 每3秒改变一次条件
    • 共运行10轮测试
  6. 清理阶段

    • 重置代理状态
    • 删除测试代理

运行准备

  1. 首先启动Toxiproxy服务器:
docker run -it --rm -p 8474:8474 -p 8000-9000:8000-9000 shopify/toxiproxy
  1. 运行示例程序:
cargo run

实际应用建议

  1. 将此工具集成到您的CI/CD流程中,自动化测试网络容错能力

  2. 针对微服务架构,可以创建多个代理同时测试服务间的交互

  3. 结合单元测试框架,编写断言验证系统在各种网络条件下的行为

  4. 测试完成后务必清理代理,避免影响后续测试

回到顶部