Bugün, "yük dengeleme" yani ecnebilerin deyimiyle "load balancing" kavramını Nginx ve NodeJS özelinde inceleyeceğiz.

Neden yük dengeleme yapmamız gerektiğine, "bir elin nesi var iki elin sesi var" diyerek iyi bir cevap vermiş atalarımız. Aynen öyle. Eğer web uygulamanız tek bir sunucu üzerinde çalışıyorsa ve tüm yükü bu sunucu çekiyorsa haliyle biraz zorlanacatır. Ancak siz bu yükü, aynı işi yapan birden fazla sunucuya paylaştırırsanız, iş çok daha hızlı tamamlanacaktır.

Senaryomuz şöyle olsun;

Üç adet sunucumuz bulunsun. Sunuculardan biri yük paylaşımının yapılacağı, diğer ikisi ise web uygulamasının bulunacağı sunucular olsun.

Server 1

Nginx web sunucusunun kurulu olacağı ve gelen isteklerin diğer web sunucularına nasıl paylaştırılacağına karar veren sunucumuz.

Name: loadbalancer
IP: 192.168.1.11

Server 2

Nodejs web uygulamasının bulunacağı sunucu.

Name: web1
IP: 192.168.1.12

Server 3

Nodejs web uygulamasının bulunacağı diğer sunucu.

Name: web2
IP: 192.168.1.13


Vagrant Yapılandırması

Öncelikle dizin planımızı şöyle hazırlayalım. Resimdeki gibi üç ayrı dizin oluşturalım ve her birinin içerisine Vagrantfile adında birer dosya oluşturalım.

Sakarya Üniversitesi Javascript Eğitimi

Vagrantfile içeriklerimiz aşağıdaki gibi olsun;

server1 / Vagrantfile

NAME = 'loadbalancer'  
IP = "192.168.1.11"

Vagrant.configure("2") do |config|  
  config.vm.box = "ubuntu/trusty64"
  config.vm.hostname = NAME
  config.vm.network "public_network", ip: IP

  config.vm.provider "virtualbox" do |vb|
    vb.customize ["modifyvm", :id, "--memory", '2048']
  end
end

server2 / Vagrantfile

NAME = 'web1'  
IP = "192.168.1.12"

Vagrant.configure("2") do |config|  
  config.vm.box = "ubuntu/trusty64"
  config.vm.hostname = NAME
  config.vm.network "public_network", ip: IP

  config.vm.provider "virtualbox" do |vb|
    vb.customize ["modifyvm", :id, "--memory", '2048']
  end
end

server3 / Vagrantfile

NAME = 'web2'  
IP = "192.168.1.13"

Vagrant.configure("2") do |config|  
  config.vm.box = "ubuntu/trusty64"
  config.vm.hostname = NAME
  config.vm.network "public_network", ip: IP

  config.vm.provider "virtualbox" do |vb|
    vb.customize ["modifyvm", :id, "--memory", '2048']
  end
end

Vagrantfile içeriklerinde değişien tek şey IP adresleri ve sunucu isimleri oldu. Dilerseniz ek konfigürasyonlar ekleyebilirsiniz tabiki.

Şimdi Vagrant sunucularımızı ayağa kaldıralım.

Server1 için;
[email protected]:~/Desktop/loadbalancing/server1$ vagrant up  
Server2 için;
[email protected]:~/Desktop/loadbalancing/server2$ vagrant up  
Server3 için;
[email protected]:~/Desktop/loadbalancing/server3$ vagrant up  

Sunucu konfigürasyonları

Server2 ve Server3

Aşağıdaki işlemleri server2 ve server3 için ayrı ayrı yapmamız gerekiyor.

Bu iki sunucumuzda da aynı web uygulaması bulunacak. Aynı kurulumlar yapılacak.

Web uygulaması NodeJS ile çalışacak. Hızlı bir kurulum yapıp test edebilmek adına express ile çalışacağız.

NodeJS Kurulumu
[email protected]:~/Desktop/loadbalancing/server2$ vagrant ssh  
[email protected]:~$ sudo apt-get update  
[email protected]:~$ sudo apt-get install nodejs npm -y  
[email protected]:~$ sudo ln -s /usr/bin/nodejs /usr/bin/node  
Express kurulumu ve uygulamayı ayağa kaldırmak
[email protected]:~$ sudo npm install express-generator -g  
[email protected]:~$ sudo mkdir /var/www && cd /var/www  
[email protected]:~$ sudo express .  
[email protected]:~$ sudo npm install  
[email protected]:~$ npm start  

Uygulamamızı ayağa kaldırdık. Hemen test edelim.

Web tarayıcımızdan, web1 ve web2 sunucularımızda koşturan NodeJS uygulamasına erişelim.

http://192.168.1.12:3000
veya
http://192.168.1.13:3000

adreslerine erişmeye çalıştığımızda express' in aşağıdaki karşılama ekranı ile karşılaşacağız. Eğer iki IP adresinde de bu ekran ile karşılaşıyorsak nodejs uygulamasını başarıyla çalıştırmışız demektir.

Sakarya Üniversitesi Javascript Eğitimi

Server 1

Aşağıdaki komut ile sunucumuzun komut satırı arayüzüne erişelim.

[email protected]:~/Desktop/loadbalancing/server1$ vagrant ssh  

Nginx kurulumunu yapalım.

[email protected]:~$ sudo apt-get install nginx -y  

Nginx konfigürasyonunu yapalım.

vagra[email protected]:~$ sudo vi /etc/nginx/sites-available/default  

Nginx'in varsayılan ayarlarının bulunduğu dosyayı bir komut satırı editörü olan vi ile açtık. Şimdi bu dosyanın içeriğini tamamen silelim ve aşağıdaki kodları yapıştıralım.

Vi editörünü kullanarak dosya üzerinde değişiklik yapabilmek için insert moduna geçmeniz gerekiyor. Klavyenizden i tuşuna basarak bu moda geçebilirsiniz. Insert modundan çıkmak için escape tuşuna basmalısınız. Herhangi satırı komple simek için, insert modunda değilken d tuşuna ardarda iki kere basmalısınız. Dosyayı kaydedip çıkmak için ise yine insert modunda değilken :wq yazıp enter tuşuna basmanız gerekiyor. Kaydetmeden çıkmak için ise :q!. Daha fazlası şurada.

upstream servers {  
          server 192.168.1.12:3000;
          server 192.168.1.13:3000;
}

server {  
        listen 80;

        location / {
            proxy_pass http://servers;
        }
}

Yukarıdaki kodun upstream kısmında bulunan IP adresleri web uygulamalarımızın çalıştığı sunucunun ip adresini ve dinlediği portu belirtmekte.

Kaydedip çıkalım ve Nginx'i yeniden başlatalım.

[email protected]:~$ sudo service nginx reload  

Şimdi web tarayıcımıza gidelim loadbalancer sunucumuzun IP adresine erişmeye çalışalım.

http://192.168.1.11/

Sakarya Üniversitesi Javascript Eğitimi

Eğer bu ekran ile karşılaşıyorsanız, hayırlı olsun nur topu gibi bir load balancer'ınız oldu.

Sakarya Üniversitesi Javascript Eğitimi

"Yok arkadaş ben inanmadım, kanıtla" dersen de şöyle bir şey yapabiliriz. Web uygulamamızın koştuğu iki ayrı sunucu vardı. Bu sunucuların döndüğü cevabı değiştirelim ve tekrar test edelim. Göreceksiniz ki her refresh yapışınızda farklı sunucuya yönlendirileceksiniz.

Server 2 için (web1)

[email protected]:~/Desktop/loadbalancing/server2$ vagrant ssh  
[email protected]:~$ sudo vi routes/index.js  

Aşağıdaki satırı,

res.render('index', { title: 'Express' });  

Aşağıdaki satır ile değiştirelim.

res.render('index', { title: 'Served from Web1' });  


Server 3 için (web2)

[email protected]:~/Desktop/loadbalancing/server3$ vagrant ssh  
[email protected]:~$ sudo vi routes/index.js  

Aşağıdaki satırı,

res.render('index', { title: 'Express' });  

Aşağıdaki satır ile değiştirelim.

res.render('index', { title: 'Served from Web2' });  

Şimdi http://192.168.1.11/ adresine gidin ve sayfayı hızlıca yenileyin. Göreceksiniz ki en müsait sunucu hangisi ise ona yönlendirileceksiniz. Sakarya Üniversitesi Javascript Eğitimi Sakarya Üniversitesi Javascript Eğitimi

Performans testleri

Şimdi load balancerdan önce ve sonraki performans durumuna bakalım.

Apache Benchmark aracı ile testimizi yapalım.

n: Gerçekleştirilecek istek sayısı
c: Bir seferde gerçekleştirilecek birden çok istek sayısı.

Load balancer olmadan

[email protected]:~$ ab -n 2000 -c 100 http://192.168.1.12:3000/  

Sonuç

Server Software:  
Server Hostname:        192.168.1.12  
Server Port:            3000

Document Path:          /  
Document Length:        197 bytes

Concurrency Level:      100  
Time taken for tests:   16.932 seconds  
Complete requests:      2000  
Failed requests:        0  
Total transferred:      786000 bytes  
HTML transferred:       394000 bytes  
Requests per second:    118.12 [#/sec] (mean)  
Time per request:       846.616 [ms] (mean)  
Time per request:       8.466 [ms] (mean, across all concurrent requests)  
Transfer rate:          45.33 [Kbytes/sec] received

Connection Times (ms)  
              min  mean[+/-sd] median   max
Connect:        0    1   1.4      0      10  
Processing:    55  826 138.7    819    1171  
Waiting:       55  825 138.7    819    1171  
Total:         57  827 138.1    820    1172

Percentage of the requests served within a certain time (ms)  
  50%    820
  66%    857
  75%    894
  80%    916
  90%    954
  95%   1017
  98%   1086
  99%   1154
 100%   1172 (longest request)

Load balancer ile

[email protected]:~$ ab -n 2000 -c 100 http://192.168.1.11/  

Sonuç

Server Software:        nginx/1.4.6  
Server Hostname:        192.168.1.11  
Server Port:            80

Document Path:          /  
Document Length:        197 bytes

Concurrency Level:      100  
Time taken for tests:   12.773 seconds  
Complete requests:      2000  
Failed requests:        0  
Total transferred:      846000 bytes  
HTML transferred:       394000 bytes  
Requests per second:    156.59 [#/sec] (mean)  
Time per request:       638.629 [ms] (mean)  
Time per request:       6.386 [ms] (mean, across all concurrent requests)  
Transfer rate:          64.68 [Kbytes/sec] received

Connection Times (ms)  
              min  mean[+/-sd] median   max
Connect:        0    1   1.9      0      19  
Processing:    39  622 182.3    592    1024  
Waiting:       39  622 182.3    592    1024  
Total:         41  623 182.1    595    1024

Percentage of the requests served within a certain time (ms)  
  50%    595
  66%    672
  75%    743
  80%    821
  90%    900
  95%    938
  98%    967
  99%    974
 100%   1024 (longest request)

Kapanış

Test sonuçlarına baktığımızda 2000 isteğin karşılanması için;

Geçen Zaman

Load balancer olmadan: 16.932sn
Load balancer ile: 12.773sn

Saniyede karşılanan istek sayısı

Load balancer olmadan: 118.12
Load balancer ile: 156.59

Fark ortada. Toplam 2000 istekte 4 saniyenin biraz üzerinde kârımız var ve saniyede 38 tane fazladan istek işlemiş olduk.



Oldu o zaman kaçtım ben.

nodejs dersleri