---
title: "`systemtap-toolkit` و `stapxx`: كيفية استخدام البيانات لحل المشكلات الصعبة؟ - API7.ai"
description: "يمكن استخدام مجموعات الأدوات المعتمدة على systemtap: systemtap-toolkit وstapxx لحل مشكلات التحليل الفوري والتشخيص لـ NGINX وOpenResty."
url: "https://api7.ai/ar/learning-center/openresty/systemtap-toolkit-and-stapxx"
---

# \`systemtap-toolkit\` و \`stapxx\`: كيفية استخدام البيانات لحل المشكلات الصعبة؟

API7.ai

December 22, 2022

[OpenResty (NGINX + Lua)](https://api7.ai/learning-center/openresty)

كما تم تقديمه في المقالة السابقة، كمهندسي تطوير على جانب الخادم، لا نقوم بالتعمق في تعلم أدوات التصحيح الديناميكي، ولكننا نبقى في الغالب على مستوى الاستخدام ونكتب بعض البرامج النصية البسيطة على الأكثر. المستوى الأدنى، مثل ذاكرة التخزين المؤقت للوحدة المركزية (CPU cache)، والهندسة المعمارية، والمترجم، وما إلى ذلك، هو مجال مهندسي الأداء.

هناك مشروعان مفتوحا المصدر في OpenResty: `openresty-systemtap-toolkit` و `stapxx`. هما مجموعتا أدوات مبنية على `systemtap` لتحليل وتشخيص NGINX و OpenResty في الوقت الفعلي. يمكنهما تغطية الميزات وسيناريوهات التصحيح الشائعة مثل on-CPU، off-CPU، القاموس المشترك، جمع القمامة، تأخر الطلبات، تجميع الذاكرة، تجميع الاتصالات، الوصول إلى الملفات، وغيرها.

في هذه المقالة، سنستعرض هذه الأدوات واستخداماتها المقابلة، لمساعدتنا في العثور بسرعة على الأدوات لتحديد المشكلات عند مواجهة مشاكل استكشاف الأخطاء وإصلاحها مع NGINX و OpenResty. في عالم OpenResty، تعلم استخدام هذه الأدوات هو طريقة مؤكدة للتقدم، وطريقة فعالة جدًا للتواصل مع المطورين الآخرين - بعد كل شيء، البيانات التي تولدها الأدوات ستكون أكثر دقة وتفصيلاً مما يمكننا وصفه بالكلمات.

ومع ذلك، من الضروري ملاحظة أن وضع LuaJIT GC64 مفعل بشكل افتراضي في إصدار OpenResty `1.15.8`، ولكن `openresty-systemtap-toolkit` و `stapxx` لا يتبعان التغييرات المقابلة، مما سيؤدي إلى عدم عمل الأدوات داخلهما بشكل صحيح. لذا، من الأفضل استخدام هذه الأدوات في الإصدار القديم `1.13` من OpenResty.

معظم مساهمي المشاريع مفتوحة المصدر يعملون بدوام جزئي وليسوا ملزمين بإبقاء الأدوات تعمل، وهو ما نحتاج إلى أن نكون على دراية به عند استخدام المشاريع مفتوحة المصدر.

## مثال: `shared dict`

لنبدأ بأداة ربما نكون أكثر دراية بها وأسهل في البدء بها، `ngx-lua-shdict`، كمثال لبدء منشور اليوم.

`ngx-lua-shdict` هي أداة تحلل `shared dict`s في NGINX وتتبع عملياتها. يمكنك استخدام الخيار `-f` لتحديد `dict` و `key` للحصول على البيانات في `shared dict`. الخيار `--raw` يسمح لك بتصدير القيمة الخام للمفتاح المحدد.

التالي هو مثال على سطر الأوامر للحصول على البيانات من `shared dict`.

```
# بافتراض أن معرف عملية NGINX Worker هو 5050
$ ./ngx-lua-shdict -p 5050 -f --dict dogs --key Jim --luajit20
Tracing 5050 (/opt/nginx/sbin/nginx)...

type: LUA_TBOOLEAN
value: true
expires: 1372719243270
flags: 0xa
```

بالمثل، يمكننا استخدام الخيار `-w` لتتبع كتابات القاموس لمفتاح معين:

```
$./ngx-lua-shdict -p 5050 -w --key Jim --luajit20
Tracing 5050 (/opt/nginx/sbin/nginx)...

Hit Ctrl-C to end

set Jim exptime=4626322717216342016
replace Jim exptime=4626322717216342016
^C
```

لنرى كيف يتم تنفيذ هذه الأداة. `ngx-lua-shdict` هو نص برمجي بلغة Perl، ولكن التنفيذ لا علاقة له بـ Perl، حيث يتم استخدامه فقط لإنشاء نص `stap` وتشغيله.

```
open my $in, "|stap $stap_args -x $pid -" or die "Cannot run stap: $!\n";
```

يمكننا كتابته بلغة Python، PHP، Go، أو أي لغة نفضلها. النقطة الرئيسية في نص `stap` هي السطر التالي من الكود:

```
probe process("$nginx_path").function("ngx_http_lua_shdict_set_helper")
```

هذا هو `probe` الذي ذكرناه سابقًا، والذي يتحقق من الوظيفة `ngx_http_lua_shdict_set_helper`. يتم استدعاء هذه الوظيفة في ملف `lua-nginx-module/src/ngx_http_lua_shdict.c` في وحدة `lua-nginx-module`.

```
static int
ngx_http_lua_shdict_add(lua_State *L)
{
return ngx_http_lua_shdict_set_helper(L, NGX_HTTP_LUA_SHDICT_ADD);
}

static int
ngx_http_lua_shdict_safe_add(lua_State *L)
{
return ngx_http_lua_shdict_set_helper(L, NGX_HTTP_LUA_SHDICT_ADD
|NGX_HTTP_LUA_SHDICT_SAFE_STORE);
}

static int
ngx_http_lua_shdict_replace(lua_State *L)
{
return ngx_http_lua_shdict_set_helper(L, NGX_HTTP_LUA_SHDICT_REPLACE);
}
```

بهذه الطريقة، يمكننا تتبع جميع عمليات القاموس المشترك ببساطة عن طريق التحقق من هذه الوظيفة.

## on-CPU, off-CPU

في استخدام OpenResty، المشكلة الأكثر شيوعًا التي نواجهها هي الأداء. هناك نوعان رئيسيان من ضعف الأداء، أي انخفاض QPS: استخدام وحدة المعالجة المركزية (CPU) مرتفع جدًا واستخدام وحدة المعالجة المركزية منخفض جدًا. قد يكون سبب الاختناق الأول هو عدم استخدام طرق تحسين الأداء التي قدمناها سابقًا، بينما قد يكون السبب الثاني هو وظائف الحظر. يمكن أن تساعدنا الرسوم البيانية للهب on-CPU و off-CPU في تحديد السبب الجذري النهائي.

لإنشاء رسوم بيانية للهب on-CPU على مستوى C، تحتاج إلى استخدام `sample-bt` في `systemtap-toolkit`؛ بينما يتم إنشاء رسوم بيانية للهب on-CPU على مستوى Lua بواسطة `lj-lua-stacks` في `stapxx`.

لنأخذ `sample-bt` كمثال على كيفية استخدامه. `sample-bt` هو نص برمجي يأخذ عينات من مكدس الاستدعاءات لأي عملية مستخدم نحددها (ليس فقط عمليات NGINX و OpenResty).

على سبيل المثال، يمكننا أخذ عينة من عملية NGINX Worker قيد التشغيل (مع معرف عملية `8736`) لمدة 5 ثوان باستخدام الكود التالي:

```
$ ./sample-bt -p 8736 -t 5 -u > a.bt
WARNING: Tracing 8736 (/opt/nginx/sbin/nginx) in user-space only...
WARNING: Missing unwind data for module, rerun with 'stap -d stap_df60590ce8827444bfebaf5ea938b5a_11577'
WARNING: Time's up. Quitting now...(it may take a while)
WARNING: Number of errors: 0, skipped probes: 24
```

يخرج ملف النتيجة `a.bt`، والذي يمكن استخدامه لإنشاء رسم بياني للهب باستخدام مجموعة أدوات FlameGraph:

```
stackcollapse-stap.pl a.bt > a.cbt
flamegraph.pl a.cbt > a.svg
```

`a.svg` هو الرسم البياني للهب الذي تم إنشاؤه، والذي يمكننا فتحه في المتصفح لعرضه. ومع ذلك، خلال فترة أخذ العينات، يجب أن نحافظ على عدد معين من الطلبات. وإلا، لن يكون هناك طريقة لإنشاء الرسم البياني للهب إذا كان عدد العينات `0`.

التالي، سننظر في كيفية أخذ عينات off-CPU، باستخدام النص البرمجي `sample-bt-off-cpu` في `systemtap-toolkit`، والذي يشبه `sample-bt`، كما يلي:

```
$ ./sample-bt-off-cpu -p 10901 -t 5 > a.bt
WARNING: Tracing 10901 (/opt/nginx/sbin/nginx)...
WARNING: _stp_read_address failed to access memory location
WARNING: Time's up. Quitting now...(it may take a while)
WARNING: Number of errors: 0, skipped probes: 23
```

في `stapxx`، الأداة لتحليل التأخير هي `epoll-loop-blocking-distr`، والتي تأخذ عينات من عملية مستخدم محددة وتخرج توزيع التأخير بين استدعاءات نظام `epoll_wait` المتتالية.

```
$ ./samples/epoll-loop-blocking-distr.sxx -x 19647 --arg time=60
Start tracing 19647...
Please wait for 60 seconds.
Distribution of epoll loop blocking latencies (in milliseconds)
max/avg/min: 1097/0/0
value |-------------------------------------------------- count
    0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  18471
    1 |@@@@@@@@                                            3273
    2 |@                                                    473
    4 |                                                     119
    8 |                                                      67
   16 |                                                      51
   32 |                                                      35
   64 |                                                      20
  128 |                                                      23
  256 |                                                       9
  512 |                                                       2
 1024 |                                                       2
 2048 |                                                       0
 4096 |                                                       0
```

كما نرى، يظهر هذا الإخراج أن الغالبية العظمى من التأخيرات أقل من 1 مللي ثانية، ولكن هناك عدد قليل فوق 200 مللي ثانية، وهذه هي التي يجب مراقبتها.

## تتبع Upstream والمراحل

بالإضافة إلى مشاكل الأداء التي قد تحدث في كود OpenResty نفسه، عندما يتواصل OpenResty مع خدمات upstream من خلال وحدات مثل `cosocket` أو `proxy_pass`، إذا كانت الخدمة upstream نفسها لديها تأخير كبير، يمكن أن يكون لها تأثير كبير على الأداء العام.

في هذه الحالة، يمكننا استخدام الأدوات `ngx-lua-tcp-recv-time`، `ngx-lua-udp-recv-time` و `ngx-single-req-latency` للتحليل. هنا مثال على `ngx-single-req-latency`.

هذه الأداة ليست تمامًا مثل معظم الأدوات داخل مجموعة الأدوات. معظم الأدوات الأخرى تعتمد على عدد كبير من العينات والتحليل الإحصائي لاستخلاص استنتاج رياضي حول التوزيع. بدلاً من ذلك، `ngx-single-req-latency` تحلل الطلبات الفردية وتتبع الوقت الذي تقضيه الطلبات الفردية في مراحل مختلفة في OpenResty، مثل مراحل `rewrite`، `access`، و `content`، وكذلك upstream.

يمكننا النظر إلى مثال محدد للكود:

```
# جعل أداة ./stap++ مرئية في PATH:
$ export PATH=$PWD:$PATH

# بافتراض أن معرف عملية NGINX Worker هو 27327
$ ./samples/ngx-single-req-latency.sxx -x 27327
Start tracing process 27327 (/opt/nginx/sbin/nginx)...

POST /api_json
    total: 143596us, accept() ~ header-read: 43048us, rewrite: 8us, pre-access: 7us, access: 6us, content: 100507us
    upstream: connect=29us, time-to-first-byte=99157us, read=103us

$ ./samples/ngx-single-req-latency.sxx -x 27327
Start tracing process 27327 (/opt/nginx/sbin/nginx)...

GET /robots.txt
    total: 61198us, accept() ~ header-read: 33410us, rewrite: 7us, pre-access: 7us, access: 5us, content: 27750us
    upstream: connect=30us, time-to-first-byte=18955us, read=96us
```

هذه الأداة ستتبع أول طلب تواجهه بعد بدئها. الإخراج مشابه جدًا لـ `opentracing`، ويمكننا حتى التفكير في `systemtap-toolkit` و `stapxx`، كإصدارات غير تدخلية من APM (إدارة أداء التطبيقات) في OpenResty.

## الخلاصة

بالإضافة إلى الأدوات الشائعة التي تحدثت عنها اليوم، يوفر OpenResty بشكل طبيعي العديد من الأدوات الأخرى التي يمكنك استكشافها وتعلمها بنفسك.

هناك فرق كبير آخر بين OpenResty ولغات ومنصات التطوير الأخرى في تقنية التتبع، والذي يمكننا تقديره ببطء.

> حافظ على الكود نظيفًا ومستقرًا، لا تضيف إليه مجسات، ولكن خذ عينات منه من خلال تقنيات التتبع الديناميكي الخارجية.

ما هي الأدوات التي استخدمتها لتتبع وتحليل المشكلات أثناء استخدام OpenResty؟ أنت مدعو لمشاركة هذه المقالة، وسنتشارك ونتقدم معًا.

Share article link

Share

Related Posts

[![OpenResty الأسئلة الشائعة | هيكل الشبكة للاختبار، الميزات المتعلقة بـ SSL، DSL، أداة \`ab\`](https://static.api7.ai/2022/12/02/63896c177fde1.png)](https://api7.ai/learning-center/openresty/faq-3)

## [OpenResty الأسئلة الشائعة | هيكل الشبكة للاختبار، الميزات المتعلقة بـ SSL، DSL، أداة \`ab\`](https://api7.ai/learning-center/openresty/faq-3)

[![اختبار الأداء الدقيق باستخدام \`wrk\`](https://static.api7.ai/2022/11/25/63802abdc3b1b.png)](https://api7.ai/learning-center/openresty/performance-testing-tool-wrk)

## [اختبار الأداء الدقيق باستخدام \`wrk\`](https://api7.ai/learning-center/openresty/performance-testing-tool-wrk)

Table of Contents

- [مثال: `shared dict`](#%D9%85%D8%AB%D8%A7%D9%84-shared-dict)
- [on-CPU, off-CPU](#on-cpu-off-cpu)
- [تتبع Upstream والمراحل](#%D8%AA%D8%AA%D8%A8%D8%B9-upstream-%D9%88%D8%A7%D9%84%D9%85%D8%B1%D8%A7%D8%AD%D9%84)
- [الخلاصة](#%D8%A7%D9%84%D8%AE%D9%84%D8%A7%D8%B5%D8%A9)
