Kullanıcılar birden çok BIG-IP F5 üzerinden geçerek bir sunucuya erişip hizmet alabiliyorlar. Çok karışık bir yapı olmasından dolayı standart “persistence metodları” ile servise gelen istekler düzgün şekilde dağıtılamıyor ve bu nedenle iRule ile sunucudan gelen “XSESSIONID” isimli bir cookie değerine göre F5’lerde persistence oluşturularak her durumda bir istemcinin hep aynı sunucuya gitmesi sağlanıyor. Ancak, son yapılan güncellemeler ile sistemler yeni versiyona yükseltildikten sonra LTM log dosyalarında aşağıdaki gibi TCL Error hata mesajları görülmeye başlandı. Dahası servis sahipleri dağıtımın düzgün şekilde yapılamamasından dolayı, isteklerin olması gereken sunuculara gönderilmediğinden şikayet etmeye başladılar.
01220001:3: TCL error: /Common/Xsession_mobilA <HTTP_RESPONSE> - Prerequisite operation not in progress (line 1) (line 1) invoked from within "persist add uie [HTTP::cookie "XSESSIONID"]"
Ne var ki bu hata mesajı için bir düzenden bahsetmek pek mümkün değil. Tamamen rastgele zamanlarda ortaya çıkan “invoked from within” hatasını Google ile aratınca pek bir şey çıkmamasından dolayı, probleme daha yakından bakalım.
Daha önce programlama ile ilgilenenlerin tanıdığı bir durumdan bahsetmek gerekirse klavyeden bir değer girilmesini isteyen bir uygulama yazdığınızı düşünelim. Kullanıcılar genelde, herhangi bir tuş kombinasyonu ile anlamlı ya da anlamsız bir veri girip “ENTER” karakterine basarlar. Sistem, girilen değerin sonunda gönderilen “ENTER” karakterini aldığında, veriyi alır ve girişi okuma işlemini sonlandırır. Genelde bu bilgi bir değişken içinde saklanır ve uygulamayı geliştiren kişinin amacına göre işlenir. Sonrasında ne olduğu ile şu an ilgilenmiyoruz.
Buraya kadarki kısımda, ya kullanıcı klavyeden adını, soyadını, ya da istenen bilgiye karşılık gelen veriyi girmek yerine “CRTL + D” tuşlarına bassa ? Bu durum bir veri girişi yerine geçer ve sistem yine okuma işlemini tıpkı “ENTER” karakterine basmışsınız gibi sonlandırır. Ancak bu veri tampon bellekten okunmaya çalışıldığında “BOŞ” olarak adlandırılan bir değer döner. Bu durumda bir exception oluşur. Sonuç olarak bir değişkeniniz var fakat içi ‘boş’ ile doludur.
Burada verilen örnek ile yaşanılan sorun bire bir uyumlu ancak bu örnek bir web yazılımından ziyade daha alt seviyeli olan C ve C++ gibi dillerde görebileceğiniz bir durumdur. Örnek bir kod şöyle olabilir.
#include <stdio.h> #include <stdlib.h> int main(int argc, char **argv){ char a[10] = "#include <stdio.h> #include <stdlib.h> int main(int argc, char **argv){ char a[10] = "\0"; puts("Type any word : "); fgets( a, 10, stdin); puts(a); return 0; }"; puts("Type any word : "); fgets( a, 10, stdin); puts(a); return 0; }
Yaşadığımız soruna geri dönersek, sorun sunucunun XSESSIONID isimli cookie’yi oluşturup içine herhangi bir veri yazmamasından dolayı oluşuyor. Örneği gerçek hayata uygulamak isterseniz, aşağıda php ile yazılmış basit bir web sayfası kodu var.
<?php setcookie("XSESSIONID") ?>
Temelde yaptığı şey sadece, istekte bulunan kişiye, ismi “XSESSIONID” olan içi boş bir cookie göndermek.
Bu kodu bu haliyle bir web sunucusuna aktarıp sayfayı curl ile çağıralım ve ne olduğunu görelim.
[plymouth@red ~]$ curl -v "http://10.34.23.127/test1.php" * About to connect() to 10.34.23.127 port 80 (#0) * Trying 10.34.23.127… connected * Connected to 10.34.23.127 (10.34.23.127) port 80 (#0) > GET /test1.php HTTP/1.1 > User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.18 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2 > Host: 10.34.23.127 > Accept: */* > < HTTP/1.1 200 OK < Date: Mon, 16 Nov 2015 14:48:48 GMT < Server: Apache < X-Powered-By: PHP/5.3.3 < Set-Cookie: XSESSIONID= < Content-Length: 0 < Content-Type: text/html; charset=UTF-8 < * Connection #0 to host 10.34.23.127 left intact * Closing connection #0
Dönen cevabın içindeki XSESSIONID cookie’sinin herhangi bir değer barındırmadığını “=” karakterinin sağ tarafının tamamen boş olmasından anlayabiliyoruz.
Şimdi F5 üzerinde basit bir virtual server oluşturup, pool’a kodumuzu çalıştırdığımız sunucuyu ekleyerek, testi aşağıdaki iRule ile tekrar edelim.
when HTTP_RESPONSE { if { [HTTP::cookie exists "XSESSIONID"] } { persist add uie [HTTP::cookie "XSESSIONID"] } } when HTTP_REQUEST { HTTP::header insert "rlnclientipaddr" [IP::remote_addr] "CLIENTPORT" [TCP::remote_port] "Proxy-Client-IP" [IP::remote_addr] if { [HTTP::cookie exists "XSESSIONID"] } { persist uie [HTTP::cookie "XSESSIONID"] persist:[persist lookup uie [HTTP::cookie "XSESSIONID"]]" } }
Eğer bu iRule’u oluşturduğunuz Virtual Server’a ekledikten sonra /var/log/ltm dosyasını tail ile açarsanız, her yeni istekle birlikte, içi boş olan XSESSIONID isimli cookilerin “TCL Error” ile başlayan hata loglarının düşmesine neden olduğunu görmeniz mümkün.
Eğer PHP kodunu değiştirip aşağıdaki gibi düzenlerseniz, loglardaki hata mesajlarının artık gelmediğini görürsünüz.
<?php setcookie("XSESSIONID", "TEST") ?>
Bu kod ile XSESSIONID isimli cookie’ye TEST değerini atamış ve böylece F5 BIG-IP üzerinden geçecek bu tarz bir trafik için TCL Error hatası alınmadan oturumların başarılı bir şekilde kurulmasını sağlamış oluyoruz.