| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Release a murder of crows upon your enemies.
Crows is a distributed load and stress testing runner. The tests can be written in any language that can compile to WASM given the bindings for the library are available. At the moment the bindings are available only for Rust, but once the ABIs are stable it should be relatively straightforward to add more languages.
A sample scenario written in Rust looks like this:
#[config]
fn config() -> ExecutorConfig {
let config = ConstantArrivalRateConfig {
duration: Duration::from_secs(5),
rate: 10,
allocated_vus: 10,
..Default::default()
};
ExecutorConfig::ConstantArrivalRate(config)
}
#[export_name = "scenario"]
pub fn scenario() {
http_request(
"https://google.com".into(), GET, HashMap::new(), "".into(),
);
}
It will send 10 requests per second to google.com. For information on how to compile and run it please go to the Usage section
This project is at a "minimal working setup" stage. It has solid foundation as I put a lot of thought into figuring out the best way to implement it, but there are a lot of details that are missing, like metrics support, checks, most of the executors etc.
What you should expect then? Most of the basic stuff works, but it's not been thorouhly tested nor benchmarked. Error messages may make no sense or may not even reach the CLI if they happen on the server side. Use if you're curious and/or you would like to contribute, but it's probably not the best idea to use it for anything important or if you value your time. I will update the README once I feel the project is stable enough and feature complete enough for a usable version.
There are a lot of tools for stress testing available on the market. Why have I decided to write Crows then? A few reasons:
Crows is not production ready, so it misses some of the features, but my personal high level wishlist is:
At the moment you can install the crows only through the cargo command:
cargo install crows
The simplest way to use Crows is to use the local mode. After you obtain the crows binary you can run a scenario compiled to WebAssembly with a single command:
crows run scenario.wasm
In order to create a scenarios you have to generate a Rust appliction with:
cargo new crows-sample
Then you need to set the crate type and add the crows-bindings dependency:
[lib]
crate-type = ["cdylib"]
[dependencies]
crows-bindings = "0.3"then add your scenario in src/lib.rs:
use crows_bindings::{
config, http_request, ConstantArrivalRateConfig, ExecutorConfig, HTTPMethod::*,
};
use std::time::Duration;
#[config]
fn config() -> ExecutorConfig {
let config = ConstantArrivalRateConfig {
duration: Duration::from_secs(5),
rate: 10,
..Default::default()
};
ExecutorConfig::ConstantArrivalRate(config)
}
#[export_name = "scenario"]
pub fn scenario() {
println!("Send request to https://google.com/");
http_request(
"https://google.com".to_string(), GET, Default::default(), "".to_string(),
);
}This scenario will keep sending 10 requests per second to https://google.com for 5 seconds. Just please maybe use another URL if you don't want to get blocked by Google.
Now you can compile the scenario with:
cargo build --release --target wasm32-wasi
and run with:
crows run target/wasm32-wasi/release/crows_sample.wasm
In a distributed mode you need to start a coordinator and at least one worker. You interact with the coordinator using the CLI.
cargo install crows-coordinator cargo install crows-worker
First you start the coordinator:
crows-coordinator
and then at least one worker:
WORKER_NAME=worker-1 crows-worker
Now you can upload and run a scenario:
crows upload --name test --path scenario.wasm crows start --name test --workers-number 1
I plan to prepare a more thorough description with diagrams and stuff, so in here I just wanted to give a brief summary.
A high level overview is as follows:
A coordinator is a single point of failure, but in the case of stress and load testing I think it's a sensible trade-off. On the upside this kind of architecture is extremely simple and with persistance layer it might be possible to tolerate coordinator crashes. In the future I'm open to making the coordinator distributed, but I don't think it's a pressing issue. Most of the issues I can identify with a single point of contact are not very problematic:
On top of that I really want to avoid the situation where every node can potentially be either a coordinator or a worker, cause I think it would complicate the project quite a lot without that many advantages.
Connections between components are plain TCPSocket connections with messages being lenght delimited JSON messages (ie. each message starts with 4 bytes describing the message length and then the message itself). The messages are abstracted with a custom RPC system that allows two way communication with either side initiating a message. In other words both sides can send a request and receive a response. One of the things that was really important for me was not having a requirement to expose the network address of a worker, cause this drastically simplifies server setup - it can be literally any machine or a virtual machine that connect to the coordinator. Even your laptop behind a NAT.
In the future I think I might change the serialization format to something like FlatBuffers, so it's easier to work with different versions, but for now JSON is enough and its simplicity makes development easier.
Worker is one of the most interesting parts of the project, in my humble opinion. A workers runs on top of a Tokio asynchronous runtime. All of the scenarios are executed in the context of the async runtime, thus even though the scenarios are written like you would normally write synchronous code, they will be executed in an asynchronous wait under the hood.
When a scenario is being executed a WASM runtime, using Wasmtime, is created. All the IO operations are done on the host side and thus WASM modules only call the host defined functions. For example in order to make an HTTP request:
Objects shared between the host and the WASM module are serialized and deserialized using JSON.
WASM modules are compiled as WASI enabled modules, which means it's possible to support common I/O operations like printing to STDOUT or reading files. At the moment only the former is supported and anything printed to STDOUT or STDERR will be passed to the coordinator and then potentially to the client. In the future I would also like to support reading files and allowing to distribute files between workers.
Executors define how scenarios are being executed. They define how and when to allocated new WASM instances and when to run iterations. At the moment only one executor is available constant arrival rate. If you want to see some other examples of possible executors take a look at (executors available in the K6 project)[https://k6.io/docs/using-k6/scenarios/executors/] (which is a great tool, which I've successfully used in the past, btw. kudos to the K6 team!).
I don't have a very precise plan on where I want Crows to go, but some loose thoughts on the stuff I'd like to work on if I have time:
While working on this project I have received support on GitHub Sponsors by the following people. Thank you for all the support!
Crows is licensed under AGPLv3 license.
Before accepting contributions I would like contributors to sign a CLA. I know it may be seen as hostile to the OSS movement, especially in the light license changes of projects like Terraform or Redis. I don't plan any moves like that, but I'm also a single person without any budget and with responsibilities towards my family, so I would like to leave myself some options. The most probable scenario where I might need a CLA is if I want also sell a commercial license for companies that don't want to to use an AGPLv3 tool for any reason or to start a hosted paid version of the tool where you can register and run your scenarios if you don't want to host the tool yourself. Both things are equally unlikely at the moment, but you never know.
| Back | FazBrowse Home | New Git URL |