PgBouncer kullanımı
Mar 18, 2018 · 3 minute read · CommentsProgrammingLinux
Connection Pooling Nedir?
Connection Pooling kısaca DB bağlantılarını cacheleyip, gelen yeni bağlantılarda varolan DB bağlantısını kullananmaktır diyebiliriz. Bu sayede her seferinde yeni bir bağlantı açmaktan ötürü doğan zaman ve memory kaybınını azaltabiliriz.
Normal bir web uygulamasında kullanıcı sisteme bir istek gönderdiğinde bir DB connection açılır ve response kullanıcıya gönderilene kadar DB connection açık kalır. Eğer DBnin connection limitinin 100 olduğunu varsayarsak anlık aynı anda sadece 100 kullanıcı DB connection kurabilir. 101. kişi uygulamaya istek gönderdiğinde uygulama DB bağlantısı açmak isteyecek fakat DB connection limiti dolduğu için yeni bağlantıyı drop edecektir. Bundan kurtulmanın en basit yöntemi DB connection limitlerini artırmaktır. Diğer bir yöntem ise PgBouncer gibi bir connection pooling aracı kullanmaktır. DB connection limitlerini artırmak en kolay yöntemdir fakat gerçek bir Postgresql DB connection açmak PgBouncer’a göre daha maliyetli bir çözümdür. Postgresql bir connectioni handle edebilmek için bir kaç MB memory kullanırken PgBouncer sadece 2KB memory kullanır[1]. Ayrıca normal DB connection açmak süre bakımından da PgBouncer’a göre daha fazla zaman alır.
PgBouncer kullandığımız durumda uygulamamız direk DBye bağlanmak yerine PgBouncer’a bağlanır. DBye connectioni sadece PgBouncer kurar ve bir DB connectionı üzerinden birden fazla kullanıcı için sorgu çalıştırabilir. Yazının devamında bunu daha iyi anlayacaksınız.
PgBouncer kullanılmadığı durumda kullanıcı uygulamaya bir request gönderdiğinde uygulamamız ilk DB’ye connection kurar ve response dönene kadar db connection’ı bloke eder. Uygulama tarafında bir hesaplama yapılıyor olsa bile kullanıcıya response dönene kadar db connection açık kalacaktır. Buda uygulamız yoğun kullanıldığı durumda DB connection limitine ulaşacak ve uygulamamız artık kullanıcıları karşılayamayacak duruma gelecektir.
Bazı PgBouncer terimleri:
Server
: Postgresql ServerClient
: Uygulamanın PgBouncer’a yaptığı connectionın kendisi diyebiliriz. Uygulamadb.connect()
yaptığında bu connection bir client olarak tanımlanır. Uygulamadb.disconnect()
yaptığında ise client bağlantısı kesilmiş olur.Pool
: Her bir pool client’dan gelen connectionları karşılar ve clientlardan gelen sorguları sıraya sokup DB connection üzerinden çalıştırır. DB connection üzerinde çalışan aktif bir sorgu varsa gelen sorguyu bekletir.
Limitler:
- Bir Postgresql connection üzerinde anlık sadece 1 query çalıştırabilir.
- Maximum Postgresql’in connection limiti kadar pool açılabilir.
Bazı PgBouncer configleri:
pool_mode
:session
olduğunda web worker request geldiğinde PgBouncer’a bağlanır ve request bitene kadar kullandığı pool’u meşgul eder. Buda şu demek; anlık 20 request oluştuğunda 20 pool dolu olucak, ekstra gelen requestlerquery_wait_timeout
kadar bekleyecektir, bu süre içerisinde pool boşalırsa işleme alınacak, aksi taktirde connection drop edilecektir. Bunun şöyle bir dezavantajı var: uygulama PgBouncer pooluna bağlandı, bir select statement çalıştırdı ve uygulama tarafında 10 saniye boyunca işlem yaptı diyelim. Bu hesaplama süresi boyunca PgBouncer<=>DB connection’ı bloke edilir.transaction
olduğu durumda PgBouncer gelen transactionlara göre db connection’ı kullanır. Anlık 20 kullanıcı uygulamaya istek gönderse herbir web worker PgBouncer’a bağlanır. Fakat PgBouncer aynı kullanıcının bağlantısının içerisinde yer alan farklı transactionları farklı poollara gönderebilir. Bu sayedesession
‘da olduğu gibi uygulama tarafında yapılan hesaplamalar süresi boyunca PgBouncer<=>DB connection bloke edilmez. Aynı DB connection’ı 20 kullanıcı da kullanabilir. 1. kullanıcının attığı query DBde çalıştırıldıktan sonra DB connection boşalacak ve sıradaki query işleme alınacaktır.
default_pool_size
:pool_size
(Max pool size) belirtilmediği sürece kullanıcı/db eşleşmesi için maximum kaç pool açılabileceğini belirler. Meseladefault_pool_size
100 isemyuser@pghost1
için yüz adet pool olabilir. Aynı kullanıcı/db için ekstra pool açmaz.server_idle_timeout
: PgBouncer’ın DBye açtığı connection üzerinde aktif çalışan bir query kalmadığında belirtilen saniye kadar zaman geçtiğinde DB connection’ı kapatır(pool kapanır).server_life_time
: DB’de çalışan query belirtilen sürede bitmezse connection kapatılır.max_client_conn
: Bir poolun maximum kaç clientı karşılayacağını belirtir.max_client_conn
ayarını 100 olarak belirlediğimizde bir pool max 100 client(connection) karşılayacağını belirtmiş oluruz. Aynı anda 100 client PgBouncer’a bağlandığında tek bir pool(1 DB connection) bu 100 clientı handle edebilmesi mümkün. Burda şuna dikkat etmek gerek, eğer çalıştırdığımız queryler uzun zaman alıyorsa bir pool aynı anda sadece bir query çalıştırabildiğinden diğer clientlardan gelen queryler kuyrukta bekleyecektir.
PgBouncer’ın bütün configlerine buradan ulaşabilirsiniz.
Django Notları:
Django’da select statementlar da dahil olmaz üzere her bir query transaction bloğu içerisinde çalıştırılır.
[1] Postgresql ve PgBouncer connection benchmark yapmadım ama şuradan memory kullanım farkına bakabilirsiniz.