Locust ile Özgür Yük Testi

Ayşenur Çelik Aykuş
TurkNet Technology
Published in
3 min readJul 8, 2023

Yazılım uygulamalarında yük/performans testlerinin yapılmasındaki amaç, belirlenen kısıtlar ölçüsünde uygulanan yük altında, sistemde ortaya çıkabilecek darboğazları (bottleneck) ortaya çıkarmaktır. Aynı zamanda servis sürekliliği açısından ne kadar kaynak kullanımına ihtiyaç var bunu belirlemektir.

locust.io

Neden locust.io?

Yük testi yapmak için çeşitli yazılımlar mevcut(jmeter, gatling, grinder vs.) fakat locust’u seçmemizdeki en büyük sebep, python diliyle özgür senaryo yazımına izin vermesi ve testlerimizin istatistiklerini doğrudan web kullanıcı arayüzünde görebilmemizdi. Ek olarak locust, birden fazla makineye dağıtılmış olarak çalışan yük testlerini desteklemekte ve bu nedenle milyonlarca eş zamanlı kullanıcıyı simüle etmek için kullanılabilmektedir.

Kurulum

Not: Locust.io’yu kullanmak için bilgisayarınızda Python kurulu olması gerekmektedir.

Pip kullanarak Locust’u kuralım.

pip install locust

locust -v komutunu çalıştırarak Locust'u doğru bir şekilde kurduğumuzu doğrulayabiliriz. Komut çıktısı bize versiyon numarasını verecektir.

Bir Örnekle Başlayalım

Bu örnek turk.net’ in anasayfasına ve de belirlenen pathteki bir diğer sayfaya istek atacak şekilde tasarlandı.

from locust import HttpUser, SequentialTaskSet, task, constant

class HomeLoadTest(SequentialTaskSet):

def on_start(self):
print("Homepage services started")

@task
def home_page(self):
with self.client.get("",catch_response=True) as response:
if response.status_code == 200:
response.success()

@task
def abonelik(self):
with self.client.get("taahhutsuz-ozgur-iletisim-abonelik") as response:
if response.status_code == 200:
response.success()

def on_stop(self):
print("Homepage services stopped")

class HomePageLoadTest(HttpUser):

wait_time = constant(1)
tasks = [HomeLoadTest]
host = "https://turk.net/"

Bu dosyayı locustfile.py veya başka bir isimle kaydedelim ve kullandığımız idenin terminalinden locust -f dosyaismi.py şeklinde çalıştıralım. Eğer dosyanızı locustfile.py olarak kaydettiyseniz sadece locust komutunu çalıştırmak yeterli olacaktır.

Locust’u başlattığımızda 8089 portu üzerinden bir sayfa göreceğiz.

Number of users: Sanal kullanıcı sayısı.

Spawn rate: Saniye başına kaç kullanıcı arttırılacağı.

Örneğin Number of users 100, spawn rate 20 yazarsanız, teste başladıktan sonra her saniye başı 20 kullanıcı ekleyerek 100 kullanıcıya ulaşır.

Tanımlamalar:

Requests: Şimdiye kadar yapılan toplam istek sayısı
Fails: Başarısız olan isteklerin sayısı
Median: Milisaniye cinsinden %50 lik dilim için yanıt hızı
90%ile: Milisaniye cinsinden %90 lık dilim için yanıt hızı
Average: Milisaniye cinsinden ortalama yanıt hızı
Min: Milisaniye cinsinden minimum yanıt hızı
Max: Milisaniye cinsinden maximum yanıt hızı
Average size (bytes): Bayt cinsinden ortalama yanıt boyutu
Current RPS: Saniyedeki geçerli istek sayısı
Current Failures/s: Saniyedeki toplam hata sayısı

Test çıktılarımızı locust arayüzünden resimlerde olduğu gibi detaylıca inceleyebiliyoruz. Test stop butonuna basana kadar ya da ideden sonlandırana kadar koşmaya devam eder.

Test betiğini açıklamak gerekirse:

class HomeLoadTest(TaskSet):
...

@task
def home_page(self):
with self.client.get("",catch_response=True) as response:
if response.status_code == 200:
response.success()
  • TaskSet: Kullanıcı davranışını tanımladığınız TaskSet ile bir sınıf oluşturuyoruz ve ardından eylemi @task annotation ı ile belirtiyoruz.
  • SequentialTaskSet: Tasksetten farklı olarak, toplam istek sayısının her bir classa eşit şekilde dağıtılmasını istediğimizde bunu kullanırız.
class HomePageLoadTest(HttpUser):

wait_time = constant(1)
tasks = [HomeLoadTest]
host = "https://turk.net/"
  • HttpUser: HTTP isteklerini yapabilmek için HttpUser parametresine sahip bir sınıfa ihtiyacımız var. Burada, konfigürasyon dosyasına da yazabileceğimiz spesifik özellikleri tanımlıyoruz. Eğer projede bir conf dosyası varsa bu kısım dosyayı override eder. Örnekte, bir servisin diğerine geçmesi için beklemesi gereken süreyi(wait_time), hangi class ın koşulacağı(tasks) ve isteklerin yapılacağı adres(host) bilgilerini verdim.
def on_start(self):
print("Homepage services started")

...

def on_stop(self):
print("Homepage services stopped")

On_start, On_Stop: On_start metodu testler başlamadan önce bir kez çalıştırılır. Bu metodu ön koşul belirlememiz gereken senaryolarda kullanabiliriz. Login, auth gibi. On_stop metodu ise testler bittikten sonra en son çalıştırılacak metottur. Logout ya da save metodu gibi son çalışması gereken senaryolarda kullanılabilir.

Sonuç

Locust, python dili ile basit ve hızlı bir şekilde kullanıcı davranışlarını belirleme, sonrasında belirlenen bu davranışların yüz binlerce kullanıcı ile simüle ederek gerçeğe en yakın oranda yük ve stres testleri koşmamızı kolaylaştırmıştır. Web arayüzü sayesinde de, hem test sonuçlarını raporlama hem de sonuç raporlarının grafik üzerinde anlık gösterimini sağlayarak sistemlerimizin dayanabildiği maksimum kullanıcı ve istek sonuçlarını alabiliyoruz.

Serinin devamında locust’un dağıtık sistemlerde nasıl çalıştığından bahsedeceğim.

--

--