_______. _______.___ ___ .______ ____ ____ _______ .______
/ | / | / / | _ / / | ____|| _
| (----` | (----` V / | |_) | / / | |__ | |_) |
> < | / / | __| | /
.----) | .----) | / . | | ----. / | |____ | | ----.
|_______/ |_______/ /__/ __ | _| `._____| __/ |_______|| _| `._____|
SSXRVER هي مكتبة شبكة عالية الأداء وعالية الحركة تعمل على منصة Linux. إنه مكتوب في C ++ 17 ويدعم بروتوكولات TCP و UDP.
يرجى محاولة مطابقة نفس بيئة التطوير مثلي. إذا لم تكن بحاجة إلى وحدة قاعدة بيانات ، فيرجى تعديل cmakelists.txt وفقًا لذلك.
تثبيت Cmake
# debian/ubuntu
sudo apt-get install cmakeتعزيز تركيب المكتبة
wget http://sourceforge.net/projects/boost/files/boost/1.72.0/boost_1_72_0.tar.bz2
tar -xvf boost_1_72_0.tar.bz2
cd ./boost_1_72_0
./bootstrap.sh --prefix=/usr/local
sudo ./b2 install --with=allتشغيل.
./build.shسيقوم المترجم بنجاح بإنشاء Build/ Directory ، والملف القابل للتنفيذ في دليل الإصدار المقابل. على سبيل المثال ، عند تحديد إصدار الإصدار ، يكون الملف القابل للتنفيذ في/إنشاء/إصدار/ssxrver.
قم بتقليد تنسيق conf/ssxrver.json.example لإنشاء ملف التكوين الخاص بك (لاحظ أنه لا يمكن التعليق على ملف التكوين ، ولم يتم التعليق عليه ، ولم يتم التعليق عليه). سأشرح خيارات كل ملف تكوين أدناه. أنا في الواقع ضبط القيم الافتراضية للعديد من المعلمات. إذا لم يتم تكوينه ، فلن يؤثر عليه.
{
" port " : 4507, # 端口号,不填的话默认4507
" address " : " 127.0.0.1 " , # 绑定的地址
" worker_processes " : 4, # IO 线程数量,不填默认为 4 个
" worker_connections " : -1, # 一个 IO 线程最多支持多少连接, -1 表示最多能创建多少就创建多少,不做限制
" task_processes " : 0, # 任务线程,不填的话默认为 0
" cpu_affinity " : " off " , # cpu 亲和度 ,默认关闭
" http " : { # http 模块
" max_body_size " : 67108864, # 单个 http 包最大支持大小
" root_path " : " /home/randylambert/sunshouxun/ssxrver/html/ " # 文件访问根路径
},
" log " : { # log 模块
" level " : " INFO " , # 输出等级,可填三种等级, DEBUG,INFO,WARN 不填默认为 INFO 等级
" ansync_started " : " off " , # 是否打开异步日志线程,不填默认关闭
" flush_second " : 3, # 异步线程每隔多久持久化一次
" roll_size " : 67108864, # 日志文件滚动大小
" path " : " /home/randylambert/sunshouxun/ssxrver/logs/ " , # 日志文件存放路径
" base_name " : " ssxrver " # 日志文件基础名
},
" mysql " : { # 数据库模块
" mysql_started " : " off " , # 是否打开数据库模块,默认关闭
" address " : " 127.0.0.1 " , # 以下是对应数据库连接信息
" user " : " root " ,
" password " : " 123456 " ,
" database_name " : " ttms " ,
" port " : 0,
" unix_socket " : null,
" client_flag " : 0
},
" blocks_ip " : [ " 122.0.0.2 " , " 198.1.2.33 " ] # 可屏蔽部分恶意 IP
}تشغيل الملف القابل للتنفيذ.
./ssxrver -f /配置文件的路径
# 例如
./build/Release/ssxrver -f ./conf/ssxrver.json| بيئة اختبار | قيمة |
|---|---|
| إصدار تصفيفة الشعر نظام التشغيل | Deepin V20.1 Community Edition (1030) |
| نسخة نواة | 5.4.70-AMD64-Desktop (64 بت) |
| نسخة المترجم | GCC 8.3 |
| زيادة نسخة المكتبة | 1.72 |
| المعالج | Intel (R) Core (TM) I7-8750H CPU @2.20GHz |
| L1 حجم ذاكرة التخزين المؤقت | 32 كيلو |
| L2 حجم ذاكرة التخزين المؤقت | 256k |
| L3 حجم ذاكرة التخزين المؤقت | 9216K |
| سرعة القرص الصلب | 1.8 محرك الأقراص الصلبة الميكانيكية TIB 5400 دورة في الدقيقة |
| قرص الثابت قراءة وتكتب السرعة | 370 ميغابايت في 3.03 ثانية = 122.27 ميغابايت/ثانية |
| ذاكرة | 7.6 جيجابايت |
| قسم المبادلة | 4.7 جيجابايت |
| العد الأساسي المنطقي | 12 النوى |
للتحكم في المتغيرات ، أعد تشغيل الكمبيوتر قبل الاختبار للتأكد من أن بيئة الاختبار لا تحتوي على تطبيقات أخرى مع تحميل وحدة المعالجة المركزية العالية وتحميل IO العالي.
أداة الاختبار هي WebBench1.5. قم بإزالة بيانات الاحماء الأولى. أمر الاختبار كما يلي (تم الوصول إلى 100 عميل بشكل مستمر لمدة 15 ثانية).
./webbench -c 100 -t 15 http://127.0.0.1:8081/كائنات الاختبار هي apache/2.4.38 ، nginx/1.14.2 ، ssxrver.
ملاحظة: سواء كان استخدام WebBench أو AB ، لا يمكن استخدام البيانات المقاسة بواسطة أداة قياس الضغط هذه إلا كمرجع بسيط. قياس الضغط هو اختبار يتطلب جميع الجولة ومتعددة الزاوية ، بدلاً من مجرد تشغيل أمر. حتى أثناء قياس الضغط ، لا يتم نقل البيانات عبر الشبكة على الإطلاق ، ولكن تدور حول النواة.
| مكتبة الشبكة | السرعة (الصفحات/دقيقة) | يطلب معدل النجاح |
|---|---|---|
| SSXRver يرجع الاستجابة التي تم إنشاؤها في الذاكرة | 7107414 | 100 ٪ |
| يقوم SSXRver بإرجاع الملفات الثابتة | 5114376 | 100 ٪ |
| Apache/2.4.28 | 2884072 | 100 ٪ |
| Nginx/1.14.2 | 4728748 | 100 ٪ |
نتائج اختبار SSXRver جيدة جدًا ، لكن من الغريب ، اعتقدت أن البيانات ستكون أعلى ، لأنه عندما كنت أتطور في الأيام الأولى ، لم أقم بإجراء العديد من التحسينات في ذلك الوقت. عندما عدت الاستجابة التي تم إنشاؤها مباشرة في الذاكرة ، تم قياسها على الأقل ما يقرب من 8000000 صفحة/دقيقة (لم يتم أخذ نتائج الاختبار البالغة 8000000/دقيقة في لقطات الشاشة ، تاركة 7550778). في ذلك الوقت ، كان لدى Nginx/1.14.2 بحد أقصى 5000000 صفحة/دقيقة. ومع ذلك ، بغض النظر عما إذا كان SSXRVER أو NGINX/1.14.2 ، لم أتمكن من العثور على هذه القيمة العالية. لا أعرف ما هو السبب ، الذي أدى إلى مثل هذه الفجوة الكبيرة في النتيجة النهائية (هل لأن جهاز الكمبيوتر الخاص بي يتقدم؟
في الوقت الحاضر ، سأقوم شخصياً بتعديل وحدة المخزن المؤقت ووحدة السجل الخاصة بـ SSXRver إذا كان لدي وقت.
بادئ ذي بدء ، فإن أسهل طريقة لتعديل الوحدة العازلة هي تغييرها إلى مخزن مؤقت دوري ، وبالتالي تقليل عدد مرات تحريك البيانات المخزن المؤقت بشكل فعال ، أو التخلي مباشرة عن هذا التنفيذ المخزن المؤقت وإعادة تنفيذ المخزن المؤقت عالي الأداء.
ثانياً ، تتم كتابة وحدة السجل الحالية في شكل دفق C ++. على الرغم من أنه أعلى بالتأكيد من استخدام C ++ مباشرة مع ioStream ، إلا أن التحميل الزائد في السجل في << سوف يظل النموذج الرمزي يسبب تحكمًا غير مريح في التنسيق ومشاكل الأداء الناتجة عن سلاسل مكالمات الوظائف. يمكن حل كل من هذه المشكلات عن طريق تنفيذ السجل في شكل printf.
لأسباب زمنية ، لا يقوم SSXRver بتنفيذ وحدة إدارة الذاكرة ، لذلك يكاد يكون من المستحيل كتابة وحدة إدارة للذاكرة عالية الأداء (من الأفضل الذهاب مباشرة إلى Jemalloc أو TCMALLOC). ومع ذلك ، من خلال تحليل سيناريو مكتبة الشبكة ، لا يزال هناك فرصة ضئيلة لكتابة وحدة إدارة الذاكرة ذات الأداء الأعلى في هذا السيناريو. إذا كان لدي وقت ، فسوف ألقي نظرة على التنفيذ في Nginx وأتعلمه.
عندما كنت أتناول المعلومات ، توصلت إلى استنتاج مفاده أنه في C ++ 17 ، يمكنك استخدام std :: string_view لاستبدال سلسلة const & ، والتي ستحسن بعض الكفاءة. لذلك ، حاولت استبدال جميع الأماكن التي يكون فيها Const String وفي مشروعي بـ Std :: String_View. ومع ذلك ، عندما استخدمت أخيرًا perf -top لعرض الحمل الذي تم تغييره ، اكتشفت بشكل غير متوقع أن بعض الوظائف زادت فعليًا بعد أن استخدمت std :: string_view لاستبدالها. كنت في حيرة للغاية لماذا حدث هذا الموقف. لأسباب زمنية ، لن أتحقق من السبب المحدد لهذه المشكلة في الوقت الحالي. لدي الفرصة للتحقق من التنفيذ الأساسي للتحقق من السبب المحدد.
عند تنفيذ وحدة تحليل HTTP ، استخدمت آلة حالة مكتوبة بخط اليد تتوافق مباشرة مع الأوتار في الإصدار الأول. ثم استبدلته بآلة الحالة التي تنفذها Ragel. ومع ذلك ، خلال الاختبارات الحديثة ، وجدت أن حمولة وظيفة تحليل HTTP مبالغ فيها للغاية ، تصل إلى 10 ٪. هل يمكن أن يكون استخدام Ragel تسبب في تدهور الأداء؟ (إذا كان تحليل الرأس سيؤدي إلى مثل هذا الحمل العالي للنظام ، فيبدو أن HTTP/2.0 سيظل يحسن الأداء بشكل كبير) لسوء الحظ ، عندما كتبت بجهاز الحالة بدقة من قبل ، لم أختبر تحميل وظيفة التحليل المقابلة. الآن لا يمكنني الحصول على مقارنة البيانات بين الاثنين في وقت واحد ، ولدي الفرصة لكتابة اختبار قياسي.
يدعم SSXRver انتقال UDP البسيط ، لكنني شخصياً أعتقد أن إطار UDP دون التحكم في الازدحام ، ومراقبة حركة المرور ، ووظائف إعادة إرسال الحزم يمكن القول بشكل أساسي بشكل طبيعي. في المستقبل ، لدي وقت لتعلم بروتوكولات QUIC و KCP. سأكمل المعرفة المتعلقة بـ UDP. أعتقد أن بروتوكول UDP الأكثر كفاءة ومرونة سيتم استخدامه على نطاق أوسع في المستقبل!
في الواقع ، أعتقد في الواقع أن أفضل إطار عمل للشبكة في الوقت الحالي يجب أن يكون هذا العنوان المتعدد المنفذ مضاعفًا بالإضافة إلى مؤشرات ترابط متعددة (متعددة العمليات) يربط العنوان والمنفذ نفسه ، ويقوم kernel بتنفيذ موازنة التحميل تلقائيًا. في الوقت نفسه ، يقوم نظام الكتل من خلال Coroutine Framework + Hook. بعد استخدام هذا الإطار ، يمكن أن يضمن أداءً عاليًا دون استخدام مؤشر الترابط الرئيسي لتوزيع الاتصالات ، وليس هناك حاجة إلى الوقوع في جحيم رد الاتصال غير المتزامن.
بالإضافة إلى ذلك ، إذا كان بإمكانك استخدام آلية IO غير المتزامنة IO_URING تمت إضافتها بعد Linux kernel 5.1 ، أعتقد أن أداء الخادم سيكون أعلى. ومع ذلك ، لا أعرف الكثير عن io_uring في الوقت الحالي ، وليس لدي القدرة على تصميم مكتبة شبكة IO غير متزامنة تعتمد على io_uring.