
⏰ 🔥 Un proxy TCP per simulare condizioni di rete e di sistema per test di caos e resilienza
Toxiproxy è un framework per simulare condizioni di rete. È stato creato specificamente per funzionare in ambienti di testing, CI e sviluppo, supportando manipolazioni deterministiche delle connessioni, ma con supporto per il caos randomizzato e la personalizzazione. Toxiproxy è lo strumento che ti serve per dimostrare con i test che la tua applicazione non ha punti di errore singoli. Lo abbiamo utilizzato con successo in tutti gli ambienti di sviluppo e test di Shopify dal ottobre 2014. Vedi il nostro [post sul blog][blog] sulla resilienza per maggiori informazioni.
L'utilizzo di Toxiproxy consiste in due parti. Un proxy TCP scritto in Go (ciò che questo repository contiene) e un client che comunica con il proxy via HTTP. Devi configurare la tua applicazione in modo che tutte le connessioni di test passino attraverso Toxiproxy e quindi poter manipolare la loro salute via HTTP. Vedi Utilizzo sotto per come impostare il tuo progetto.
Ad esempio, per aggiungere 1000ms di latenza alla risposta di MySQL dal client Ruby:```ruby Toxiproxy[:mysql_master].downstream(:latency, latency: 1000).apply do Shop.first # this takes at least 1s end
Per fermare tutte le istanze Redis:```ruby
Toxiproxy[/redis/].down do
Shop.first # this will throw an exception
end
While the examples in this README are currently in Ruby, there's nothing stopping you from creating a client in any other language (see Clients).
The existing ones we found didn't provide the kind of dynamic API we needed for
integration and unit testing. Linux tools like nc and so on are not
cross-platform and require root, which makes them problematic in test,
development and CI environments.
Let's walk through an example with a Rails application. Note that Toxiproxy is in no way tied to Ruby, it's just been our first use case. You can see the full example at sirupsen/toxiproxy-rails-example. To get started right away, jump down to Usage.
For our popular blog, for some reason we're storing the tags for our posts in
Redis and the posts themselves in MySQL. We might have a Post class that
includes some methods to manipulate tags in a Redis set:```ruby
class Post < ActiveRecord::Base
def tags TagRedis.smembers(tag_key) end
def add_tag(tag) TagRedis.sadd(tag_key, tag) end
def remove_tag(tag) TagRedis.srem(tag_key, tag) end
def tag_key "post:tags:#{self.id}" end end
Abbiamo deciso che generare un errore durante la scrittura nel data store dei tag
(aggiunta/rimozione) è accettabile. Tuttavia, se il data store dei tag non è disponibile, dovremmo
essere in grado di vedere il post senza tag. Potremmo semplicemente catturare
l'eccezione `Redis::CannotConnectError` attorno alla chiamata Redis `SMEMBERS` nel metodo `tags`.
Usiamo Toxiproxy per testarlo.
Dato che abbiamo già installato Toxiproxy ed è in esecuzione sulla nostra macchina, possiamo
passare al punto 2. Qui dobbiamo assicurarci che Toxiproxy abbia una mappatura per
i tag Redis. In `config/boot.rb` (prima che venga effettuata qualsiasi connessione) aggiungiamo:```ruby
require 'toxiproxy'
Toxiproxy.populate([
{
name: "toxiproxy_test_redis_tags",
listen: "127.0.0.1:22222",
upstream: "127.0.0.1:6379"
}
])
Poi in config/environments/test.rb impostiamo TagRedis come client Redis
che si connette a Redis tramite Toxiproxy aggiungendo questa riga:```ruby
TagRedis = Redis.new(port: 22222)
Tutte le chiamate nell'ambiente di test ora passano attraverso Toxiproxy. Questo significa che possiamo
aggiungere un test unitario in cui simuliamo un guasto:```ruby
test "should return empty array when tag redis is down when listing tags" do
@post.add_tag "mammals"
# Take down all Redises in Toxiproxy
Toxiproxy[/redis/].down do
assert_equal [], @post.tags
end
end
Il test fallisce con Redis::CannotConnectError. Perfetto! Toxiproxy ha messo giù
Redis con successo per la durata della chiusura. Sistemiamo il metodo tags
per renderlo resiliente:```ruby
def tags
TagRedis.smembers(tag_key)
rescue Redis::CannotConnectError
[]
end
I test passano! Ora abbiamo un test unitario che dimostra che il recupero dei tag quando Redis
è giù restituisce un array vuoto, invece di lanciare un'eccezione. Per una
copertura completa dovresti anche scrivere un test di integrazione che includa il recupero dell'intera
pagina del post del blog quando Redis è giù.
L'applicazione di esempio completa è disponibile su
[sirupsen/toxiproxy-rails-example](https://github.com/sirupsen/toxiproxy-rails-example).
## Utilizzo
Configurare un progetto per usare Toxiproxy consiste in tre passaggi:
1. Installare Toxiproxy
2. Popolare Toxiproxy
3. Usare Toxiproxy
### 1. Installare Toxiproxy
**Linux**
Vedi [`Releases`](https://github.com/Shopify/toxiproxy/releases) per gli ultimi
binari e pacchetti di sistema per la tua architettura.
**Ubuntu**```bash
$ wget -O toxiproxy-2.1.4.deb https://github.com/Shopify/toxiproxy/releases/download/v2.1.4/toxiproxy_2.1.4_amd64.deb
$ sudo dpkg -i toxiproxy-2.1.4.deb
$ sudo service toxiproxy start
OS X
Con Homebrew:```bash $ brew tap shopify/shopify $ brew install toxiproxy
Oppure con [MacPorts](https://www.macports.org/):```bash
$ port install toxiproxy
Windows