PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Kelola Pengumpulan Koneksi di aplikasi web multi-penyewa dengan Spring, Hibernate, dan C3P0

Anda dapat memilih di antara 3 strategi berbeda yang akan memengaruhi polling koneksi. Bagaimanapun, Anda harus menyediakan implementasi MultiTenantConnectionProvider . Strategi yang Anda pilih tentu saja akan memengaruhi implementasi Anda.

Komentar umum tentang MultiTenantConnectionProvider.getAnyConnection()

getAnyConnection() diperlukan oleh hibernasi untuk mengumpulkan metadata dan menyiapkan SessionFactory. Biasanya dalam arsitektur multi-penyewa Anda memiliki database khusus/master (atau skema) yang tidak digunakan oleh penyewa mana pun. Ini semacam database template (atau skema). Tidak masalah jika metode ini mengembalikan koneksi ke database (atau skema) ini.

Strategi 1 :setiap penyewa memiliki database sendiri. (dan itulah kumpulan koneksinya sendiri)

Dalam hal ini, setiap penyewa memiliki kumpulan koneksi sendiri yang dikelola oleh C3PO dan Anda dapat memberikan implementasi MultiTenantConnectionProvider berdasarkan AbstractMultiTenantConnectionProvider

Setiap penyewa memiliki C3P0ConnectionProvider sendiri , jadi yang harus Anda lakukan di selectConnectionProvider(tenantIdentifier) adalah mengembalikan yang benar. Anda dapat menyimpan Peta untuk menyimpannya di cache dan Anda dapat dengan malas menginisialisasi C3POConnectionProvider dengan sesuatu seperti :

private ConnectionProvider lazyInit(String tenantIdentifier){
    C3P0ConnectionProvider connectionProvider = new C3P0ConnectionProvider();
    connectionProvider.configure(getC3POProperties(tenantIdentifier));
    return connectionProvider;
}

private Map getC3POProperties(String tenantIdentifier){
    // here you have to get the default hibernate and c3po config properties 
    // from a file or from Spring application context (there are good chances
    // that those default  properties point to the special/master database) 
    // and alter them so that the datasource point to the tenant database
    // i.e. : change the property hibernate.connection.url 
    // (and any other tenant specific property in your architecture like :
    //     hibernate.connection.username=tenantIdentifier
    //     hibernate.connection.password=...
    //     ...) 
}

Strategi 2 :setiap tenant memiliki skemanya sendiri dan kumpulan koneksinya sendiri dalam satu database

Kasus ini sangat mirip dengan strategi pertama mengenai ConnectionProvider implementasi karena Anda juga dapat menggunakan AbstractMultiTenantConnectionProvider sebagai kelas dasar untuk mengimplementasikan MultiTenantConnectionProvider . Anda

Implementasinya sangat mirip dengan implementasi yang disarankan untuk Strategi 1 kecuali bahwa Anda harus mengubah skema alih-alih database dalam konfigurasi c3po

Strategi 3 :setiap penyewa memiliki skemanya sendiri dalam satu database tetapi menggunakan kumpulan koneksi bersama

Kasus ini sedikit berbeda karena setiap penyewa akan menggunakan penyedia koneksi yang sama (sehingga kumpulan koneksi akan dibagikan). Dalam hal :penyedia koneksi harus mengatur skema untuk digunakan sebelum penggunaan koneksi apa pun. yaitu Anda harus mengimplementasikan MultiTenantConnectionProvider.getConnection(String tenantIdentifier) (yaitu implementasi default yang disediakan oleh AbstractMultiTenantConnectionProvider tidak akan berfungsi).

Dengan postgresql Anda dapat melakukannya dengan :

 SET search_path to <schema_name_for_tenant>;

atau menggunakan alias

 SET schema <schema_name_for_tenant>;

Jadi inilah yang getConnection(tenant_identifier); your Anda akan terlihat seperti:

@Override
public Connection getConnection(String tenantIdentifier) throws SQLException {
    final Connection connection = getAnyConnection();
    try {
        connection.createStatement().execute( "SET search_path TO " + tenanantIdentifier );
    }
    catch ( SQLException e ) {
        throw new HibernateException(
                "Could not alter JDBC connection to specified schema [" +
                        tenantIdentifier + "]",
                e
        );
    }
    return connection;
}

Referensi yang berguna ada di sini (dokumen resmi)

Tautan bermanfaat lainnya C3POConnectionProvider.java

Anda dapat menggabungkan strategi 1 dan strategi 2 dalam implementasi Anda. Anda hanya perlu cara untuk menemukan properti koneksi/url koneksi yang benar untuk penyewa saat ini.

EDIT

Saya pikir pilihan antara strategi 2 atau 3 tergantung pada lalu lintas dan jumlah penyewa di aplikasi Anda. Dengan kumpulan koneksi terpisah :jumlah koneksi yang tersedia untuk satu penyewa akan jauh lebih rendah dan demikian:jika untuk beberapa alasan yang sah satu penyewa tiba-tiba membutuhkan banyak koneksi, kinerja yang dilihat oleh penyewa tertentu ini akan menurun secara drastis (sementara penyewa lainnya tidak akan terkena dampak).

Di sisi lain, dengan strategi 3, jika karena alasan yang sah satu penyewa tiba-tiba membutuhkan banyak koneksi:kinerja yang dilihat oleh setiap penyewa akan menurun.

Secara umum, saya pikir strategi 2 lebih fleksibel dan aman:setiap penyewa tidak dapat mengkonsumsi lebih dari jumlah koneksi yang diberikan (dan jumlah ini dapat dikonfigurasi per penyewa jika Anda membutuhkannya)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cara menggunakan array_agg() untuk varchar[]

  2. Membandingkan Kinerja &Harga PostgreSQL DigitalOcean – ScaleGrid vs. Database yang Dikelola DigitalOcean

  3. sqlalchemy.exc.NoSuchModuleError:Tidak dapat memuat plugin:sqlalchemy.dialects:postgres

  4. Postgres - FATAL:file database tidak kompatibel dengan server

  5. Migrasi Rails:Bigint di PostgreSQL tampaknya gagal?