Panduan Pasukan Lucee MY

Tala connection pool pangkalan data dalam Lucee

Menala connection pool Lucee: had sambungan, timeout, gejala kebocoran sambungan, dan cara mengukur kesannya dengan query sebenar di rig tanpa meneka.

Tala connection pool pangkalan data dalam Lucee
0
Kandungan

Tala connection pool pangkalan data dalam Lucee

Setiap pertanyaan CFML memerlukan sambungan ke pangkalan data, dan membuka sambungan baharu itu perlahan kerana ia melibatkan handshake TCP, pengesahan dan peruntukan memori di kedua-dua belah. Lucee menyelesaikan masalah ini dengan connection pool, iaitu sekumpulan sambungan yang dibuka sekali lalu dipakai semula. Masalah sebenar bermula apabila tetapan kolam itu salah: had terlalu tinggi membenarkan MySQL anda ditenggelamkan, manakala had terlalu rendah membuat permintaan beratur menunggu sambungan. Artikel ini menunjukkan cara menala dua tetapan utama iaitu connectionLimit dan connectionTimeout, serta cara membaca bilangan sambungan aktif sebenar daripada MySQL supaya anda menala berdasarkan ukuran dan bukan tekaan.

Apa itu connection pool

Lucee menggunakan Apache Commons Pool 2 untuk mengurus sambungan pangkalan data. Apabila pertanyaan dijalankan, Lucee meminta sambungan daripada kolam, menjalankan pertanyaan itu, lalu memulangkan sambungan ke kolam supaya pertanyaan seterusnya boleh memakainya semula. Sambungan kekal terbuka dan tersedia, jadi kos membuka sambungan baharu dibayar sekali sahaja dan bukan pada setiap pertanyaan.

Lucee mengenali tiga corak sambungan. Corak lalai ialah sambungan berkongsi, yang dikongsi merentasi permintaan dan dipulangkan selepas setiap pertanyaan. Corak kedua ialah sambungan eksklusif melalui requestExclusive, yang memberikan satu sambungan khusus untuk keseluruhan satu permintaan. Corak ketiga ialah sambungan transaksi, yang menjadi eksklusif secara automatik semasa blok cftransaction. Kebanyakan aplikasi hanya memerlukan corak lalai. Panduan menyambung Lucee ke MySQL menerangkan penubuhan datasource asas, dan artikel ini menyambung terus ke penalaan kolamnya.

connectionLimit: had sambungan serentak

connectionLimit menetapkan bilangan maksimum sambungan yang dibuka Lucee untuk sesebuah datasource pada satu masa. Lalainya ialah -1, yang bermaksud tanpa had: Lucee membuka sambungan sebanyak permintaan serentak yang tiba. Dalam praktiknya MySQL sendiri menjadi siling, kerana nilai max_connections lalai MySQL 8 ialah 151.

Nilai -1 ini mudah tetapi berbahaya. Apabila aplikasi menerima lonjakan trafik, Lucee membuka sambungan baharu tanpa sekatan sehingga MySQL menolak sambungan seterusnya dengan ralat too many connections. Pada masa itu aplikasi sudah separa lumpuh, bukan kerana pertanyaan lambat tetapi kerana tiada sambungan tinggal. Menetapkan had yang munasabah, contohnya 20 atau 30, memaksa aplikasi beratur dengan tertib apabila kolam penuh dan bukannya menolak pangkalan data ke tepi tebing.

connectionTimeout: masa sambungan terbiar

connectionTimeout menetapkan berapa lama, dalam minit, sesebuah sambungan dibenarkan duduk terbiar dalam kolam sebelum Lucee menutupnya. Lalainya ialah 1 minit, dan nilai 0 bermaksud tanpa had. Perhatikan unitnya: ia minit, bukan saat, dan ini antara kesilapan paling kerap apabila orang menyalin tetapan dari ingatan.

Tetapan ini penting untuk trafik yang tidak sekata. Jika aplikasi sibuk, sambungan dipakai semula sebelum sempat terbiar satu minit, jadi ia kekal hidup. Jika trafik sunyi, sambungan yang terbiar ditutup dan memori dibebaskan. Menetapkan nilai terlalu besar, contohnya 60 minit, mengekalkan sambungan terbiar yang tidak diperlukan dan membazir slot sambungan di MySQL, manakala nilai 0 bermakna sambungan terbiar tidak pernah ditutup secara automatik.

Kenapa had terlalu tinggi memudaratkan

Setiap sambungan bukan percuma. Di sebelah Lucee, setiap sambungan memegang objek Java dan penimbal dalam memori JVM. Di sebelah MySQL, setiap sambungan memegang satu thread, dan thread yang tidak aktif tetap memakan memori. Sambungan yang berlebihan kelihatan dalam SHOW PROCESSLIST sebagai baris berkeadaan Sleep, iaitu sambungan terbuka tetapi tidak melakukan apa-apa.

Apabila kolam tanpa had dan aplikasi membuka sambungan lebih pantas daripada ia menutup, kesannya menjalar ke seluruh pelayan: memori JVM membengkak dan boleh mencetuskan masalah yang diterangkan dalam panduan menangani Lucee out of memory, manakala MySQL kehabisan sambungan dan menolak pertanyaan baharu. Had yang munasabah bukan sekatan prestasi; ia pagar yang melindungi pangkalan data daripada aplikasi sendiri.

TetapanMaksudLalaiUnit
connectionLimitBilangan maksimum sambungan serentak-1 (tanpa had)bilangan
connectionTimeoutMasa sambungan terbiar sebelum ditutup1minit
requestExclusiveSambungan khusus untuk satu permintaanfalseboolean
validateSahkan sambungan sebelum dipakaifalseboolean

Gejala kebocoran sambungan

Kebocoran sambungan berlaku apabila sambungan diambil dari kolam tetapi tidak dipulangkan. Tiga punca paling biasa ialah pertanyaan yang tidak ditutup, transaksi yang digantung, dan pengecualian yang melemparkan keluar dari blok cftransaction tanpa rollback.

Pertanyaan yang tidak ditutup berlaku apabila hasil dibiarkan mengalir tanpa dibaca habis, jadi sambungan dianggap masih digunakan. Transaksi digantung berlaku apabila cftransaction dibuka tetapi kod di dalamnya tersekat menunggu sesuatu, contohnya panggilan HTTP luar, sambil memegang sambungan eksklusif sepanjang tempoh itu. Pengecualian dalam cftransaction pula berbahaya kerana jika tiada rollback, sambungan kekal dalam keadaan autocommit dimatikan dan tidak dapat dipulangkan dengan bersih.

Gejala yang boleh diukur ialah Threads_connected yang naik tetapi tidak pernah turun, dan bilangan baris Sleep yang bertambah. Lama-kelamaan aplikasi melempar ralat tidak dapat memperoleh sambungan, dan panduan memantau log Lucee membantu mengesan titik permulaannya.

Membaca bilangan sambungan aktif dari MySQL

MySQL menyimpan kaunter sambungan dalam pemboleh ubah status, dan anda boleh membacanya terus dari CFML melalui datasource yang sama. Dua kaunter paling berguna ialah Threads_connected untuk bilangan sambungan yang sedang terbuka, dan Max_used_connections untuk nilai tertinggi yang pernah dicapai sejak MySQL dimulakan:

<cfscript>
    aktif = queryExecute("SHOW STATUS LIKE 'Threads_connected'", [], {datasource: "kedai"});
    paling = queryExecute("SHOW STATUS LIKE 'Max_used_connections'", [], {datasource: "kedai"});
    writeOutput("Sambungan aktif sekarang: " & aktif.Value[1] & "<br>");
    writeOutput("Paling tinggi pernah dicapai: " & paling.Value[1]);
</cfscript>

Untuk melihat setiap sambungan secara individu, gunakan SHOW PROCESSLIST. Ruangan Command menunjukkan apa yang sedang dilakukan oleh sambungan itu, dan baris berkeadaan Sleep ialah sambungan terbiar dalam kolam:

<cfscript>
    proses = queryExecute("SHOW PROCESSLIST", [], {datasource: "kedai"});
    writeOutput("Jumlah sambungan: " & proses.recordCount & "<br>");
    for (baris in proses) {
        writeOutput("ID " & baris.Id & " -> " & baris.Command & " (" & baris.State & ")<br>");
    }
</cfscript>

Konfigurasi datasource dalam Application.cfc

Datasource boleh ditakrifkan terus dalam Application.cfc, dan inilah tempat paling kemas untuk menetapkan connectionLimit dan connectionTimeout supaya ia dikomit bersama kod. Blok berikut ialah contoh untuk datasource kedai dengan had 20 sambungan dan masa terbiar 5 minit:

component {
    this.name = "kedaiApp";

    this.datasources["kedai"] = {
        class: "com.mysql.cj.jdbc.Driver",
        connectionString: "jdbc:mysql://localhost:3306/kedai?useUnicode=true&characterEncoding=UTF-8&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC",
        username: "kod",
        password: "kod123",
        connectionLimit: 20,
        connectionTimeout: 5
    };
}

Blok di atas memerlukan mula semula aplikasi atau penyahkodan semula Application.cfc sebelum tetapan baharu berkuat kuasa, kerana datasource dibaca semasa permulaan aplikasi dan bukan pada setiap permintaan. Butiran penuh cara datasource dibina dan dibaca ada dalam panduan konfigurasi datasource.

Cara mengulang ujian

Penalaan tanpa pengukuran ialah tekaan. Cara paling mudah untuk mengesahkan bahawa tetapan anda berkesan ialah menjalankan sekumpulan pertanyaan dan membandingkan Threads_connected sebelum dan selepas. Dalam contoh ini, 25 pertanyaan dijalankan berturut-turut, dan anda akan melihat bahawa bilangan sambungan aktif hampir tidak berubah, kerana kolam memakai semula sambungan yang sama:

<cfscript>
    sebelum = queryExecute("SHOW STATUS LIKE 'Threads_connected'", [], {datasource: "kedai"});

    for (i = 1; i <= 25; i++) {
        queryExecute("SELECT 1", [], {datasource: "kedai"});
    }

    selepas = queryExecute("SHOW STATUS LIKE 'Threads_connected'", [], {datasource: "kedai"});
    writeOutput("Sebelum beban: " & sebelum.Value[1] & "<br>");
    writeOutput("Selepas beban: " & selepas.Value[1]);
</cfscript>

Untuk menguji di bawah beban serentak yang sebenar, dan bukan sekadar pertanyaan berurutan, panduan ujian beban CFML menunjukkan cara menjana permintaan selari dan membaca kesannya terhadap kolam.

Soalan Lazim

Apakah connection pool dalam Lucee?

Connection pool ialah sekumpulan sambungan pangkalan data yang dibuka sekali dan dipakai semula merentasi pertanyaan. Lucee menguruskannya melalui Apache Commons Pool 2, jadi pertanyaan tidak perlu membuka sambungan TCP baharu setiap kali dijalankan.

Apakah maksud connectionLimit dan nilai lalainya?

connectionLimit menetapkan bilangan maksimum sambungan serentak untuk sesebuah datasource. Lalainya ialah -1, yang bermaksud tanpa had, jadi Lucee membuka sambungan mengikut permintaan sehingga MySQL sendiri mencapai had max_connections.

Dalam unit apakah connectionTimeout diukur?

connectionTimeout diukur dalam minit, bukan saat, dan lalainya ialah 1 minit. Ia menetapkan berapa lama sambungan terbiar dibenarkan duduk dalam kolam sebelum ditutup, dan nilai 0 bermaksud tanpa had.

Bagaimana saya tahu sambungan saya bocor?

Baca Threads_connected dan SHOW PROCESSLIST. Jika bilangan sambungan aktif naik dan tidak turun selepas beban reda, atau baris berkeadaan Sleep bertambah tanpa henti, kemungkinan besar ada sambungan yang tidak dipulangkan, selalunya daripada transaksi yang digantung atau pengecualian tanpa rollback.

Kenapa pertanyaan saya dapat ralat tidak dapat sambungan?

Ralat itu biasanya bermaksud kolam telah habis, iaitu semua sambungan sedang digunakan dan tiada yang dipulangkan. Semak sama ada connectionLimit terlalu rendah, sama ada transaksi memegang sambungan terlalu lama, atau sama ada ada kebocoran sambungan. Periksa juga panduan ralat datasource not found untuk membezakan punca ralat yang berbeza.

Sumber

0 komen

0 komen

Log masuk untuk menjawab atau memberi komen.

Log masuk