_______. _______.___ ___ .______ ____ ____ _______ .______
/ | / | / / | _ / / | ____|| _
| (----` | (----` V / | |_) | / / | |__ | |_) |
> < | / / | __| | /
.----) | .----) | / . | | ----. / | |____ | | ----.
|_______/ |_______/ /__/ __ | _| `._____| __/ |_______|| _| `._____|
SSXRVER adalah perpustakaan jaringan berkinerja tinggi dan berkinerja tinggi yang berjalan di platform Linux. Ini ditulis dalam C ++ 17 dan mendukung protokol TCP dan UDP.
Silakan cobalah untuk mencocokkan lingkungan pengembangan yang sama dengan saya. Jika Anda tidak memerlukan modul basis data, silakan modifikasi cmakelists.txt sesuai.
Instalasi CMake
# debian/ubuntu
sudo apt-get install cmakeBoost Instalasi Perpustakaan
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=allJalankan ./build.sh di direktori ssxrver, Anda dapat memodifikasi build.sh untuk memilih untuk menghasilkan versi debug atau versi rilis (versi rilis default)
./build.shKompilasi berhasil akan menghasilkan Direktori Build/, dan file yang dapat dieksekusi ada di direktori versi yang sesuai. Misalnya, ketika Anda memilih versi rilis, file yang dapat dieksekusi ada di/build/rilis/ssxrver.
Tiru format conf/ssxrver.json.example untuk membuat file konfigurasi Anda (perhatikan bahwa file konfigurasi tidak dapat dikomentari, tidak dikomentari, tidak dikomentari). Saya akan menjelaskan opsi setiap file konfigurasi di bawah ini. Saya sebenarnya mengatur nilai default untuk banyak parameter. Jika tidak dikonfigurasi, itu tidak akan mempengaruhi itu.
{
" 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
}Jalankan file yang dapat dieksekusi.
./ssxrver -f /配置文件的路径
# 例如
./build/Release/ssxrver -f ./conf/ssxrver.json| Lingkungan Uji | Nilai |
|---|---|
| Versi Gaya Rambut Sistem Operasi | Deepin V20.1 Edisi Komunitas (1030) |
| Versi kernel | 5.4.70-AMD64-desktop (64-bit) |
| Versi kompiler | GCC 8.3 |
| Boost Library Version | 1.72 |
| prosesor | Intel (R) Core (TM) I7-8750H CPU @2.20GHz |
| Ukuran cache L1 | 32k |
| Ukuran cache L2 | 256K |
| Ukuran cache L3 | 9216K |
| Kecepatan hard disk | 1.8 Tib Mekanik Hard Drive 5400 RPM |
| Hard disk membaca dan menulis kecepatan | 370 MB dalam 3,03 detik = 122,27 mb/detik |
| Ingatan | 7.6GB |
| Partisi Pertukaran | 4.7GB |
| Hitungan inti logis | 12 core |
Untuk mengontrol variabel, restart komputer sebelum pengujian untuk memastikan bahwa lingkungan pengujian tidak memiliki aplikasi lain dengan beban CPU tinggi dan beban IO tinggi.
Alat uji adalah WebBench1.5. Hapus data pemanasan pertama. Perintah tes adalah sebagai berikut (100 klien telah diakses terus menerus selama 15 detik).
./webbench -c 100 -t 15 http://127.0.0.1:8081/Objek uji adalah Apache/2.4.38, nginx/1.14.2, ssxrver.
Catatan: Apakah menggunakan WebBench atau AB, data yang diukur dengan alat pengukuran tekanan ini hanya dapat digunakan sebagai referensi sederhana. Pengukuran tekanan adalah tes yang membutuhkan serba dan multi-sudut, daripada hanya menjalankan perintah. Bahkan selama pengukuran tekanan, data tidak ditransmisikan melalui jaringan sama sekali, tetapi hanya berkeliling di kernel.
| Perpustakaan Jaringan | Kecepatan (halaman/mnt) | Meminta Tingkat Keberhasilan |
|---|---|---|
| SSXRVER Mengembalikan respons yang dihasilkan dalam memori | 7107414 | 100% |
| ssxrver mengembalikan file statis | 5114376 | 100% |
| Apache/2.4.28 | 2884072 | 100% |
| Nginx/1.14.2 | 4728748 | 100% |
Hasil tes SSXRVER cukup bagus, tetapi anehnya, saya pikir data akan lebih tinggi, karena ketika saya berkembang di hari -hari awal, saya tidak melakukan banyak optimasi pada waktu itu. Ketika saya mengembalikan respons yang dihasilkan langsung dalam memori, itu diukur paling dekat dengan 8000000 halaman/menit (hasil pengujian 8000000 halaman/menit tidak diambil dalam tangkapan layar, meninggalkan 7550778). Pada saat itu, Nginx/1.14.2 memiliki maksimum 5000000 halaman/menit. Namun, tidak peduli apakah itu ssxrver atau nginx/1.14.2, saya tidak dapat menemukan nilai yang tinggi. Saya tidak tahu apa alasannya, yang menyebabkan kesenjangan besar dalam hasil akhir (apakah karena komputer saya menua?  ̄ □  ̄||)
Saat ini, saya pribadi akan memodifikasi modul buffer dan modul log SSXRVER jika saya punya waktu.
Pertama-tama, cara termudah untuk memodifikasi modul buffer adalah dengan mengubahnya menjadi buffer siklik, sehingga secara efektif mengurangi berapa kali buffer memajukan data, atau secara langsung meninggalkan implementasi buffer ini dan mengimplementasikan kembali buffer kinerja tinggi.
Kedua, modul log saat ini ditulis dalam bentuk aliran C ++. Meskipun jelas lebih tinggi dalam kinerja daripada menggunakan C ++ secara langsung dengan IOSTREAM, kelebihan log dalam bentuk << simbolik masih akan menyebabkan kontrol format yang tidak nyaman dan masalah kinerja yang disebabkan oleh fungsi rantai panggilan. Kedua masalah ini dapat diselesaikan dengan mengimplementasikan log dalam bentuk printf.
Karena alasan waktu, SSXRver tidak mengimplementasikan modul manajemen memori, sehingga hampir tidak mungkin untuk menulis modul manajemen memori kinerja tinggi umum (lebih baik untuk langsung pergi ke Jemalloc atau TCMalloc). Namun, dengan menganalisis skenario perpustakaan jaringan, masih ada sedikit kesempatan untuk menulis modul manajemen memori dengan kinerja yang lebih tinggi dalam skenario ini. Jika saya punya waktu, saya akan melihat implementasi di Nginx dan mempelajarinya.
Ketika saya menanyakan informasi, saya sampai pada kesimpulan bahwa di C ++ 17, Anda dapat menggunakan std :: string_view untuk menggantikan string const &, yang akan meningkatkan efisiensi. Oleh karena itu, saya mencoba mengganti semua tempat di mana const string & dalam proyek saya dengan std :: string_view. Namun, ketika saya akhirnya menggunakan perf -top untuk melihat beban yang diganti, saya secara tak terduga menemukan bahwa beberapa fungsi benar -benar meningkat setelah saya menggunakan std :: string_view untuk menggantinya. Saya sangat bingung mengapa situasi ini terjadi. Karena alasan waktu, saya tidak akan menyelidiki penyebab spesifik dari masalah ini untuk saat ini. Saya memiliki kesempatan untuk memeriksa implementasi yang mendasarinya untuk memeriksa alasan spesifik.
Saat mengimplementasikan modul parsing HTTP, saya menggunakan mesin status tulisan tangan yang secara langsung cocok dengan string di versi pertama. Kemudian saya menggantinya dengan mesin negara yang diimplementasikan oleh Ragel. Namun, selama tes baru -baru ini, saya menemukan bahwa beban fungsi parsing HTTP sangat berlebihan, mencapai 10%. Mungkinkah menggunakan Ragel telah menyebabkan degradasi kinerja? (Jika parsing header akan menyebabkan beban sistem yang tinggi, maka tampaknya HTTP/2.0 masih akan meningkatkan kinerja secara signifikan) sayangnya, ketika saya menulis mesin negara sebelumnya, saya tidak menguji beban fungsi parsing yang sesuai. Sekarang saya tidak bisa mendapatkan perbandingan data antara keduanya sekaligus, dan saya memiliki kesempatan untuk menulis tes benchmark.
SSXRVER mendukung transmisi UDP sederhana, tetapi saya pribadi berpikir bahwa kerangka kerja UDP tanpa kontrol kemacetan, kontrol lalu lintas, dan fungsi retransmisi kehilangan paket pada dasarnya dapat dikatakan tidak dapat digunakan secara normal. Di masa depan, saya punya waktu untuk mempelajari protokol QUIC dan KCP. Saya akan melengkapi pengetahuan terkait UDP. Saya percaya bahwa protokol UDP yang lebih efisien dan fleksibel akan lebih dan lebih banyak digunakan di masa depan!
Faktanya, saya benar-benar berpikir kerangka kerja jaringan terbaik saat ini haruslah bahwa alamat multiplexing port multiplexing plus beberapa utas (multi-proses) mengikat alamat dan port yang sama, dan kernel secara otomatis melakukan menerima penyeimbangan beban. Pada saat yang sama, blok panggilan sistem melalui Coroutine Framework + Hook. Setelah menggunakan kerangka kerja ini, ini dapat memastikan kinerja tinggi tanpa menggunakan utas utama untuk mendistribusikan koneksi, dan tidak perlu jatuh ke dalam callback neraka yang tidak sinkron.
Selain itu, jika Anda dapat menggunakan mekanisme IO asinkron io_uring ditambahkan setelah kernel Linux 5.1, saya percaya bahwa kinerja server akan lebih tinggi. Namun, saya tidak tahu banyak tentang IO_uring saat ini, dan saya tidak memiliki kemampuan untuk merancang perpustakaan jaringan IO asinkron berdasarkan IO_URGE.