Daha önce Google App Engine'de bir Java projesi yapmaya çalıştığımı belirtmiştim. Sonunda yapabildim, ama düşündüğümden çok daha uzun sürdü! Kodlamasını kısa sürede yaptım, ancak appengine'in (olmayan) stabilitesi beni hayrete düşürdü! Hatta bir bug bile bulup raporladım.
"Bir Kelime Bir İşlem"in "işlem" kısmını çözen uygulamaya şu adresten erişebilirsiniz:
http://java-apps.gencsoy.net/birIslem/index.jsp
"Bir İşlem"i çözmek popüler ve kolay sayılabilecek bir iş. (Bu arada bu yarışmanın İngilizce ismini bilen varsa söylerse sevinirim.). Ben de bunu çözen ilk programımı 10 yıl önce, lise üçüncü sınıfta, delphi'de yazmıştım. Ne yazık ki eski kodlarımı bulamıyorum, buraya bir link vermek isterdim. Temelde bilgisiz (desteksiz?
) bir algoritma ile çözülebiliyor. Ben de depth-first çözdürdüm.
Kodu yazmak o kadar zor değildi. Ancak Google App Engine'e (GAE) geçirme sürecinde bazı ciddi kısıtlamaları farkettim.
- Bir isteğin en fazla 30 saniye içerisinde cevaplandırılıp kullanıcıya yollanması gerekiyor (açıklama burada).
- Arka planda çalışacak bir Thread yaratılamıyor (açıklama burada).
İlk kısıtlama önemli. Aslında işlem kısmının bir çözümü varsa genelde 30 saniye içerisinde bulabiliyor ama biz işimizi şansa bırakmamalıyız. Hem tarayıcı da 30 saniye içerisinde bağlantıyı kesebilir.
Bu ilk kısıta karşı normal bir uygulama sunucusunda algoritma işletme kodunu değiştirmeden basit bir çözüm mümkün: çözümü arka planda bir thread'e atıp kullanıcıyı bir sorgu (poll) sayfasına yönlendirmek.
Tabi ki Thread yaratılamayan bir ortamda bu çözüm de geçersiz kalıyor.
Bunun yerine farklı, ve sanırım ad-hoc, bir çözüm geliştirdim. Çözüm belli bir süre içerisinde bulunamazsa sayfayı yenileyip (refresh) çözüme kaldığı yerden devam etmek:
Çözümü arada duraklatıp devam ettirmek algoritmanın işletilme şeklini değiştiriyor! İlk halinde problemi algoritmaya verip "çöz" diyecek ve sonucu ne kadar sürecek idiyse bekleyecektim. Bu çözümü yapabilmem için çözüm algoritmamım adım adım çalıştırılabilir olması gerekiyor, bu da kod değişikliği, daha önce olmayan erişim yöntemlerinin yazılması gerek.
İlk başta göze çarpmayan bir sorun daha var. Çözümün iki adımı arasında çözücü nesnenin önce alınıp, işletilip, son halinin tekrar saklanması gerekiyor. Normal bir uygulama sunucuda bir HttpSession açıp nesneyi kolayca oraya koyup geri alabilirsiniz. Çünkü bir session sadece bir makinede açılır ve session nesneler o makinenin hafızasında tutulur. Ancak Google App Engine'ın mimarisi tamamen dağıtık. Yani çözüm sayfası yenilendiğinde başka bir sunucu isteğinize cevap veriyor olabilir. Bu da üçüncü sorunu doğuruyor:
Bu gereksinim de çözücü nesnenin sınıfının ve içerdiği diğer tüm diğer sınıfların Serializable ile işaretlenmesi anlamına geliyor. Bu da özellikle anonim sınıfları refactor etmeye yol açıyor. Serializable yapmadan serialize etmeye yarayan araçlar olduğunu biliyorum ama bunlar özellikle reflection'a dayandığı ve reflection da GAE'de sıkıntılı göründüğü için hiç bulaşmadım.
Serialization sırasında bir hata da keşfettim. EnumSet sınıfını serialize edemiyordu. Yukarda belirttiğim gibi bunun için bir bug da raporladım.
Ancak bu bug'a anlamam tahmininizden çok daha uzun sürdü. Çünkü GAE log kaydında yeterli bir hata basmıyor, doğru exception'ları göstermiyordu! Ve bu uygulamayı yazarken beni en çok uğraştıran şey bu bug oldu!
İşin çok daha vahim tarafı Eclipse plug-in'i ile gerçek davranışın arasında ciddi fark olması. Eclipse plug-in'i serialization'a bile hata vermiyor, normal bir uygulama sunucusu gibi çalışıyor!
Velhasıl enumset'i de düz set ile değiştirip uygulamamızı çalışır hale getirdik. JSP ve web sayfası konusunda paslanmışız, açıkcası hiçbir zaman da çok iyi olamadığım bir konuydu. O yüzden bazı bilenen (ve bilinmeyen) hataları olan bir uygulamayı denemek isterseniz link'i tekrar vereyim:
http://java-apps.gencsoy.net/birIslem/index.jsp
Tahmin etmişsinizdir, uygulama ciddi miktarda CPU kullanıyor. Sayılarda adet sınırı da koymadım, çok fazla sayı ve zor bir hedef girerseniz Google'un CPU'larına ciddi bir yük bindirebilirsiniz. Neyse ki bana beleş! Eğer kotalarımı doldurursanız sayı sınırı koyabilirim.
Peki sonuçta Google App Engine'ı tavsiye eder miyim? Bu kime tavsiye edeceğime bağlı. Eğer vaktiniz bol ve "yaw Google ne icat çıkarmış bi deneyelim" diyorsanız tavsiye ederim. Ama ciddi, büyük bir projeyi "Google'ın deneyimine güveniyorum" diyerek GAE'ya taşımayı en azından şimdilik bence düşünmemelisiniz. Google'ın ileride tam Java desteği verebileceğini umuyorum. Ancak vermek istemeyedebileceğinden korkuyorum.