
⏰ 🔥 ネットワークとシステムの状態をシミュレートしてカオスおよびレジリエンシーテストを行うためのTCPプロキシ
Toxiproxy はネットワーク状態をシミュレートするためのフレームワークです。テスト、CI、開発環境で動作するよう特別に作られており、接続への決定的な改ざんをサポートしつつ、ランダムなカオスとカスタマイズにも対応しています。Toxiproxy は、アプリケーションに単一障害点が存在しないことをテストで証明するために必要なツールです。 2014年10月以降、Shopify のすべての開発環境およびテスト環境で使用に成功しています。詳細は、回復性に関する[ブログ記事][blog]を参照してください。
Toxiproxy の利用は2つの部分から構成されます。Go で書かれた TCP プロキシ(このリポジトリに含まれるもの)と、HTTP 経由でプロキシと通信するクライアントです。すべてのテスト接続が Toxiproxy を通過するようにアプリケーションを設定し、HTTP 経由でその状態を操作できます。プロジェクトの設定方法については、以下の使用法を参照してください。
たとえば、Ruby クライアントから MySQL の応答に 1000ms の遅延を追加するには:```ruby Toxiproxy[:mysql_master].downstream(:latency, latency: 1000).apply do Shop.first # this takes at least 1s end
すべての Redis インスタンスを停止するには:```ruby
Toxiproxy[/redis/].down do
Shop.first # this will throw an exception
end
このREADMEの例は現在Rubyで書かれていますが、他の言語でクライアントを作成することを妨げるものは何もありません(Clientsを参照)。
既存のツールは、私たちが必要とする統合テストや単体テストのための動的APIを提供してくれませんでした。nc などのLinuxツールはクロスプラットフォームではなく、root権限が必要なため、テスト・開発・CI環境では問題になります。
Railsアプリケーションを使った例を見ていきましょう。ToxiproxyはRubyにまったく依存しているわけではなく、単に最初のユースケースだったというだけです。完全な例は sirupsen/toxiproxy-rails-example で確認できます。すぐに始めたい場合は、使い方 にジャンプしてください。
私たちの人気ブログでは、何らかの理由で投稿のタグをRedisに、投稿自体をMySQLに保存しています。Post クラスには、Redisセット 内のタグを操作するメソッドが含まれているかもしれません。```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
タグデータストアへの書き込み(追加/削除)中にエラーが発生しても問題ないと判断しました。ただし、タグデータストアがダウンしている場合は、タグなしで投稿を表示できるようにする必要があります。`tags` メソッド内の `SMEMBERS` Redis 呼び出しを `Redis::CannotConnectError` で rescue するだけで済みます。これをテストするために Toxiproxy を使いましょう。
Toxiproxy はすでにインストール済みで、マシン上で実行されているので、ステップ 2 に進むことができます。ここで、Toxiproxy が Redis タグのマッピングを持っていることを確認する必要があります。`config/boot.rb` に(接続が行われる前に)追加します:```ruby
require 'toxiproxy'
Toxiproxy.populate([
{
name: "toxiproxy_test_redis_tags",
listen: "127.0.0.1:22222",
upstream: "127.0.0.1:6379"
}
])
次に、config/environments/test.rb 内で、TagRedis が Toxiproxy を介して Redis に接続する Redis クライアントになるように、
次の行を追加します。```ruby
TagRedis = Redis.new(port: 22222)
テスト環境内のすべての呼び出しは現在、Toxiproxy を経由します。つまり、障害をシミュレートするユニットテストを追加できるということです。```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
テストは Redis::CannotConnectError で失敗します。完璧です!Toxiproxy はクロージャの間、Redis を正常に停止させました。tags メソッドを耐障害性を持つように修正しましょう:```ruby
def tags
TagRedis.smembers(tag_key)
rescue Redis::CannotConnectError
[]
end
テストはパスしました!これで、Redis がダウンしているときにタグを取得すると、例外を投げる代わりに空の配列を返すことを証明するユニットテストができました。完全なカバレッジのためには、Redis がダウンしているときにブログ投稿ページ全体の取得をラップする統合テストも書くべきです。
完全なサンプルアプリケーションは、
[sirupsen/toxiproxy-rails-example](https://github.com/sirupsen/toxiproxy-rails-example) にあります。
## Usage
Toxiproxy を使用するプロジェクトの設定は、次の3つのステップで構成されます。
1. Toxiproxy のインストール
2. Toxiproxy へのプロキシ登録
3. Toxiproxy の使用
### 1. Toxiproxy のインストール
**Linux**
最新のバイナリとお使いのアーキテクチャ向けシステムパッケージについては、[`Releases`](https://github.com/Shopify/toxiproxy/releases) を参照してください。
**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
Homebrew を使用する場合:```bash $ brew tap shopify/shopify $ brew install toxiproxy
または [MacPorts](https://www.macports.org/):```bash
$ port install toxiproxy
Windows
Windows版Toxiproxyは、https://github.com/Shopify/toxiproxy/releases/download/v2.1.4/toxiproxy-server-windows-amd64.exe からダウンロードできます。
Docker
ToxiproxyはGithubコンテナレジストリから入手できます。
旧バージョン(<= 2.1.4)はDocker Hubから入手できます。```bash
$ docker pull ghcr.io/shopify/toxiproxy
$ docker run --rm -it ghcr.io/shopify/toxiproxy
Toxiproxy を他のコンテナではなくホストから使用する場合、`--net=host` でホストネットワーキングを有効にしてください。```shell
$ docker run --rm --entrypoint="/toxiproxy-cli" -it ghcr.io/shopify/toxiproxy list
Goがインストールされている場合、makeファイルを使用してソースからToxiproxyをビルドできます:```bash $ make build $ ./toxiproxy-server
#### Upgrading from Toxiproxy 1.x
#### Toxiproxy 1.x からのアップグレード
Toxiproxy 2.0 では、バージョン 1.x と互換性がなくなる API の変更がいくつか行われました。
Toxiproxy サーバーのバージョン 2.x を使用するには、クライアントライブラリが同じバージョンをサポートしていることを確認する必要があります。実行中の Toxiproxy のバージョンは、`/version` エンドポイントを確認することで確認できます。
具体的なライブラリの変更については、クライアントライブラリのドキュメントを参照してください。Toxiproxy サーバーの詳細な変更は、[CHANGELOG.md](https://github.com/shopify/toxiproxy/blob/main/CHANGELOG.md) に記載されています。
### 2. Populating Toxiproxy
### 2. Toxiproxy への投入
When your application boots, it needs to make sure that Toxiproxy knows which
endpoints to proxy where. The main parameters are: name, address for Toxiproxy
to **listen** on and the address of the upstream.
アプリケーションの起動時には、Toxiproxy がどのエンドポイントをどこにプロキシするかを把握している必要があります。主なパラメータは、名前、Toxiproxy が**リッスン**するアドレス、アップストリームのアドレスです。