
⏰ 🔥 네트워크 및 시스템 상태를 시뮬레이션하여 카오스 및 복원력 테스트를 수행하는 TCP 프록시
Toxiproxy는 네트워크 상태를 시뮬레이션하기 위한 프레임워크입니다. 테스트, CI 및 개발 환경에서 작동하도록 특별히 만들어졌으며, 연결에 대한 결정적 변조를 지원하면서도 무작위 혼란과 사용자 지정도 지원합니다. Toxiproxy는 테스트를 통해 애플리케이션에 단일 실패 지점이 없음을 입증하는 데 필요한 도구입니다. 우리는 2014년 10월부터 Shopify의 모든 개발 및 테스트 환경에서 이를 성공적으로 사용해 왔습니다. 복원력에 대한 자세한 내용은 [블로그 게시물][blog]을 참조하세요.
Toxiproxy 사용은 두 부분으로 구성됩니다. 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를 제공하지 못했습니다. Linux 도구인 nc 등은 크로스 플랫폼을 지원하지 않고 root 권한이 필요하여 테스트, 개발, CI 환경에서 문제가 됩니다.
Rails 애플리케이션을 사용한 예제를 살펴보겠습니다. Toxiproxy는 결코 Ruby에 묶여 있지 않으며, 단지 우리의 첫 번째 사용 사례였을 뿐입니다. 전체 예제는 sirupsen/toxiproxy-rails-example에서 볼 수 있습니다. 바로 시작하려면 Usage로 내려가세요.
인기 있는 블로그에서 어떤 이유로 게시물의 태그를 Redis에 저장하고 게시물 자체는 MySQL에 저장한다고 가정해 봅시다. Redis set에서 태그를 조작하는 몇 가지 메서드를 포함하는 Post 클래스가 있을 수 있습니다.```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
태그 데이터 저장소에 쓰는 동안(추가/제거) 오류가 발생하는 것은 괜찮다고 결정했습니다.
그러나 태그 데이터 저장소가 다운된 경우에는
태그 없이 게시물을 볼 수 있어야 합니다. 간단히
`Redis::CannotConnectError`를 `tags` 메서드의 `SMEMBERS` Redis 호출 주변에서
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
The test fails with Redis::CannotConnectError. Perfect! Toxiproxy took down
the Redis successfully for the duration of the closure. Let's fix the tags
method to be resilient:```ruby
def tags
TagRedis.smembers(tag_key)
rescue Redis::CannotConnectError
[]
end
테스트가 통과합니다! 이제 Redis가 다운되었을 때 태그를 가져오면 예외를 던지는 대신 빈 배열을 반환한다는 것을 증명하는 단위 테스트가 생겼습니다. 전체 커버리지를 위해서는 Redis가 다운되었을 때 블로그 포스트 페이지 전체를 가져오는 것을 포함하는 통합 테스트도 작성해야 합니다.
전체 예제 애플리케이션은
[sirupsen/toxiproxy-rails-example](https://github.com/sirupsen/toxiproxy-rails-example)에 있습니다.
## 사용법
Toxiproxy를 사용하도록 프로젝트를 구성하는 것은 세 단계로 이루어집니다:
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
Toxiproxy for Windows는 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
#### Toxiproxy 1.x에서 업그레이드
Toxiproxy 2.0에서는 API에 여러 변경 사항이 적용되어 1.x 버전과 호환되지 않습니다.
Toxiproxy 서버 2.x 버전을 사용하려면 클라이언트 라이브러리가 동일한 버전을 지원하는지
확인해야 합니다. `/version` 엔드포인트를 확인하면 실행 중인 Toxiproxy 버전을
알 수 있습니다.
특정 라이브러리 변경 사항은 해당 클라이언트 라이브러리 문서를 참조하세요. Toxiproxy 서버의 자세한
변경 사항은 [CHANGELOG.md](https://github.com/shopify/toxiproxy/blob/main/CHANGELOG.md)에서 확인할 수 있습니다.
### 2. Toxiproxy 채우기
애플리케이션이 부팅될 때 Toxiproxy가 어떤 엔드포인트를 어디로 프록시할지 알 수 있도록
해야 합니다. 주요 매개변수는 이름, Toxiproxy가 **수신(listen)**할 주소, 그리고
업스트림의 주소입니다.