29 Temmuz 2016 Cuma

Tomcat üzerinde Connection Pool nasıl kullanılır?

Merhaba, bu yazımda Connection Pool nedir, Tomcat üzerinde nasıl connection pool oluşturulur, neden oluşturulur gibi başlıklara değineceğim.

Connection(Bağlantı) nedir?
Connection bir veritabanı üzerinde işlem yapabilmek için açtığımız bağlantıdır.

Bağlantı açarken nelere dikkat etmemiz lazım?
Kaynakların verimli kullanılması açısından DB(database) ye bağlanıp işlem yaptıktan sonra bağlantıyı kapatmamız lazım. Tüm program döngüsü boyunca ortalıkta boş boş takılan bağlantılar olmasını istemeyiz. Bu durumdada her işlem için bağlantı açmamız gerekecektir. Bağlantı açma ise biraz masraflıdır (yaklaşık 10ms), özellikle geniş trafiğe sahip sistemleri düşündüğümüzde sürekli bağlantı açma-kapama db mizi sıkıntıya sokabilir.

Peki en ideal bağlantı açma yöntemi nedir?
Connection Pool dediğimiz kavram burada devreye giriyor. Çevirisidende anlaşılacağı üzere bağlatılarımızın depolandığı bir havuz. Bu havuzun çalışma mantığıda şöyle.

  1. Tomcat serverimiz çalıştırıldığında belirtilen sayı kadar bağlantı açar. (20,30,40...)
  2. Client işlem yapmak istediğinde bağlantıları artık db den değilde tomcat üzerinden ister.
  3. İşlemi bitince bağlantıyı tekrardan havuza yollar ve kaynakların verimli kullanılmasını sağlar.

 
Bağlantı istekleri Pool üzerinden yapılır.


Anlattığım gibi server ayağa kalktığında 1 defaya mahsus olarak gerekli bağlantılar açılır ve depolanır. Sonraki erişimler yaklaşık 3ms sürecektir. Kabaca işlem başına 7ms kardayız. 

Tomcat Server üzerinden pool nasıl ayarlanır?

1. tomcat/contex.xml dosyamıza datasource tanımlaması yapılır. 


    <ResourceLink type="javax.sql.DataSource" name="jdbc/poolTest" global="jdbc/poolTest"/>
    // verdiğimiz name üzerinden erişim sağlayacağız.

2. tomcat/server.xml dosyamıza pool bilgilerini gireriz. 
// GlobalNamingResources tag ı arasına eklenecek.

 <Resource type="javax.sql.DataSource"
       auth="Container"
        name="jdbc/poolTest"
        driverClassName="com.mysql.jdbc.Driver"
       factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
        url="jdbc:mysql://127.0.0.1:3306/testDB"  // db adresimiz
        username="testUser" // db username
        password="testUser" // db password
  initialSize="10"  // standart bağlantı sayısı
        maxActive="20"  // max bağlantı sayısı
        maxIdle="10"  // max boş bağlantı sayısı
        minIdle="5"/>  // min boş bağlantı sayısı

3. Projemizin web.xml dosyasına poolu tanıtalım.

  <resource-ref>
<description>DB Connecion Pool Source</description>
<res-ref-name>jdbc/testDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

Bu eklemelerden sonra server çalıştığı esnada bağlantılar açılacaktır. 



 ** Benim Veritabanım üzerinde açık bağlantılar. Ve gördüğünüz gibi kurtlar hep uyku modunda ve atıl kurt dememizi bekliyorlar. Mysql Workbench ile bakılmıştır. İsimler değişiklik gösterebilir.

Son olarak bu bağlantıları nasıl kullancağımıza bakalım. Java projelerimizde bu bağlantıları çağırabilmek için verileri serverden okuyup bir datasource içinde tutacağız. Daha sonra bu kaynaktan bağlantılarımızı isteyip kullanabiliriz.


private Connection getConnectionFromPool() throws NamingException, SQLException {
Context envCtx = (Context) new InitialContext();
// Look up our data source
DataSource ds = (DataSource) envCtx.lookup("java:comp/env/jdbc/testDB");
Connection conn = ds.getConnection();
logger.debug("Connection taken");
return conn;
}

Son olarak bağlantılar ile işiniz bittikten sonra havuza geri göndermeyi unutmayın. conn.close() ile kapatabilirsiniz. Sonraki yazımda görüşmek üzere :D






28 Temmuz 2016 Perşembe

JVM Classloader Nasıl Çalışır?




Classloader java klaslarının Java sanal makinesine(JVM) yüklenmesini sağlar. 3 farklı classloader bulunmaktadır. Peki bunlar nelerdir?

1. Bootstrap(ön yükleyici) Classloader :
  • İlk olarak çalışan classloader dir.
  • Yüklemeye \jre\lib\rt.jar konumundan başlar ve temel java klaslarını yükler.(util, lang).
  • Native olarak yazılmış, çoğunluğunda C dili kullanılmıştır.
  • Diğer tüm classloaderlerin atasıdır(Parent). Root olarak düşünebiliriz.
  • Primordial Classloader olarakta bilinir.
2. Extension Classloader :
  • İkinci olarak çalışır ve class dosyalarını yüklemeye jre/lib/ext klasöründen yada java.ext.dirs tarafından belirtilen kısımlardan başlar.
  • Atası (Parent) bootstrap classloader dir.
  • Java ile yazılmıştir.
3. Applicaton/System Classloader :
  • Son olarak system classloader çalışır.
  • Atası(Parent) extension classloader dir.
  • Genellikle uygulama bağımlı klas dosyalarını yüklemek için kullanılırlar.
  • Yüklemeye CLASSPATH ten başlar. Eğer -cp parametresi ile klas eklenmiş ise onlarıda yükler.

Classloader ler 3 temel prensibe dayanarak çalışırlar
  1. Delegation (Delegasyon-Yetkilendirme)
  2. Visibility
  3. Uniqueness (Eşsizlik)
Delegation: Bir loader eğer yükleme yapacaksa atalarına bildirmeden yükleme yapamaz.
Sözde kod ile anlatacak olursak :  
  1. Extension classloader hmenn klasini yüklemek ister
  2. Parenti olarak bootstrapa aynı klasın önceden yüklenme durumunu sorar.
  3. Eğer yüklenmemişse yükler, yüklendiyse yükleme işlemini iptal eder.
Bu durum system classloader içinde geçerlidir. Klasın daha önceden yüklenme durumunu parentlerine sırayla sorar.

Visibility: Bir loader parenti tarafından yüklenen klasları görebilir ama parent(ata) child(çocuk) ların yüklediğini göremez.

Uniqueness: Aynı isimde 2 klas yüklenemez. Delegasyondandaki sorgulama evresi ile bunun önüne geçilir.

Kendimiz RUNTIME esnasında nasıl klas yükleriz ?

Java klas yüklememiz için bize bir API sağlar. Bu API aracılığıyla Class.forName(klasAdi) metodu ile klas yükleyebiliriz. Bu işlem sırasıyla şöyle gerçekleşir.

  1. loadClass() metodu çalışır ve jar dosyaları arasında klası arar.
  2. Eğer klas var ise yüklemeyi gerçekleştirir.
  3. Eğer yok ise ClassNotFoundException fırlatır.