
⏰ 🔥 وكيل TCP لمحاكاة ظروف الشبكة والنظام لاختبار الفوضى والمرونة
Toxiproxy هو إطار عمل لمحاكاة ظروف الشبكة. صُمم خصيصًا للعمل في بيئات الاختبار والتكامل المستمر (CI) والتطوير، ويدعم العبث الحتمي بالاتصالات، مع دعم للفوضى العشوائية والتخصيص. Toxiproxy هو الأداة التي تحتاجها لإثبات بالاختبارات أن تطبيقك لا يحتوي على نقاط فشل فردية. لقد استخدمناها بنجاح في جميع بيئات التطوير والاختبار في Shopify منذ أكتوبر 2014. اطّلع على [مقالة مدونتنا][blog] حول المرونة لمزيد من المعلومات.
يتكوّن استخدام Toxiproxy من جزأين: وكيل TCP مكتوب بلغة Go (وهو ما يحتويه هذا المستودع) وعميل يتواصل مع الوكيل عبر HTTP. يمكنك ضبط تطبيقك بحيث تمر جميع اتصالات الاختبار عبر Toxiproxy ثم تتحكم في حالتها الصحية عبر HTTP. اطّلع على الاستخدام أدناه لمعرفة كيفية إعداد مشروعك.
على سبيل المثال، لإضافة 1000ms من زمن الاستجابة إلى استجابة MySQL من عميل Ruby:```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، إلا أنه لا شيء يمنعك من إنشاء عميل بأي لغة أخرى (انظر العملاء).
الأدوات الحالية التي وجدناها لم توفر نوع واجهة برمجة التطبيقات الديناميكية التي احتجناها لاختبارات
التكامل والوحدات. أدوات لينكس مثل nc وغيرها ليست
متعددة المنصات وتتطلب صلاحيات root، مما يجعلها مشكلة في بيئات
الاختبار والتطوير والتكامل المستمر.
لنستعرض مثالًا مع تطبيق Rails. لاحظ أن Toxiproxy ليس مرتبطًا بـ Ruby بأي شكل، فهو فقط كان حالة الاستخدام الأولى لدينا. يمكنك رؤية المثال الكامل على sirupsen/toxiproxy-rails-example. لتبدأ فورًا، انتقل إلى الاستخدام.
في مدونتنا الشهيرة، ولسبب ما نُخزّن الوسوم لمشاركاتنا في
Redis والمنشورات نفسها في MySQL. قد يكون لدينا كلاس Post
يتضمّن بعض الطرق للتعامل مع الوسوم في 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
لقد قررنا أن الخطأ أثناء الكتابة إلى مخزن بيانات الوسوم
(إضافة/إزالة) مقبول. ومع ذلك، إذا كان مخزن بيانات الوسوم معطلاً، فيجب أن نتمكن
من رؤية المنشور بدون وسوم. يمكننا ببساطة التقاط
`Redis::CannotConnectError` حول استدعاء Redis الخاص بـ `SMEMBERS` في دالة
`tags`. دعنا نستخدم 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 ليكون عميل Redis
يتصل بـ Redis عبر Toxiproxy بإضافة هذا السطر:```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).
## الاستخدام
يتكوّن إعداد مشروع لاستخدام Toxiproxy من ثلاث خطوات:
1. تثبيت Toxiproxy
2. ملء Toxiproxy
3. استخدام Toxiproxy
### 1. تثبيت Toxiproxy
**لينكس**
انظر [`Releases`](https://github.com/Shopify/toxiproxy/releases) للحصول على أحدث الملفات الثنائية والحزم النظامية لمعمارية جهازك.
**أوبونتو**```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
ويندوز
يتوفر Toxiproxy لنظام ويندوز للتحميل على https://github.com/Shopify/toxiproxy/releases/download/v2.1.4/toxiproxy-server-windows-amd64.exe
دوكر
يتوفر 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 مثبتًا، يمكنك بناء Toxiproxy من المصدر باستخدام ملف make:```bash $ make build $ ./toxiproxy-server
#### الترقية من Toxiproxy 1.x