Sunday, November 21, 2010

Kasım 2010 Mısır Turu

Last week I've been to Egypt. This post is about what I've seen there. 
It's in Turkish, english readers can enjoy the photos.

9 günlük Kurban Bayramı tatilini fırsat bilip "boyu devrilesice" Bamtur'dan Mısır turu satın aldık. Tur paketinde 2 gün Kahire, 1 gün İskenderiye ve 4 gün de Sharm El Sheikh vardı. Kahire'de piramitleri, İskenderiye'de büyük kütüphaneyi görüp, tatili Sharm'da denizin ve mercanların keyfini çıkartarak sonlandıracaktık. Tatilimizin nasıl sona erdiğini merak ediyorsanız okumaya devam edin.



Mısır'ın başketi Kahire'ye EgyptAir ile uçtuk. Yaklaşık 20 milyon kişinin yaşadığı Kahire'ye, Nil çevresindeki ufak tefek yeşillikleri saymazsak, tek bir renk hakimdi, kum rengi. Unutmadan yazayım, Mısır ile Türkiye arasında saat farkı yokmuş.



14 Kasım 2010 Pazar günü öğleden sonra 3'te otele yerleştik. Piramitlere giden caddenin üzerindeki 4 yıldızlı otelin balkonundan çektiğim bu resim Kahire'deki trafiği gösteriyor. İki gün şehirde gezmemize rağmen bir tane trafik ışığı göremedik. Trafiği kontrol etmek için her kavşağa trafik polisi koymuşlar. İstanbul'un trafiğinden şikayet edenlerin gidip Kahire'yi bir görmeleri lazım, tam bir kaos. Tüm taksiler vuruk içinde, sanki çarpışan araba. Şehirde taksimetreli (beyaz) ve taksimetresiz (Siyah) olmak üzere iki tip taksi var. Taksimetreliler biraz daha konforlu gözüküyor fakat çok pahalı. Taksimetresizlere binmeden once pazarlık yapıyorsunuz, çatpat ingilizce bilen bir şoföre rastlarsanız şanslısınız yoksa anlaşana kadar akla karayı seçersiniz.



Bu resim bayramdan bir gün önce Kahire caddelerinden birinde çekildi. Kasaplar resimde görüldüğü gibi açık hava kasabı şeklinde.



Kahire'de turist olmak gerçekten çok zor. Halk sürekli kazıklama modunda. Ne alırsan al pazarlık şart. 3 Mısır pound'u değerindeki Nil nehri üzerindeki tekne gezintisini 60 pound'a satan Mısır'lı elemana buradan selamlarımı gönderiyorum. (Bu yazının yazıldığı tarihte 1 TL yaklaşık olarak 4 Mısır Pound'u değerindedir). Nil olmasaydı Mısır da olmazdı, %94'ü çöl olan bu memlekete adeta hayat veriyor Nil.









Mısır'a gidip de piramitleri görmemek olmaz. 4600 yıl önce yapılmış bu dev yapıları dimdik ayakta görmek çok heyecan vericiydi. Mısır'lı satıcıların ve dilencilerin yoğun markajı altında piramitleri gezmeye çalıştık. Piramitlerin yapımında halkın firavun tarafından köle gibi çalıştırıldığını düşünürdüm hep. Gerçeği öğrenebilmem için taaa Mısır'lara gitmek gerekiyormuş. (Ne derler bilirsiniz, gitmeden, görmeden bilemezsin...) Gelelim piramitler ile ilgili gerçeğe. Piramitlerin yapımında Mısır halkının çalıştığı doğru fakat halk bunu bir iş olarak yapmış. Bugün çoğumuzun yaptığı gibi sabah 8 akşam 5 çalışıp maaşlarını almışlar. Firavun bu sayede tüm halkına iş imkanı vermiş. Herkesin işi gücü olduğu için de suç oranı yüzde sıfır imiş.

Piramitler ile ilgili aklımda kalan diğer ilginç bilgiler ise şöyle:

  • Piramitler kralların mezarları olarak yapılmış. Ana karnından dünyaya gelip tekrar toprak ananın karnına girişi anlatmaya çalışan bu dev yapılar, ana karnının dünya üzerindeki temsiliymiş.
  • Yapımı 20 yıl süren en büyük piramit tam 140 metre yüksekliğinde. Fransızlar 1889 yılında Eiffel kulesini yapana kadar dünya üzerindeki en yüksek bina ünvanı Büyük Piramit'teymiş.
  • Piramitleri koruması! için firavun Sphinx'i yaptırmış. Aslan vücudu üzerindeki insan kafası kralın halkına karşı olan merhametini ve mantığını, aslan vücudu ise düşmanlara ve hırsızlara karşı kralın vahşiliğini gösteriyormuş.
  • Büyük Piramit yaklaşık 1 milyon 300 bin tane, ağırlığı 2.5 tonla 15 ton arasında değişen taş bloklardan oluşuyor.
  • Piramitler ilk yapıldıklarında şimdi göründükleri gibi basamak basamak değillermiş. Hırsızların tırmanmalarını önlemek için dümdüz sıvalı dış duvarları varmış. Zamanla düşen ve alınan taşlar yüzünden bugünkü basamaklı halini almış.
  • Piramitlerin içine girmek isterseniz görebileceğiniz pek bir şey yok. Mezarlardaki tüm eşyalar ve mumyalar Kahire ve İngiltere'deki müzelerde olduğu için piramitlerin içi (en azından ziyarete açık kısımları) bomboş. 1 metre eninde ve 1 metre yüksekliğindeki tünellerden 20 metre aşağı inerek mezara ulaştık. Sadettin Teksoy'un piramitlerdeki kanter içinde kalarak yaptığı çekimi hatirlarsınız. Aynen o şekilde 20 metre inip çıkıyorsunuz. Görebileceğiniz tek şey boş mezar odaları.

Piramitlerin içinde göremediğimiz tüm tarihi eserleri Kahire Müzesi'nde görme şansımız oldu. Müzeye kamera, fotoğraf makinası ve telefon sokmak yasak. Çok sıkı bir şekilde denetim var. Müzeye girdikten sonra mumyaları da görmek isterseniz ayrıca para verip bilet almanız gerekiyor. (Kişi başı 20 liraydı galiba) Her eserin başında 1 saniye kalarak müzeyi dolaşırsanız müze geziniz yaklaşık 2 gün sürüyor. 200 bin civarında eser sergileniyor.



İki gün Kahire'de kaldıktan sonra, bayramın birinci günü İskenderiye'ye doğru yola çıktık. Kahire-İskenderiye arası 260 kilometre. 3 buçuk saatlik bir otobüs yolculuğunun ardından İskenderiye'ye geldik. Adını Büyük İskender'den (Alexander the Great) alan Mısır'ın ikinci büyük şehri olan İskenderiye Kahire'ye göre çok daha temiz gözüküyordu. İskenderiye, feneri ve kütüphanesi ile meşhur bir kent. Ama ortada fener mener yok. Zamanının ve günümüzün en büyük feneri olarak anılan İskenderiye feneri 1300'lü yıllarda depremlere dayanamayarak yıkılmış. Bugün fenerin olduğu yerde İskenderiye kalesi var.

İskenderiye'deki kütüphane 2002 yılında yeni binasına taşınmış. Yukarıda sağdaki resimde gözüken kütüphanenin dış duvarları. MÖ 282 yılında yapılan kütüphane birileri tarafından yakılmış. Kimin yaktığı kesin olarak blinmiyor, kimin yaktığına dair 3 teori var. Birincisi Julius Caesar, Mısır donanmasını topa tutarken arada kütüphaneyi de yakmış. İkinci bir teoriye göre İskenderiye'de çıkan din çatışmaları ve ayaklanmalar sırasında kütüphane de ateşe verilmiş. Üçüncü bir teoriye göre de, kütüphane İskenderiye Müslümanlar tarafından alındıktan sonra yakılmış. Kim yaktıysa çok ayıp etmiş. 150 bin tane el yazması kitabı yakmak aklı başında birisinin yapacağı iş değil.





Tatilimizin 4. günü (17 Kasım 2010) sabah Kahire havaalanından Sharm El Sheikh'e doğru yola çıktık. 45 dakikalık bir uçuştan sonra Sharm'a ulaştık. Uçağın pencerelerinden Sharm'ın güzel plajlarını, denizinin güzelliğini gördükçe bir an önce otele yerleşip kendimizi denize atmak için sabırsızlanıyorduk. Ama Sharm'ı sadece havadan görebildik. Mükemmel!!! tur şirketi Bamtur otel rezervasyonlarını yaptırmadığı için (Bamtur yetkilileri dolandırıldıklarını söylüyorlar) havaalanında geçen 10 saatin ardından tıpış tıpış İstanbul'a geri dönmek zorunda kaldık. 10 saat boyunca Sharm'da bir tek boş oda bile bulamayan Bamtur görevlilerine karşı olan hislerimi burada yazmaya kalkarsam Google'ın Blogger servisinin de yasaklı siteler arasında girmesinden korkuyorum.

İşte böyle dostlar. Mısır'ı da görmüş olduk şu hayatta. Tüm aksiliklere rağmen Kahire-İskenderiye gezilerimiz ve tur sırasında tanıştığımız güzel insanlar tesellimiz oldu. Uzun lafın kısası siz siz olun Bamtur ile tatil planı yapmayın.

Tuesday, October 12, 2010

JMeter JDBC Request Demo - Screencast

Merhaba

Daha önce bu günlükte JMeter ile ilgili bir iki yazı yazmıştım. Genelde ingilizce yazmaya çalışıyorum çünkü ingilizce yazılar daha fazla kişi tarafından okunuyor ve okuyucu yorumları daha fazla oluyor.

JMeter yazılarının Türkçe cevirilerini yapmak için bilgisayarın başına oturduğumda küçük bir demonun yüzlerce satırdan çok daha etkili olabileceğini düşündüm ve aşağıdaki videoda izleyebileceğiniz demoyu kaydettim.

İyi seyirler.

JMeter JDBC Request Demo from ilkinulas on Vimeo.


NOT: Ekranı kaydetmek için RecordMyDesktop kullandım.

Tuesday, June 15, 2010

Java Garbage Collection : Unexpected Full GC

I've been digging garbage collection logs these days. We have a production server which suffers long pauses of garbage collection. According to garbage collection log file, there are three different cases that force the JVM to do a StopTheWorld collection:

1. Full GC after a promotion failure: This is the evidence of not enough contiguous space in the old (tenured) generation. The simplest solution to this is increasing heap size. (I am glad it worked for us.)

2. Full GC after a concurrent mode failure (in other words; full promotion guarantee failure) : CMS collector can not catch up with the object allocation speed of the application. If this is the case try setting CMSInitiatingOccupancyFraction to a lower value. CMS will start early but will finish its job on-time.

3. The third one was very difficult for me to figure out. Here is what it looks like: Everything seems to work fine but suddenly Full GC kicks in and 37 seconds of break for application threads.

216066.711: [GC 216066.713: [ParNew: 911554K->71428K(943744K), 0.0860545 secs] 2346321K->1508264K(4089472K), 0.0878449 secs] [Times: user=3.63 sys=0.32, real=0.09 secs]
216066.896: [Full GC 216066.897: [CMS: 1436836K->1003062K(3145728K), 37.8691646 secs] 1527124K->1003062K(4089472K), [CMS Perm : 86016K->31249K(86016K)], 37.8707796 secs] [Times: u
ser=37.64 sys=0.35, real=37.87 secs]
216106.398: [GC 216106.399: [ParNew: 838912K->46337K(943744K), 0.0555625 secs] 1841974K->1049399K(4089472K), 0.0573404 secs] [Times: user=1.33 sys=0.45, real=0.06 secs]
The above log says that in order to clean permanent generation a full collection occured and (86016 - 31249) kilobytes of space freed in permanent generation.

What I've learned today is : The garbage of the permanent generation is only collected by a Full GC. If you see unexpected full collections try expanding permanent generation.

Monday, June 7, 2010

Project Voldemort

Üniversitede bilgisayar mühendisliği okuyup da veritabanları dersini almayan yoktur. Veritabanı dersinde bize ilk öğretilen şey "normalization" oldu, dediler ki :

  • Aman tablolarda tekrar eden bilgiler olmasın. (Primary Keys, unique constraints)
  • Sakın farklı yapıdaki bilgileri getirip aynı tabloya koyma. Herbir farklı yapı için ayrı bir tablo oluşturmaya özen göster.
  • Müşterinin adres bilgilerini Adres tablosuna, sipariş bilgilerini Siparis tablosuna, kişisel bigilerini Musteri tablosuna koy. Denizli'den sipariş veren 30 yaşından küçük müşterileri bulmak için Adres, Sirapis ve Musteri tablolarını çarp (join dediğimiz olay da sonuçta tabloların bir çarpımıdır), işte sana istediğin bilgi.

Bu yöntem yıllarca bilişim sektörünü idare etti. Hala birçok alanda idare etmeye devam ediyor. Bugün Oracle olmasaydı ne yapardık :D Artan ihtiyaçları karşılamak için günümüzde uyguladığımız yöntem, eğer bütçe yeterli ise Oracle'ı çalıştıracak daha güçlü bir makina satın almak oluyor. İşlemci gücünü artırmak için her ihtiyaçta daha güçlü bir makinaya taşınmak gün gelir çözüm olmaktan çıkar. Bu tür durumlarda iş gücünü birden fazla sunucuya dağıtmak gereklidir. İlişkisel veritabanları dağıtık ortamlarda (distributed) beklenen performansı veremeyebilirler, çünkü network üzerinde farklı makinalarda olan sunucular arasında basit bir SQL join'i çalıştırmak çok güçtür.

Web 2.0 ile beraber internet kullanıcılarının içerik paylaşması internet sitelerinin işlemesi gereken bilgiyi inanılmaz derecede artırdı. Bunun en çarpıcı örneği Twitter. Twitter aracılığı ile gönderilen tweet sayısı günde 50 milyon'a ulaşmış durumda. (Saniyede yaklaşık 600 tweet) Depolanan veri miktarı arttıkça bu verileri bölümleyip (partition) birden fazla yerde saklama ihtiyacı ortaya çıkıyor. Milyonlarca kayıt barındırıdan ve farklı disklerde olan tablolar ile yapılan join işlemleri uygulamaların okuma (read) performansını olumsuz etkilediği için NoSQL depolama sistemleri geliştirilmiştir. NoSQL sistemler, RDBMS'lere göre veriyi daha hızlı işlerler, okuma ve yazma performansları RMDBMS'lere göre çok daha iyidir. Bunun diğer bir sebebi de RDBMS'lerin ACID (atomicity, consistency, isolation, durability) kısıtlarını yerine getirmek zorunda olmaları ve bunun için ekstra işlemler yapmak zorunda kalmalarıdır. NoSQL depolama sistemleri RDBMS'leri ortadan kaldırmayacak fakat bazı uygun projelerde RDBMS'lerin yerini alacak gibi gözüküyor.

Bu yazıda LinkedIn'in kullandığı ve duyurduğu bir proje olan Project Voldemort'tan bahsedeceğim. LinkedIn, iş dünyasının facebook'u olarak biliniyor. SSS sayfasında söyledikleri doğruysa 8 Nisan 2010 itibari ile 65 milyon üyesi varmış. 65 milyon üyenin birbirleri ile olan bağlantılarını, iş tecrüblerini, oluşturdukları profesyonel grupları hesaba katınca ortaya inanılmaz boyutlarda bir veri çıkıyor. LinkedIn mühendisleri (eminin onların bizlerden bir farkı yok :D ) bu kadar çok veriyi saklamak ve işlemek için Amazon'un Dynamo'sundan ve memcached'den esinlenerek Voldemort'u yazmaya karar vermişler. Böyle güzel bir projenin ismi neden Voldemort olur onu da anlamış değilim. Bknz : Lord Voldemort

Project Voldemort'un ne olduğunu kısaca şöyle açıklayabiliriz:

  • Dağıtık (distributed) bir sistemdir. Veriler birden fazla lokasyona dağıtılmış saklanabilir.
  • Verilere erişim aynı bir Hashtable'a erişim gibi key'ler ile yapılır. SQL gibi bir sorgulama dili desteklemez.
  • Verileri diske yazar. Sistemin kapatılıp açılması verilerin kaybolmasına sebeb olmaz.

Projesinin ana sayfasında yazan Voldemort'un ne olduğunu anlatan maddeler ise şöyle:

  1. Veriler otomatik olarak sunucu grubundaki diğer makinalara kopyalanır(replicated)
  2. Veriler otomatik olarak bölümlenir (partitioned). İstediğin bir veriyi bulmak için bütün makinalar aranmaz, sadece tek bir makinaya bakarak veriler bulunabilir.
  3. Sunucu grubu içindeki bir sunucunun kapanmasından uygulama etkilenmez.
  4. Veri bütünlüğünü sağlamak için veriler versiyonlanır.
  5. Her bir sunucu diğer sunuculardan bağımsızdır. Single Point Of Failure (bunun türkçe karşılığını bulamadım. Kendim birşey uydurayım dedim beceremedim) SPOF yoktur.
  6. Basit bir arayüzü vardır. SQL desteklemez. Join'leri kod içinde sizin yapmanız gerekir.
    value = store.get(key)
    store.put(key, value)
    store.delete(key)
    
  7. Verileri diskte depolarken ön belliğinden, disk okuması yapmadan, verilere erişim sağlar. Ayrıca bir caching katmanı kullanmaya gerek kalmaz.
  8. Bu çok hoşuma gitti : Verileri depolama katmanı taklit edilebilir(mockable). Unit testler sadece hafızada çalışan bir Voldemort instance ile yapılabilir.

Bu projeyi deneme fırsatım olmadı. En kısa zamanda kurup örnek bir projede kullanıp, izlenimlerimi bu sayfalarda paylaşacağım. Buraya kadar okuduklarınız ilginizi çektiyse projenin sayfasına gidip daha detaylı bilgiye erişebilirsiniz.

Sunday, March 21, 2010

Load Test Whatever You Want With Apache JMeter

This is the second post about load testing with Apache JMeter, read the first post here: A step by step tutorial about load testing relational databases.

JMeter has lots of Samplers. If you need a sampler that is not provided by JMeter you can write your custom sampler. (custom samplers are called "Java Request" in JMeter terminology)
This post will show you, step by step, how to write a JMeter Java Request.

Step 1: Preparing the development environment

Add these two jar files to the java classpath.
  1. $JMETER_HOME/lib/ext/ApacheJMeter_core.jar
  2. $JMETER_HOME/lib/ext/ApacheJMeter_java.jar
(If you are using Eclipse, add these files as external jar files to the java build path.)

Step 2: Extending AbstractJavaSamplerClient

After setting up the classpath, create a custom sampler by extending AbstractJavaSamplerClient and override the following methods.
public Arguments getDefaultParameters() {...}
public void setupTest(JavaSamplerContext context) {...}
public void teardownTest(JavaSamplerContext context) {...}
public SampleResult runTest(JavaSamplerContext context) {...}
getDefaultParameters
Implement getDefaultParameters if you want initial values for test paramters. JMeter will display the parameters in its Java Request configuration GUI. (See the contents of the red rectangle in the picture below.) Here's an example implementation:
public Arguments getDefaultParameters() {
    Arguments defaultParameters = new Arguments();
    defaultParameters.addArgument("memcached_servers", "localhost:11211");
    defaultParameters.addArgument("username", "testuser");
    defaultParameters.addArgument("password", "testpasswd");
    return defaultParameters;
}
setupTest
This is where you read test parameters and initialize your test client. JMeter calls this method only once for each test thread.

teardownTest
Clean up the mess.

runTest
Write your test logic in this method. JMeter will call runTest method for every execution of test threads. Here is a typical runTest implementation:
@Override
public SampleResult runTest(JavaSamplerContext context) {
    SampleResult result = new SampleResult();
    boolean success = true;
    result.sampleStart();
    //
    // Write your test code here.
    //
    result.sampleEnd();
    result.setSuccessful(success);
    return result;
}
The time elapsed betweed result.sampleStart() and result.sampleEnd() is used to calculate average response time of the application under test.

Step 3: Deploy your custom sampler

When you are done create a jar file (containing your custom sampler) in the $JMETER_HOME/lib/ext/ directory. JMeter will display your java request in the java request configuration page.

You can see the results of your test by adding listeners to your test plan. "A step by step tutorial about load testing relational databases" post shows how to add listeners to test plans.

Sunday, March 14, 2010

Load Testing Relational Databases With JMeter

Apache JMeter is a performance testing tool which is entirely written in Java. Any application that works on request/response model can be load tested with JMeter. A relational database is not an exception: receives sql queries, executes them and returns the results of the execution.

I'am going to show you how easy it is to set up test scenarios with the graphical user interface of JMeter. But before diving into details let's give a shot to basic terms:

Test plan : describes a test scenario
Thread Group : represents users running your test scenario.
Samples : a way of sending request and waiting response. HTTP request, JDBC request, SOAP/XML-RPC request and java object request are examples of samples.
Logic Controller : used to customize the logic that JMeter uses to decide when to send requests
Listeners : receives test results and displays reports.
Timers : cause JMeter to delay a certain amount of time before each request that a thread makes.
Assertions : test that application returns expected responses

Note : This post is not meant to be an alternative documentation for JMeter. JMeter has a great documentation. You can find the details in its User's Manual (http://jakarta.apache.org/jmeter/usermanual/index.html
Suppose we have an application that logs every transaction into a relational database. We are going to create a test plan - step by step - in order to answer the questions below.
  • How many transaction records can be inserted to transaction table in a second?
  • How much time does it take to insert a single transaction record to transaction table?
  • How does number of concurrent threads (users) affects the inserts/secs and average response times?
  • How does number of records affects the insert/secs and average response times?

Step 1

Copy mysql jdbc driver into the lib folder of your JMeter installation. JMeter needs a suitable jdbc driver in the classpath to connect to the database.
Example ~/tools/jakarta-jmeter-2.3.4/lib/mysql-connector-java-5.0.5.jar
We are going to store orders of the customers and the result of the order in the transactions table.
CREATE TABLE transactions (
    id INT NOT NULL AUTO_INCREMENT,
    customer_id INT NOT NULL,
    order_id INT NOT NULL,
    result INT,
    PRIMARY KEY (id)
);

Step 2

Create a test plan and name it "Test MYSQL DB". Then add the following jmeter components to the test plan.
  1. Thread group named 'Database Users'
  2. Sampler of type JDBC Request
  3. Config element of type JDBC Connection Configuration
  4. Three config elements of type Random Variable
  5. Listener of type Summary Report
After adding these components JMeter test plan looks like the following picture.

Step 3

Configure database users. The thread group component simulates the database users.
1. Number of users (threads)
2. How many times a user will send request (loop count). If you select 'Forever', threads will run in a while(true) {...} loop until you decide to stop the test.

Step 4

Configure JDBC connection pool. JDBC Connection Configuration component is used to create jdbc connection pools. Database url, jdbc driver, database user and password are configured with this component. Connection pools are identified by "Variable Name". JDBC Samplers (requests) use this variable name (connection pool name) to pop and push connections. I named the test connection pool as "my db pool"

Step 5

Define random variables that will be used in INSERT statements. In this test I am using three random variables : user id, order id and result. Following picture shows the a random number configuration for user id. Random number generator will give us a random integers between 1 and 1000000. We can refer to generated random number with the name user_id.

Step 6

JDBC Request component is the place where we tell our users (threads) what to do. The name of the pool that was configured in Step 3 "my db pool" will be used as the "variable name bound to pool". All threads will execute prepared statements. User id, order id and result will be generated by the random number configurator (described in Step 5)

Step 7

Now we have our threads configured to insert transaction records to the transactions table. In this last step we will add a Listener of type Summary Report in order to view test results.

The results tells us that 10 concurrent users (threads) working in an infinite loop can insert nearly 3300 rows in our transactions table. And the average time spent for inserting a row is 2 ms. You can also choose "Graph Results" listener to view visual representation of the results.
I created and run a simple DB test plan. I hope you'll find this post helpful. Keep this motto in mind
if you can’t measure it, you can neither manage it nor improve it
Happy testing...

Monday, February 1, 2010

2010 Winter Olympics - Bahçeköy/İSTANBUL

Hi everybody, I've been busy training hard for the winter olympics. You can watch me practicing bobsleigh with my two assistants Johny and Karsaf :)