Code Monkey home page Code Monkey logo

rhino's Introduction

Rhino: Dockerized Load and Performance Testing for Web Services

Rhino is a lightweight annotation-based JUnit-style load and performance testing framework tailored for testing web services which consists of the Rhino Java SDK as well as a collection of libraries and tools which enable developers to develop load and performance tests very fast. The Rhino can be added as library dependency into your project or the Rhino Maven archetype can be used to create a new maven project. The deployable artifact will be a Docker container which can be run on container orchestration platforms like Mesos, Kubernetes, AWS ECS, and so on.

1.5.0: Grafana/InfluxDB Integration is included!

With Influx DB and Grafana Integration, you can also monitor the current load testing and watch how services under test behaves under certain load pattern.
Rhino's philosophy is:

  • one repository for project's source code as well as Unit, Integration, Load and Performance Tests.
  • to speed up load and performance test development,
  • to afford a debuggable test framework written in Java, so that you can go through the breakpoints while investigating problems in your load testing code,
  • to provide a Cloud-native load testing environment, that is elastic, scalable, covering region and environment- aware load scenarios,
  • to enable the integration with the existing code, e.g your integration test frameworks to make them reusable in your load and performance test,
  • to provide an intuitive framework so that the engineers do not need to re-learn the language, or the framework every time they need to write new load tests.

Considering all these aspects, we began with Project Rhino in 2018 and it is available as F/OSS with Apache 2.0 License, now.

How to use?

Add maven dependency into your project:

<dependency>
  <groupId>io.ryos.rhino</groupId>
  <artifactId>rhino-core</artifactId>
  <version>2.2.1</version>
</dependency>

For more information about project setup: Getting Started with Rhino Load Testing.

How do the load tests look like?

Simulation is a test entity which will be executed and generates load according to the implementation provided in the test classes against the instance under test, e.g a web service. So as to create a new simulation entity, create a plain Java object with @Simulation annotation:

@Simulation(name = "Example Simulation")
public class PerformanceTestingExample {
}

The simulation above does nothing unless we add DSL methods into it. DSL methods are
annotated with @Dsl annotation which contain encompass DSL method calls and returns a LoadDsl instance. A simulation might have multiple DSL methods defined which will be materialized into reactive components to build a load generation pipeline:

@Simulation(name = "Server-Status Simulation")
public class RhinoEntity {

  @Provider(factory = UUIDProvider.class)
  private UUIDProvider uuidProvider;

  @Dsl(name = "Health")
  public DslBuilder performHealth() {
    return dsl()
        .run(http("Health API Call")
            .header(c -> from(X_REQUEST_ID, "Rhino-" + UUID.randomUUID().toString()))
            .endpoint(TARGET)
            .get()
            .saveTo("result"));
  }
}

The name of the simulation is important. In a performance testing project, it is very likely that you will have multiple simulations. Rhino does know which simulation is to be run from the simulation name provided, so the names must be unique.

A simple Rhino application would look like:

import io.ryos.rhino.sdk.Simulation;

public class Rhino {

    public static void main(String ... args) {
        Simulation.create(PROPS, SIM_NAME).start();
    }
}

How to run?

If you choose to use the Rhino archetype, the maven project is configured to create a Docker container:

$ mvn -e clean install
$ docker run -t yourproject:latest

Questions/Contributions?

Feel free to fork the project and make contributions in terms of Pull Requests. For bigger proposals, architectural discussions and bug reports, use the Github's issue tracker.

Sponsors

rhino's People

Contributors

dependabot[bot] avatar gitter-badger avatar h-marvin avatar luxmeter avatar reevik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rhino's Issues

Rhino Management UI.

The RMU features consist of:

  • Scheduling load tests,
  • Management of load test projects,
  • Management of load patterns, that is to be applied to test instances,
  • Management of test users,
  • Monitoring and archiving load test scenarios,
  • Creating and managing load test notifications,
  • LDAP integration.

Non-reporting HttpSpec

Non-reporting HttpSpec. In some cases, like in preparation step, the DSL is to be muted so that the framework is not be able to report any measurement.

Vault support for User Credentials

As of 1.0 Rhino support only classpath files for user credentials. HashiCorp's Vault is broadly used secure server to manage credentials in Enterprises.

InfluxDB integration over streaming

The experimental implementation of InfluxDB integration is done via over-HTTP by using InfluxDB Java library, that is not reliable but may exist as an option in the framework for testing. For production use cases, rhino should support streaming services integration between load generators and timeseries database.

Unhandled exceptions stop the simulation.

The main flux needs to implement onErrorResume by returning an empty Mono. In error cases, the framework must report the error as well as the error rate in its output.

Distributed load orchestrator

The load patterns as in ramp-up phase, or throughout the load testing run needs to be synced by a central orchestration component, that is DLO, distributed load orchestrator.

Input validation improvements

Add tests for input validations including

  • pinging the influx db to verify the influx db configurations.
  • pinging the Grafana.

Load DSL

Load DSL is to describe the load test in reactive approach. The goal in release 1.1.0 is to provide a simple (I mean, really simple one) Http DSL.

Reactive runner with HTTP load specs.

As of 1.1.0 simulation metrics is collected by instances of Measurement type, that is the object which records the execution time in scenario methods. The concept of measurement is to provide developers with a handy toolset with which the load test developers can set the measurement points in their scenario methods on their own. The concept works very fine with variety of load testing scenarios. However, whenever developers need to write load test for web services over HTTP, the salt request time from the time point once the request is first fired without taking the queue time into account is to be reported.

Moreover, the blocking fashion of scenario implementation comes with a well-known cost, that is inefficiency due to thread contention, starving threads, etc. Furthermore, if the scenario implementation is blocking one, the worker threads which run scenarios will also get blocked, so the entire load testing framework get halted.

From all drawbacks of blocking architecture listed above, a new architecture is to be initiated taking reactive principles into consideration, i.e pull vs push.

Proposal

  • The scenarios is not to be run by single threads assigned from a threadpool, instead the scenarios is to return a specification describing how to run the load test. The framework itself will then materialise the specification provided. Materialised specs will subscribe themselves in load publishers.
  • Blocking test execution strategy must exist along with the reactive runner. The developers are subject to select the runner strategy by providing @Runner(clazz=Runner Implementation) annotation.
  • Rhino affords its own non-blocking HTTP client based on Reactor-Netty.
  • In addition to metrics collected by Rhino's Measurement facility, we still need to measure the actual turn-around time transparent to the developers.
@Runner(clazz=ReactiveRunner.class)
public class ReactiveSimulation {

}

The challenge will be to subscribe the HTTP requests with the Flux load generator in reactive way. To cope with this, the scenario methods should return a specification of load generation, not the implementation itself. The framework will then materialize the specification into reactive implementation:

@Simulation
@Runner(clazz=ReactiveRunner.class)
public class ReactiveSimulation {
    @TestSpec
    public Spec loadSpec(Measurement measurement) {
        return new HttpSpec
            .get()
            .queryParams()
            .headers()
            .toSpec();
    }
}

Load DSL - waitUntil - spec for monitoring the API result

Async processing is to be monitored through monitoring APIs, e.g:

waitUntil(session -> 
    http("monitor")
        .target("/monitor")
        .get()
        .saveTo("result"),
        result -> result.getStatusCode() == 200, 
        1 mins, 10 retries)

The measurement is to be done from the first monitoring request till the last attempt.

Operation signature is as follows:

waitUntil(Function<Spec, UserSession> specFunction ,
        Function<HttpResult, Boolean> specFunction,
        Duration delay, // Delay between two attempts
        Integer maxRetry // max attempt
)

Remove all Jersey Client dependencies.

The framework still uses Jersey Client to make Http requests for its internal workflows. Replace the Jersey client with async HTTP client in Auth workflows.

Grafana Integration

  • Rhino is to be able to create dashboard with the simulation id given right before every load test load in case of Grafana integration is enabled.
  • Grafana integration is configurable in rhino.properties.

Basic Auth

The framework needs to support Basic Auth besides Access Token/OAuth.

User source as file.

1.0.0 supports CSV user sources, with classpath:// prefix.
"file:///" is to be added to define paths to the user source from outside of the classpath.

Simulation log rotator

Instead of writing out to the sim log, use a logger like log4j to facilitate the rotation feature.

Distinct user provider

The load testing user which is streamed through the reactive pipeline and the user injected by provider, are to be different so that the multi-user tests can be carried out. As a matter of fact that the user repository is the same one as the user provider, it is likely that the same user is injected into the injection point is currently active in the pipeline in which case that multi user testing cannot be run.

Load Ramp-up.

Ramp-up load before the load generator reaches its maximum load generation capacity.

The ramp-up can be configured by annotation: @RampUp(injectUser=10, every=10)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.