Kemampuan untuk membentuk lalu lintas yang masuk ke database adalah salah satu yang paling penting. Dalam beberapa hari terakhir Anda tidak memiliki banyak kendali atas itu - aplikasi mengirim lalu lintas ke database dan hanya itu. HAProxy, yang biasa digunakan, juga tidak memiliki opsi untuk mengontrol lalu lintas secara halus. Dengan diperkenalkannya proxy SQL-aware, seperti ProxySQL, lebih banyak kemungkinan tersedia untuk administrator database. Mari kita lihat kemungkinan penanganan koneksi dan pembatasan di ProxySQL.
Penanganan Koneksi di ProxySQL
Seperti yang Anda ketahui, cara kerja ProxySQL adalah melalui aturan kueri. Ini adalah daftar aturan yang menguji setiap kueri dan yang mengatur dengan tepat bagaimana ProxySQL akan menangani kueri. Mulai dari awal, aplikasi terhubung ke ProxySQL. Ini akan mengautentikasi terhadap ProxySQL (inilah sebabnya ProxySQL harus menyimpan semua pengguna dan hash kata sandi) dan kemudian ProxySQL akan menjalankannya melalui aturan kueri untuk menentukan ke grup host mana kueri harus dikirim.
ProxySQL membuka kumpulan koneksi ke server backend. Ini bukan pemetaan 1-ke-1, secara default ia mencoba untuk menggunakan kembali satu koneksi backend untuk koneksi frontend sebanyak mungkin. Ini disebut multiplexing koneksi. Detailnya bergantung pada lalu lintas persis yang harus ditanganinya. Setiap transaksi terbuka harus ditangani dalam koneksi yang sama. Jika ada semacam variabel lokal yang ditentukan, koneksi ini tidak dapat digunakan kembali. Mampu menggunakan kembali koneksi backend tunggal dengan beberapa koneksi frontend mengurangi beban database backend secara signifikan.
Setelah koneksi dibuat ke ProxySQL, seperti yang kami sebutkan sebelumnya, koneksi akan diproses sesuai dengan aturan kueri. Di sini pembentukan lalu lintas dapat terjadi. Mari kita lihat opsinya
Pembatasan Koneksi di ProxySQL
Pertama, lepaskan semua SELECT. Kami menjalankan "aplikasi" kami, Sysbench, dengan cara berikut:
[email protected]:~# sysbench /root/sysbench/src/lua/oltp_read_only.lua --threads=4 --events=200 --time=0 --mysql-host=10.0.0.101 --mysql-user=sbtest --mysql-password=sbtest --mysql-port=6033 --tables=32 --report-interval=1 --skip-trx=on --table-size=100000 --db-ps-mode=disable --rate=10 run
sysbench 1.1.0-bbee5d5 (using bundled LuaJIT 2.1.0-beta3)
Running the test with following options:
Number of threads: 4
Target transaction rate: 10/sec
Report intermediate results every 1 second(s)
Initializing random number generator from current time
Initializing worker threads...
Threads started!
[ 1s ] thds: 4 tps: 5.97 qps: 103.49 (r/w/o: 103.49/0.00/0.00) lat (ms,95%): 244.38 err/s: 0.00 reconn/s: 0.00
[ 1s ] queue length: 0, concurrency: 4
[ 2s ] thds: 4 tps: 13.02 qps: 181.32 (r/w/o: 181.32/0.00/0.00) lat (ms,95%): 580.02 err/s: 0.00 reconn/s: 0.00
[ 2s ] queue length: 5, concurrency: 4
[ 3s ] thds: 4 tps: 14.99 qps: 228.81 (r/w/o: 228.81/0.00/0.00) lat (ms,95%): 669.89 err/s: 0.00 reconn/s: 0.00
[ 3s ] queue length: 1, concurrency: 4
[ 4s ] thds: 4 tps: 16.99 qps: 232.88 (r/w/o: 232.88/0.00/0.00) lat (ms,95%): 350.33 err/s: 0.00 reconn/s: 0.00
[ 4s ] queue length: 0, concurrency: 3
[ 5s ] thds: 4 tps: 8.99 qps: 99.91 (r/w/o: 99.91/0.00/0.00) lat (ms,95%): 369.77 err/s: 0.00 reconn/s: 0.00
[ 5s ] queue length: 0, concurrency: 1
[ 6s ] thds: 4 tps: 3.99 qps: 55.81 (r/w/o: 55.81/0.00/0.00) lat (ms,95%): 147.61 err/s: 0.00 reconn/s: 0.00
[ 6s ] queue length: 0, concurrency: 1
[ 7s ] thds: 4 tps: 11.06 qps: 162.89 (r/w/o: 162.89/0.00/0.00) lat (ms,95%): 173.58 err/s: 0.00 reconn/s: 0.00
[ 7s ] queue length: 0, concurrency: 2
[ 8s ] thds: 4 tps: 7.99 qps: 112.88 (r/w/o: 112.88/0.00/0.00) lat (ms,95%): 200.47 err/s: 0.00 reconn/s: 0.00
[ 8s ] queue length: 0, concurrency: 2
[ 9s ] thds: 4 tps: 9.01 qps: 110.09 (r/w/o: 110.09/0.00/0.00) lat (ms,95%): 71.83 err/s: 0.00 reconn/s: 0.00
[ 9s ] queue length: 0, concurrency: 0
[ 10s ] thds: 4 tps: 9.99 qps: 143.87 (r/w/o: 143.87/0.00/0.00) lat (ms,95%): 153.02 err/s: 0.00 reconn/s: 0.00
[ 10s ] queue length: 0, concurrency: 1
[ 11s ] thds: 4 tps: 12.02 qps: 177.28 (r/w/o: 177.28/0.00/0.00) lat (ms,95%): 170.48 err/s: 0.00 reconn/s: 0.00
[ 11s ] queue length: 0, concurrency: 1
[ 12s ] thds: 4 tps: 5.00 qps: 70.95 (r/w/o: 70.95/0.00/0.00) lat (ms,95%): 231.53 err/s: 0.00 reconn/s: 0.00
[ 12s ] queue length: 0, concurrency: 2
[ 13s ] thds: 4 tps: 10.00 qps: 137.01 (r/w/o: 137.01/0.00/0.00) lat (ms,95%): 223.34 err/s: 0.00 reconn/s: 0.00
[ 13s ] queue length: 0, concurrency: 1
[ 14s ] thds: 4 tps: 11.01 qps: 143.14 (r/w/o: 143.14/0.00/0.00) lat (ms,95%): 130.13 err/s: 0.00 reconn/s: 0.00
[ 14s ] queue length: 0, concurrency: 0
[ 15s ] thds: 4 tps: 5.00 qps: 100.99 (r/w/o: 100.99/0.00/0.00) lat (ms,95%): 297.92 err/s: 0.00 reconn/s: 0.00
[ 15s ] queue length: 0, concurrency: 4
[ 16s ] thds: 4 tps: 10.98 qps: 122.82 (r/w/o: 122.82/0.00/0.00) lat (ms,95%): 344.08 err/s: 0.00 reconn/s: 0.00
[ 16s ] queue length: 0, concurrency: 0
[ 17s ] thds: 4 tps: 3.00 qps: 59.01 (r/w/o: 59.01/0.00/0.00) lat (ms,95%): 287.38 err/s: 0.00 reconn/s: 0.00
[ 17s ] queue length: 0, concurrency: 2
[ 18s ] thds: 4 tps: 13.01 qps: 165.14 (r/w/o: 165.14/0.00/0.00) lat (ms,95%): 173.58 err/s: 0.00 reconn/s: 0.00
[ 18s ] queue length: 0, concurrency: 0
[ 19s ] thds: 4 tps: 6.99 qps: 98.79 (r/w/o: 98.79/0.00/0.00) lat (ms,95%): 253.35 err/s: 0.00 reconn/s: 0.00
[ 19s ] queue length: 0, concurrency: 1
[ 20s ] thds: 4 tps: 9.98 qps: 164.60 (r/w/o: 164.60/0.00/0.00) lat (ms,95%): 590.56 err/s: 0.00 reconn/s: 0.00
[ 20s ] queue length: 0, concurrency: 3
SQL statistics:
queries performed:
read: 2800
write: 0
other: 0
total: 2800
transactions: 200 (9.64 per sec.)
queries: 2800 (134.89 per sec.)
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)
Throughput:
events/s (eps): 9.6352
time elapsed: 20.7573s
total number of events: 200
Latency (ms):
min: 44.36
avg: 202.66
max: 726.59
95th percentile: 590.56
sum: 40531.73
Threads fairness:
events (avg/stddev): 50.0000/0.71
execution time (avg/stddev): 10.1329/0.05
Ini adalah lalu lintas baca-saja, rata-rata dalam 10 transaksi (140 kueri) per detik. Karena itu hanya SELECT, kita dapat dengan mudah memodifikasi salah satu aturan kueri yang ada dan memblokir lalu lintas:
Ini akan mengakibatkan kesalahan berikut di sisi aplikasi:
[email protected]:~# sysbench /root/sysbench/src/lua/oltp_read_only.lua --threads=4 --events=200 --time=0 --mysql-host=10.0.0.101 --mysql-user=sbtest --mysql-password=sbtest --mysql-port=6033 --tables=32 --report-interval=1 --skip-trx=on --table-size=100000 --db-ps-mode=disable --rate=10 run
sysbench 1.1.0-bbee5d5 (using bundled LuaJIT 2.1.0-beta3)
Running the test with following options:
Number of threads: 4
Target transaction rate: 10/sec
Report intermediate results every 1 second(s)
Initializing random number generator from current time
Initializing worker threads...
Threads started!
FATAL: mysql_drv_query() returned error 1148 (SELECT queries are not allowed!!!) for query 'SELECT c FROM sbtest25 WHERE id=83384'
FATAL: `thread_run' function failed: /usr/local/share/sysbench/oltp_common.lua:426: SQL error, errno = 1148, state = '42000': SELECT queries are not allowed!!!
Sekarang, ini jelas keras. Kami bisa lebih sopan dan hanya meningkatkan penundaan untuk kueri SELECT.
Ini, jelas, memengaruhi kinerja kueri saat 10 milidetik ditambahkan untuk setiap SELECT yang dieksekusi.
SQL statistics:
queries performed:
read: 2800
write: 0
other: 0
total: 2800
transactions: 200 (5.60 per sec.)
queries: 2800 (78.44 per sec.)
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)
Throughput:
events/s (eps): 5.6030
time elapsed: 35.6952s
total number of events: 200
Latency (ms):
min: 622.04
avg: 7957.01
max: 18808.60
95th percentile: 15934.78
sum: 1591401.12
Threads fairness:
events (avg/stddev): 50.0000/36.01
execution time (avg/stddev): 397.8503/271.50
Kami menyiapkan penundaan untuk setiap kueri SELECT, yang tidak selalu masuk akal selain menunjukkan bahwa Anda dapat melakukannya. Biasanya Anda ingin menggunakan penundaan pada beberapa kueri yang menyinggung. Katakanlah kita memiliki kueri yang sangat berat dan menambah beban yang signifikan pada CPU database. Yang lebih buruk, itu telah diperkenalkan oleh perubahan kode baru-baru ini dan itu berasal dari semua host aplikasi. Tentu, Anda dapat menunggu pengembang untuk mengembalikan perubahan atau mendorong perbaikan, tetapi dengan ProxySQL Anda dapat mengambil kendali di tangan Anda sendiri dan memblokir kueri atau mengurangi dampaknya bahkan cukup signifikan.
Mari kita asumsikan bahwa database kita berjalan dengan baik saat bel alarm mulai berdering.
Tinjau cepat pada metrik memberi tahu kita bahwa jumlah kueri yang dijalankan oleh ProxySQL turun sementara pemanfaatan CPU naik. Kita dapat melihat Kueri Teratas di ProxySQL untuk melihat apakah kita dapat melihat sesuatu yang tidak biasa.
Memang tidak biasa - kueri baru yang bukan bagian dari campuran kueri reguler yang kami amati di sistem kami. Kita dapat menggunakan opsi untuk membuat aturan kueri.
Kami akan menambahkan penundaan 50 detik ke kueri dengan menyetel Penundaan ke 50000 ms.
Kami dapat mengonfirmasi bahwa aturan kueri sedang digunakan dan kueri sedang digunakan .
Setelah beberapa saat kami juga dapat melihat bahwa beban turun dan nomor kueri yang dieksekusi lagi dalam kisaran yang diharapkan. Tentu saja, alih-alih menambahkan penundaan ke kueri, kami cukup memblokirnya. Itu akan lebih mudah bagi kami untuk menyelesaikannya, tetapi memblokir kueri secara total dapat berdampak signifikan pada aplikasi.
Kami berharap posting blog singkat ini memberi Anda beberapa wawasan tentang bagaimana ProxySQL dapat membantu Anda membentuk lalu lintas dan mengurangi kinerja yang dicapai oleh kueri yang tidak terkendali.