C++ (17+) için thread-safe, yüksek performanslı PostgreSQL Connection Pooling kütüphanesi


    Github Repository: https://github.com/leventkaragol/libcpp-pg-pool

    linux windows

    Amaç

    Yüksek trafikli ve multi-threaded uygulamaların temel zorluklarından biri, veritabanı kaynaklarını verimli ve güvenli bir şekilde yönetmektir. Her bir veritabanı operasyonu için yeniden bağlantı kurmak, hem ciddi bir latency maliyeti yaratır, hem de sunucu üzerinde bir performans darboğazına neden olur. libcpp-pg-pool, bu kritik soruna yönelik, PostgreSQL için özel olarak tasarlanmış, hem thread-safe hem de yüksek performanslı bir connection pool kütüphanesidir. Kütüphanenin temel amacı, maliyetli bağlantı oluşturma işlemlerini en aza indirerek, hazırda bekleyen bir bağlantı havuzunu birden çok thread arasında güvenli bir şekilde paylaştırmaktır.

    Projeye Nasıl Eklenir?

    Bu header-only bir kütüphanedir. Yani aslında tek yapmanız gereken src klasöründeki libcpp-pg-pool.hpp dosyasını projenize eklemek ve #include ile kullanmaya başlamaktır.

    Ancak bu kütüphane, arka planda libpqxx kütüphanesini kullanır. Dolayısıyla, kullanmadan önce projenize libpqxx kütüphanesini eklemeniz gerekir.

    Kullanım örneklerini Github Repository'deki "examples" klasöründe bulabilirsiniz. Aşağıda örnek bir CMakeLists.txt dosyası içeriği de bulabilirsiniz.

    cmake_minimum_required(VERSION 3.14)
    
    project(myProject)
    
    find_package(libpqxx CONFIG REQUIRED)
    
    add_executable(myProject main.cpp libcpp-pg-pool.hpp)
    
    target_link_libraries(myProject PRIVATE libpqxx::pqxx)
    

    Nasıl Kullanılır? (En Basit Haliyle)

    Yeni bir bağlantı elde etmek için "acquire" metodunu kullanabilirsiniz. "acquire" metodundan döndürülen değer bir Shared Pointer'dır ve bağlantı kapsam dışına çıktığı anda otomatik olarak havuza geri döndürülür. Bu nedenle, bağlantıyı manuel olarak kapatmanıza gerek yoktur.

    Dikkat!
    Bağlantı Havuzu uygulamada yalnızca bir kez oluşturulmalıdır. Havuz boyutuna bağlı olarak hazır olması 1 saniyeye kadar sürebilir.
    #include "libcpp-pg-pool.hpp"
    
    using namespace lklibs;
    
    int main() {
    
        const auto connectionString = "dbname=my_db user=my_user password=my_password host=localhost port=5432";
    
        // Bağlantı havuzu boyutunu isteğe bağlı olarak belirtebilirsiniz, ancak belirtmezseniz varsayılan değer 100 olacaktır
        PgPool pool(connectionString, 10);
    
    
        {
            // Havuzdan bir bağlantı alın
            const auto dbConnection = pool.acquire();
    
            pqxx::work txn(*dbConnection);
    
            const auto result = txn.exec("SELECT * FROM my_table");
    
            for (const auto& row : result)
            {
                std::cout << row[0].c_str() << std::endl;
            }
        }
    
        // dbConnection kapsam dışına çıktığında bağlantı otomatik olarak havuza geri döndürülür
        // Bu sayede bağlantıyı manuel olarak kapatmanıza gerek kalmaz
    
        return 0;
    }
    
    Dikkat!
    Bağlantı havuzu boyutu PostgreSQL'in max_connections sınırını aşmamalıdır, aksi takdirde "too many clients" gibi bir hata alırsınız

    Paylaşımlı Bağlantılar

    "acquire" metodundan dönen değer, bir Shared Pointer'dır ve paylaşılan referansları sayar. Bir bağlantı açıp başka bir sınıfla paylaştığınızda, eldeki bağlantı nesnesi kapsam dışına çıksa bile, son paylaşılan sınıf nesnesi yok edilene kadar bağlantı açık kalır.

    #include "libcpp-pg-pool.hpp"
    
    using namespace lklibs;
    
    class SampleConsumer
    {
    public:
        void setDbConnection(std::shared_ptr<pqxx::connection> dbConnection)
        {
            this->dbConnection = std::move(dbConnection);
        }
    
        void queryData() const
        {
            pqxx::work txn(*dbConnection);
    
            const auto result = txn.exec("SELECT * FROM my_table");
    
            for (const auto& row : result)
            {
                std::cout << row[0].c_str() << std::endl;
            }
        }
    
        [[nodiscard]] bool isConnectionOpen() const
        {
            return dbConnection->is_open();
        }
    
    private:
        std::shared_ptr<pqxx::connection> dbConnection;
    };
    
    int main() {
    
        const auto connectionString = "dbname=my_db user=my_user password=my_password host=localhost port=5432";
    
        PgPool pool(connectionString);
    
    
        {
            SampleConsumer myConsumer{};
    
            {
                // Havuzdan bir bağlantı alın
                const auto dbConnection = pool.acquire();
    
                // Bağlantı SampleConsumer ile paylaşıldı
                myConsumer.setDbConnection(dbConnection);
    
                myConsumer.queryData();
            }
    
            // dbConnection kapsam dışına çıktıktan sonra bile bağlantı hala canlı kalır çünkü SampleConsumer hala shared_ptr'yi tutuyor
    
            std::cout << "Connection status:" << myConsumer.isConnectionOpen() << std::endl;
        }
    
        // Bağlantıyı tutan tüm shared_ptr'ler kapsam dışına çıktığında bağlantı otomatik olarak havuza geri döndürülür
    
        return 0;
    

    Semantik Versiyonlama

    Kütüphanenin sürümlemesi, geleneksel semantik versiyonlama kullanılarak yapılır. Buna göre, MAJOR.MINOR.PATCH biçiminde yapılan sürümlemede;

    PATCH: Olası hata düzeltmeleri ve iyileştirmeleri içerir. Bunu mutlaka edinmek istersiniz.

    MINOR: Geriye dönük uyumluluk sayesinde eklenen ek işlevler. Muhtemelen bunu edinmek istersiniz, zararı olmaz.

    MAJOR: Geriye dönük uyumluluğu bozan ek işlevler. Nelerin değiştiğini anlamanız ve muhtemelen kendi kodunuzda değişiklik yapmanız gerekecek. Böyle bir şey yayınlarsam, geçiş için gereken değişiklikleri kesinlikle dokümana eklerim.

    Lisans

    Proje MIT lisansı ile lisanslanmıştır. Ticari kullanıma uygundur. Tam metni aşağıda bulabilirsiniz.

    MIT License
    
    Copyright (c) 2024 Levent KARAGÖL
    
    Permission is hereby granted, free of charge, to any person obtaining a copy of this
    software and associated documentation files (the "Software"), to deal in the Software
    without restriction, including without limitation the rights to use, copy, modify,
    merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
    permit persons to whom the Software is furnished to do so, subject to the following conditions:
    
    The above copyright notice and this permission notice shall be included in all copies
    or substantial portions of the Software.
    
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
    INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
    PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
    FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
    

    İletişim

    Kütüphaneyle ilgili sorun yaşıyorsanız, lütfen GitHub'da bir konu açın. Lütfen isteğinizi, sorununuzu veya sorunuzu olabildiğince ayrıntılı bir şekilde açıklayın ve derleyicinizin, işletim sisteminizin ve kullandığınız kütüphanenin sürümünü de belirtin. Yeni bir konu açmadan önce, lütfen konunun daha önce kapatılmış konularda bulunmadığından emin olun.

    Yazar: Levent KARAGÖL

    Makaleyi Paylaş: