الأمان والأداء
اختبار الحمل والقياس المعياري
اختبار الحمل والقياس المعياري
اختبار الحمل يحاكي حركة المرور الحقيقية لتحديد اختناقات الأداء قبل أن تؤثر على المستخدمين. إنه ضروري للتخطيط للقدرة وضمان الموثوقية.
لماذا يهم اختبار الحمل
اختبار الحمل يساعدك على:
- تحديد نقاط الانهيار والقدرة القصوى
- العثور على تسريبات الذاكرة واستنزاف الموارد
- التحقق من تكوينات التوسع التلقائي
- إنشاء خطوط أساس للأداء
- منع الانقطاعات أثناء ارتفاع حركة المرور
متى تختبر: قبل الإصدارات الكبرى، بعد تغييرات البنية التحتية، عند توقع ارتفاع حركة المرور (حملات تسويقية، مبيعات)، ودوريًا للكشف عن التراجعات.
Artillery - اختبار الحمل الحديث
Artillery أداة قوية وسهلة الاستخدام لاختبار الحمل:
<!-- تثبيت Artillery -->
npm install -g artillery
<!-- اختبار سريع من سطر الأوامر -->
artillery quick --count 10 --num 100 https://example.com
<!-- إنشاء سيناريو اختبار (load-test.yml) -->
config:
target: 'https://api.example.com'
phases:
- duration: 60
arrivalRate: 5
name: 'الإحماء'
- duration: 300
arrivalRate: 20
name: 'حمل مستدام'
- duration: 60
arrivalRate: 50
name: 'اختبار الذروة'
scenarios:
- name: 'رحلة المستخدم'
flow:
- get:
url: '/api/products'
- think: 2
- post:
url: '/api/cart'
json:
product_id: 123
quantity: 1
- get:
url: '/api/checkout'
<!-- تشغيل الاختبار -->
artillery run load-test.yml
<!-- توليد تقرير HTML -->
artillery run --output report.json load-test.yml
artillery report report.json
npm install -g artillery
<!-- اختبار سريع من سطر الأوامر -->
artillery quick --count 10 --num 100 https://example.com
<!-- إنشاء سيناريو اختبار (load-test.yml) -->
config:
target: 'https://api.example.com'
phases:
- duration: 60
arrivalRate: 5
name: 'الإحماء'
- duration: 300
arrivalRate: 20
name: 'حمل مستدام'
- duration: 60
arrivalRate: 50
name: 'اختبار الذروة'
scenarios:
- name: 'رحلة المستخدم'
flow:
- get:
url: '/api/products'
- think: 2
- post:
url: '/api/cart'
json:
product_id: 123
quantity: 1
- get:
url: '/api/checkout'
<!-- تشغيل الاختبار -->
artillery run load-test.yml
<!-- توليد تقرير HTML -->
artillery run --output report.json load-test.yml
artillery report report.json
أفضل ممارسة: ابدأ بحمل منخفض وارفعه تدريجيًا. اختبر نقاط النهاية الفردية قبل رحلات المستخدم الكاملة. اختبر دائمًا على بيئة التجهيز، أبدًا على الإنتاج.
k6 - اختبار الأداء على نطاق واسع
k6 أداة اختبار حمل حديثة مبنية للتكامل مع CI/CD:
<!-- تثبيت k6 -->
brew install k6 # macOS
sudo apt install k6 # Ubuntu
<!-- إنشاء سكريبت اختبار (load-test.js) -->
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '30s', target: 20 },
{ duration: '1m30s', target: 100 },
{ duration: '30s', target: 0 },
],
thresholds: {
http_req_duration: ['p(95)<500'], // 95٪ من الطلبات أقل من 500ms
http_req_failed: ['rate<0.01'], // معدل الخطأ أقل من 1٪
},
};
export default function () {
const res = http.get('https://api.example.com/users');
check(res, {
'الحالة 200': (r) => r.status === 200,
'وقت الاستجابة جيد': (r) => r.timings.duration < 500,
});
sleep(1);
}
<!-- تشغيل الاختبار -->
k6 run load-test.js
<!-- تشغيل مع إخراج السحابة -->
k6 run --out cloud load-test.js
brew install k6 # macOS
sudo apt install k6 # Ubuntu
<!-- إنشاء سكريبت اختبار (load-test.js) -->
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '30s', target: 20 },
{ duration: '1m30s', target: 100 },
{ duration: '30s', target: 0 },
],
thresholds: {
http_req_duration: ['p(95)<500'], // 95٪ من الطلبات أقل من 500ms
http_req_failed: ['rate<0.01'], // معدل الخطأ أقل من 1٪
},
};
export default function () {
const res = http.get('https://api.example.com/users');
check(res, {
'الحالة 200': (r) => r.status === 200,
'وقت الاستجابة جيد': (r) => r.timings.duration < 500,
});
sleep(1);
}
<!-- تشغيل الاختبار -->
k6 run load-test.js
<!-- تشغيل مع إخراج السحابة -->
k6 run --out cloud load-test.js
Apache Benchmark (ab) - اختبار سريع
ab أداة بسيطة من سطر الأوامر للاختبار الأساسي:
<!-- اختبار حمل أساسي: 1000 طلب، 10 متزامن -->
ab -n 1000 -c 10 https://example.com/
<!-- مع بيانات POST -->
ab -n 100 -c 10 -p data.json -T application/json https://api.example.com/login
<!-- مع المصادقة -->
ab -n 500 -c 20 -H "Authorization: Bearer token123" https://api.example.com/users
<!-- مقاييس الإخراج: -->
<!-- الطلبات في الثانية: قدرة الإنتاجية -->
<!-- الوقت لكل طلب: متوسط الكمون -->
<!-- معدل النقل: استخدام النطاق الترددي -->
<!-- النسبة المئوية المخدومة خلال X ms: توزيع الكمون -->
ab -n 1000 -c 10 https://example.com/
<!-- مع بيانات POST -->
ab -n 100 -c 10 -p data.json -T application/json https://api.example.com/login
<!-- مع المصادقة -->
ab -n 500 -c 20 -H "Authorization: Bearer token123" https://api.example.com/users
<!-- مقاييس الإخراج: -->
<!-- الطلبات في الثانية: قدرة الإنتاجية -->
<!-- الوقت لكل طلب: متوسط الكمون -->
<!-- معدل النقل: استخدام النطاق الترددي -->
<!-- النسبة المئوية المخدومة خلال X ms: توزيع الكمون -->
تحذير: ab لا يدعم HTTP/2 أو السيناريوهات المعقدة. استخدمه للاختبارات السريعة فقط، وليس لاختبار الحمل الشامل.
اختبار الضغط
اختبار الضغط يدفع نظامك إلى ما بعد القدرة الطبيعية لإيجاد نقاط الانهيار:
<!-- تكوين اختبار ضغط k6 -->
export const options = {
stages: [
{ duration: '2m', target: 100 }, // الصعود للحمل الطبيعي
{ duration: '5m', target: 100 }, // البقاء عند الحمل الطبيعي
{ duration: '2m', target: 200 }, // ضغط: مضاعفة الحمل
{ duration: '5m', target: 200 }, // الحفاظ على الضغط
{ duration: '2m', target: 300 }, // ضغط شديد
{ duration: '5m', target: 300 }, // نقطة الانهيار
{ duration: '2m', target: 0 }, // التعافي
],
};
<!-- راقب هذه أثناء اختبارات الضغط: -->
<!-- استخدام المعالج: يجب ألا يصل لـ 100٪ مستمر -->
<!-- استخدام الذاكرة: راقب التسريبات -->
<!-- أوقات الاستجابة: متى تتدهور؟ -->
<!-- معدلات الخطأ: ما هو عتبة الفشل؟ -->
<!-- اتصالات قاعدة البيانات: هل تصل لحدود المجموعة؟ -->
export const options = {
stages: [
{ duration: '2m', target: 100 }, // الصعود للحمل الطبيعي
{ duration: '5m', target: 100 }, // البقاء عند الحمل الطبيعي
{ duration: '2m', target: 200 }, // ضغط: مضاعفة الحمل
{ duration: '5m', target: 200 }, // الحفاظ على الضغط
{ duration: '2m', target: 300 }, // ضغط شديد
{ duration: '5m', target: 300 }, // نقطة الانهيار
{ duration: '2m', target: 0 }, // التعافي
],
};
<!-- راقب هذه أثناء اختبارات الضغط: -->
<!-- استخدام المعالج: يجب ألا يصل لـ 100٪ مستمر -->
<!-- استخدام الذاكرة: راقب التسريبات -->
<!-- أوقات الاستجابة: متى تتدهور؟ -->
<!-- معدلات الخطأ: ما هو عتبة الفشل؟ -->
<!-- اتصالات قاعدة البيانات: هل تصل لحدود المجموعة؟ -->
التخطيط للقدرة
استخدم بيانات اختبار الحمل لتخطيط توسيع البنية التحتية:
<!-- حساب القدرة المطلوبة -->
// المقاييس الحالية من اختبار الحمل:
// - ذروة حركة المرور: 10,000 طلب/دقيقة
// - الخوادم الحالية: 2
// - وقت الاستجابة عند الذروة: 800ms (مقبول: 300ms)
// الحساب:
// الخوادم المطلوبة = (الخوادم الحالية * وقت استجابة الذروة) / وقت الاستجابة المستهدف
// = (2 * 800) / 300 = 5.3 ≈ 6 خوادم
// أضف 20-30٪ عازل للأمان:
// القدرة النهائية: 6 * 1.25 = 7-8 خوادم
<!-- وثّق النتائج -->
/**
* نتائج اختبار الحمل - 2024-02-16
*
* التكوين: 2x نسخة t3.medium
* نقطة الانهيار: 8,000 طلب/دقيقة
* الاختناق: اتصالات قاعدة البيانات (أقصى 100)
* التوصية: إضافة نسخ قراءة متماثلة + تجميع الاتصالات
* التحسين المتوقع: 3x القدرة (24,000 طلب/دقيقة)
*/
// المقاييس الحالية من اختبار الحمل:
// - ذروة حركة المرور: 10,000 طلب/دقيقة
// - الخوادم الحالية: 2
// - وقت الاستجابة عند الذروة: 800ms (مقبول: 300ms)
// الحساب:
// الخوادم المطلوبة = (الخوادم الحالية * وقت استجابة الذروة) / وقت الاستجابة المستهدف
// = (2 * 800) / 300 = 5.3 ≈ 6 خوادم
// أضف 20-30٪ عازل للأمان:
// القدرة النهائية: 6 * 1.25 = 7-8 خوادم
<!-- وثّق النتائج -->
/**
* نتائج اختبار الحمل - 2024-02-16
*
* التكوين: 2x نسخة t3.medium
* نقطة الانهيار: 8,000 طلب/دقيقة
* الاختناق: اتصالات قاعدة البيانات (أقصى 100)
* التوصية: إضافة نسخ قراءة متماثلة + تجميع الاتصالات
* التحسين المتوقع: 3x القدرة (24,000 طلب/دقيقة)
*/
تذكر: الأداء يتدهور بشكل غير خطي. نظام يتعامل مع 1000 طلب/ثانية لا يتعامل بالضرورة مع 2000 طلب/ثانية بضعف الأجهزة.
تحديد الاختناقات
ادمج اختبار الحمل مع المراقبة للعثور على الاختناقات:
<!-- راقب أثناء اختبارات الحمل -->
// مقاييس التطبيق (عبر New Relic، Datadog):
// - أوقات استجابة نقاط النهاية
// - أوقات استعلامات قاعدة البيانات
// - معدلات نجاح الذاكرة المؤقتة
// - عمق قائمة انتظار المهام الخلفية
// مقاييس البنية التحتية (عبر CloudWatch، Grafana):
// - استخدام المعالج لكل خدمة
// - استخدام الذاكرة والمبادلة
// - إدخال/إخراج الشبكة والنطاق الترددي
// - إدخال/إخراج القرص و IOPS
// مقاييس قاعدة البيانات:
// - الاتصالات النشطة
// - الاستعلامات البطيئة
// - انتظارات القفل
// - تأخر النسخ المتماثل
<!-- مثال: تحديد نقطة نهاية بطيئة -->
// اختبار الحمل يظهر /api/reports يستغرق 3000ms
// APM يظهر 2800ms في استعلام قاعدة البيانات
// EXPLAIN يظهر فهرس مفقود على reports.user_id
// الحل: إضافة فهرس، إعادة اختبار → وقت استجابة 200ms
// مقاييس التطبيق (عبر New Relic، Datadog):
// - أوقات استجابة نقاط النهاية
// - أوقات استعلامات قاعدة البيانات
// - معدلات نجاح الذاكرة المؤقتة
// - عمق قائمة انتظار المهام الخلفية
// مقاييس البنية التحتية (عبر CloudWatch، Grafana):
// - استخدام المعالج لكل خدمة
// - استخدام الذاكرة والمبادلة
// - إدخال/إخراج الشبكة والنطاق الترددي
// - إدخال/إخراج القرص و IOPS
// مقاييس قاعدة البيانات:
// - الاتصالات النشطة
// - الاستعلامات البطيئة
// - انتظارات القفل
// - تأخر النسخ المتماثل
<!-- مثال: تحديد نقطة نهاية بطيئة -->
// اختبار الحمل يظهر /api/reports يستغرق 3000ms
// APM يظهر 2800ms في استعلام قاعدة البيانات
// EXPLAIN يظهر فهرس مفقود على reports.user_id
// الحل: إضافة فهرس، إعادة اختبار → وقت استجابة 200ms
خطوط الأساس للأداء
أنشئ خطوط أساس لاكتشاف التراجعات:
<!-- إنشاء مجموعة اختبار خط الأساس -->
// baseline-tests.js (k6)
export const options = {
thresholds: {
// خط الأساس من اختبار ناجح سابق
'http_req_duration{endpoint:home}': ['p(95)<200'],
'http_req_duration{endpoint:api}': ['p(95)<500'],
'http_req_duration{endpoint:search}': ['p(95)<1000'],
'http_req_failed': ['rate<0.01'],
},
};
<!-- تشغيل في خط أنابيب CI/CD -->
# .github/workflows/performance.yml
name: اختبارات الأداء
on: [push, pull_request]
jobs:
load-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: تشغيل اختبار k6
uses: grafana/k6-action@v0.3.0
with:
filename: tests/baseline-tests.js
cloud: true
token: ${{ secrets.K6_CLOUD_TOKEN }}
// baseline-tests.js (k6)
export const options = {
thresholds: {
// خط الأساس من اختبار ناجح سابق
'http_req_duration{endpoint:home}': ['p(95)<200'],
'http_req_duration{endpoint:api}': ['p(95)<500'],
'http_req_duration{endpoint:search}': ['p(95)<1000'],
'http_req_failed': ['rate<0.01'],
},
};
<!-- تشغيل في خط أنابيب CI/CD -->
# .github/workflows/performance.yml
name: اختبارات الأداء
on: [push, pull_request]
jobs:
load-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: تشغيل اختبار k6
uses: grafana/k6-action@v0.3.0
with:
filename: tests/baseline-tests.js
cloud: true
token: ${{ secrets.K6_CLOUD_TOKEN }}
تمرين: أعد Artillery أو k6، أنشئ اختبار حمل لنقطة النهاية الأكثر أهمية في تطبيقك، شغّل اختبارات عند 10، 50، 100، و200 مستخدم متزامن. وثّق أوقات الاستجابة ومعدلات الخطأ والنقطة التي يتدهور فيها الأداء. حدد وأصلح اختناقًا واحدًا.