
⏰ 🔥 وكيل TCP لمحاكاة ظروف الشبكة والنظام لاختبار الفوضى والمرونة
Toxiproxy هو إطار عمل لمحاكاة ظروف الشبكة. صُمم خصيصًا للعمل في بيئات الاختبار والتكامل المستمر والتطوير، ويدعم التلاعب الحتمي بالاتصالات، مع دعم الفوضى العشوائية والتخصيص. Toxiproxy هي الأداة التي تحتاجها لإثبات بالاختبارات أن تطبيقك لا يحتوي على نقاط فشل فردية. لقد استخدمناها بنجاح في جميع بيئات التطوير والاختبار في Shopify منذ أكتوبر 2014. راجع [منشور مدونتنا][blog] حول المرونة للحصول على مزيد من المعلومات.
يتكون استخدام Toxiproxy من جزأين. وكيل TCP مكتوب بلغة Go (وهو ما يحتويه هذا المستودع) وعميل يتواصل مع الوكيل عبر HTTP. يمكنك تهيئة تطبيقك لتوجيه جميع اتصالات الاختبار عبر Toxiproxy ثم التلاعب بصحتها عبر HTTP. راجع الاستخدام أدناه لمعرفة كيفية إعداد مشروعك.
على سبيل المثال، لإضافة 1000 مللي ثانية من زمن الاستجابة إلى استجابة MySQL من عميل Ruby:
Toxiproxy[:mysql_master].downstream(:latency, latency: 1000).apply do
Shop.first # this takes at least 1s
end
لإيقاف جميع نسخ Redis:
Toxiproxy[/redis/].down do
Shop.first # this will throw an exception
end
بينما الأمثلة في هذا README مكتوبة حاليًا بلغة Ruby، لا شيء يمنعك من إنشاء عميل بأي لغة أخرى (انظر العملاء).
لم توفّر الأدوات الموجودة التي وجدناها نوع واجهة API الديناميكية التي احتجناها
لاختبار التكامل والاختبارات الوحدوية. أدوات Linux مثل nc وما شابهها ليست
متعددة المنصات وتتطلب صلاحيات الجذر، مما يجعلها إشكالية في بيئات الاختبار
والتطوير وCI.
لنستعرض مثالًا مع تطبيق Rails. لاحظ أن Toxiproxy غير مرتبط بلغة Ruby بأي شكل، بل كان مجرد حالة الاستخدام الأولى لدينا. يمكنك الاطلاع على المثال الكامل في sirupsen/toxiproxy-rails-example. للبدء فورًا، انتقل إلى الاستخدام.
لمدونتنا الشهيرة، لسبب ما نخزّن الوسوم الخاصة بمقالاتنا في
Redis والمقالات نفسها في MySQL. قد يكون لدينا فئة Post تتضمن
بعض الطرق للتعامل مع الوسوم في مجموعة Redis:
class Post < ActiveRecord::Base
# Return an Array of all the tags.
def tags
TagRedis.smembers(tag_key)
end
# Add a tag to the post.
def add_tag(tag)
TagRedis.sadd(tag_key, tag)
end
# Remove a tag from the post.
def remove_tag(tag)
TagRedis.srem(tag_key, tag)
end
# Return the key in Redis for the set of tags for the post.
def tag_key
"post:tags:#{self.id}"
end
end
قررنا أن إظهار خطأ أثناء الكتابة إلى مخزن بيانات الوسوم (الإضافة/الإزالة) أمر مقبول. ومع ذلك، إذا كان مخزن بيانات الوسوم معطلاً، يجب أن نتمكن من رؤية المنشور بدون وسوم. يمكننا ببساطة اعتراض Redis::CannotConnectError حول استدعاء Redis SMEMBERS في طريقة tags. لنستخدم Toxiproxy لاختبار ذلك.
بما أننا قمنا بالفعل بتثبيت Toxiproxy وهو يعمل على جهازنا، يمكننا تخطي الخطوة 2. هنا نحتاج إلى التأكد من أن Toxiproxy لديه تعيين لوسوم Redis. إلى config/boot.rb (قبل إجراء أي اتصال) نضيف:
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 بإضافة هذا السطر:
TagRedis = Redis.new(port: 22222)
تمر جميع الاستدعاءات في بيئة الاختبار الآن عبر Toxiproxy. وهذا يعني أنه يمكننا إضافة اختبار وحدة نحاكي فيه حدوث فشل:
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 لتكون مرنة:
def tags
TagRedis.smembers(tag_key)
rescue Redis::CannotConnectError
[]
end
تنجح الاختبارات! لدينا الآن اختبار وحدة يثبت أن جلب الوسوم عندما يكون Redis معطلاً يعيد مصفوفة فارغة، بدلاً من إطلاق استثناء. للحصول على تغطية كاملة، يجب عليك أيضاً كتابة اختبار تكامل يغلّف جلب صفحة منشور المدونة بأكملها عندما يكون Redis معطلاً.
التطبيق المثالي الكامل موجود في sirupsen/toxiproxy-rails-example.
تكوين مشروع لاستخدام Toxiproxy يتكون من ثلاث خطوات:
Linux
راجع Releases للحصول على أحدث
الملفات الثنائية وحزم النظام الخاصة بمعماريتك.
Ubuntu
$ wget -O toxiproxy-2.13.0.deb https://github.com/Shopify/toxiproxy/releases/download/v2.13.0/toxiproxy_2.13.0_linux_amd64.deb
$ sudo dpkg -i toxiproxy-2.13.0.deb
$ sudo service toxiproxy start
OS X
باستخدام Homebrew:
$ brew tap shopify/shopify
$ brew install toxiproxy
أو باستخدام MacPorts:
$ port install toxiproxy
Windows
يتوفر Toxiproxy لنظام Windows للتنزيل على https://github.com/Shopify/toxiproxy/releases/latest/download/toxiproxy-server-windows-amd64.exe، مع واجهة سطر الأوامر (CLI) المطابقة على https://github.com/Shopify/toxiproxy/releases/latest/download/toxiproxy-cli-windows-amd64.exe
Docker
يتوفر Toxiproxy على سجل حاويات Github.
الإصدارات القديمة <= 2.1.4 متوفرة على Docker Hub.
$ docker pull ghcr.io/shopify/toxiproxy
$ docker run --rm -it ghcr.io/shopify/toxiproxy