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)