Php5 + MySQL saniyede 200 istek üzerine nasıl ölçeklendirilir?


16

Performans için ana sayfamı değiştiriyorum, şu anda 3.14.by'de yaklaşık 200 istek / saniye işlemektedir.

Garip bir şekilde, bazı VPS ve özel Atom 330 sunucusunda sayılar hemen hemen aynı.

Sunucu yazılımı şöyledir: Apache2 + mod_php prefork 4 childs (burada farklı sayıları denedim), php5, APC, nginx, PHP oturumları depolaması için memcached.

MySQL, kullanılabilir RAM'in yaklaşık% 30'unu tüketecek şekilde yapılandırılmıştır (VPS'de ~ 150Mb, özel sunucuda 700Mb)

Görünüşe bakılırsa, bir yerlerde daha yükseğe çıkmama izin vermeyen bir darboğaz var mı? (yani 6 SQL'den daha az yapmanın daha hızlı olacağını biliyorum, ancak sqld önbelleğe alınmış sorgular nedeniyle en fazla% birkaç fazla yediği için bu sınırlayıcı bir faktör gibi görünmüyor)

Herkes önceden apache2 tekme ve sadece nginx + php bırakmanın çok daha hızlı olduğunu test etti mi?

Biraz daha kıyaslama

Small 40-byte static file: 1484 r/s via nginx+apache2, 2452 if we talk to apache2 directly. 
Small "Hello world" php script: 458 r/s via ngin+apache2.

Güncelleme: Görünüşe göre, darboğaz önbellekteki verilerde MySQL performansı. Tek SQL içeren sayfa 354req / sn, 6 SQL - 180 req / sn gösterir. Sence burada ne ayarlayabilirim? (MySQL için 100-200 Mb çatabilirim)

[client]
port        = 3306
socket      = /var/run/mysqld/mysqld.sock

[mysqld_safe]
socket      = /var/run/mysqld/mysqld.sock
nice        = 0

[mysqld]
default-character-set=cp1251
collation-server=cp1251_general_cs

skip-character-set-client-handshake

user        = mysql
pid-file    = /var/run/mysqld/mysqld.pid
socket      = /var/run/mysqld/mysqld.sock
port        = 3306
basedir     = /usr
datadir     = /var/lib/mysql
tmpdir      = /tmp
skip-external-locking

bind-address        = 127.0.0.1

key_buffer      = 16M
max_allowed_packet  = 8M
thread_stack        = 64K
thread_cache_size   = 16
sort_buffer_size    = 8M
read_buffer_size    = 1M

myisam-recover      = BACKUP
max_connections        = 650
table_cache            = 256
thread_concurrency     = 10

query_cache_limit       = 1M
query_cache_size        = 16M

expire_logs_days    = 10
max_binlog_size         = 100M

[mysqldump]
quick
quote-names
max_allowed_packet  = 8M

[mysql]
[isamchk]
key_buffer      = 8M

!includedir /etc/mysql/conf.d/

Neden hem Apache hem de nginx kullanıyorsunuz?
jamieb

Bu yaygın yapılandırma, Apache2'den PHP'ye ve apache altyapısı gerektiren çeşitli uygulamalar, yükte apache2 bellek ayak izini azaltmak için nginx.
BarsMonster

Aslında sorununuzu anlamıyorum. Siteniz şu anda yavaş mı? Öyleyse, ne kadar yavaş? Ve ne kadar hızlandırmak istiyorsun? Darboğazın nerede olduğunu belirlemek için sitenizin herhangi bir bölümünü profillemeye çalıştınız mı?
jamieb

Açıklamasında: Şimdi 180-200 istek / saniye. Bu bir ana sayfa için yeterli daha sonra olsa da, ben aynı kurulumda daha hızlı çalışması için aynı kod tabanı üzerine kurulmuş diğer siteler için bu ayarı tweak istiyorum. İdeal olarak dinamik sayfalarla 100Mbit bağlantıyı doyurmak istiyorum :-)
BarsMonster 18:09

2
"Saniyedeki istek sayısı" bu bağlamda gerçekten anlamlı bir ölçüm değildir. Netbook'um "saniyede 200 istek" işleyebilir. Bu tür bir bağlantı oranı altında hangi tepki süresini elde etmek istediğinizi bize söylemelisiniz.
jamieb

Yanıtlar:


29

Açıkçası, deneyebileceğiniz çok şey var. En iyi seçeneğiniz, dizinleri (bunlar için günlükleri etkinleştir) kullanmayan sorgular ve optimize edilmemiş diğer sorgular için günlüklerinizi takip etmektir. Yıllar boyunca performansla ilgili seçeneklerin büyük bir listesini derledim, bu yüzden bilgileriniz için buraya küçük bir alt küme ekledim - umarım yardımcı olur. İşte deneyebileceğiniz şeyler için bazı genel notlar (henüz yapmadıysanız):

MySQL

  • query_cache_type = 1 - önbellek SQL sorguları açık. 2 olarak ayarlanırsa, sorgular yalnızca SQL_CACHE ipucu iletilirse önbelleğe alınır. Tip 1'de olduğu gibi, SQL_NO_CACHE ipucu ile belirli bir sorgu için önbelleği devre dışı bırakabilirsiniz
  • key_buffer_size = 128M (varsayılan: 8M) - MyISAM tablo dizinleri için bellek arabelleği. Adanmış sunucularda, key_buffer_size değerini sunucudaki toplam bellek miktarının en az dörtte birine, ancak yarısından fazlasını değil olarak ayarlamayı hedefleyin
  • query_cache_size = 64M (varsayılan: 0) - sorgu önbelleğinin boyutu
  • back_log = 100 (varsayılan: 50, maks: 65535) - Bekleyen bağlantı isteklerinin kuyruğu. Yalnızca kısa sürede çok sayıda bağlantı olduğunda önemlidir
  • join_buffer_size = 1M (varsayılan: 131072) - tam tablo taramaları yaparken kullanılan bir arabellek (dizin yok)
  • table_cache = 2048 (varsayılan: 256) - max_user_connections, en ağır SQL sorgunuzun içerdiği maksimum JOIN sayısıyla çarpılmalıdır. "Open_tables" değişkenini yoğun zamanlarda kılavuz olarak kullanın. Ayrıca "open_tables" değişkenine de bakın - "open_tables" a yakın olmalıdır
  • query_prealloc_size = 32K (varsayılan: 8K) - ifadelerin ayrıştırılması ve yürütülmesi için kalıcı bellek. Karmaşık sorgularınız varsa artırın
  • sort_buffer_size = 16M (varsayılan: 2M) - sıralamada yardımcı olur (ORDER BY ve GROUP BY işlemleri)
  • read_buffer_size = 2M (varsayılan: 128K) - Sıralı taramalara yardımcı olur. Çok sayıda ardışık tarama varsa artırın.
  • read_rnd_buffer_size = 4M - MyISAM tablosunun sıralamadan sonra okumayı hızlandırmasına yardımcı olur
  • max_length_for_sort_data - sıralama dosyasındaki satır işaretçisi yerine depolanacak satır boyutu. Rastgele tablo okumalarını önleyebilir
  • key_cache_age_threshold = 3000 (varsayılan: 300) - anahtar önbelleği sıcak bölgede tutma süresi (ısınmaya indirgenmeden önce)
  • key_cache_division_limit = 50 (varsayılan: 100) - daha sofistike bir önbellek tahliye mekanizması (iki seviye) sağlar. En alt seviye için saklanacak yüzdeyi belirtir. delay_key_write = ALL - anahtar arabelleği, her dizin güncelleştirmesindeki tablo için değil, yalnızca tablo kapatıldığında temizlenir. Bu, tuşlara çok fazla yazıyor, ancak bu özelliği kullanırsanız, sunucuyu --myisam-recover = BACKUP, FORCE seçeneğiyle başlatarak tüm MyISAM tablolarının otomatik denetimini eklemelisiniz.
  • memlock = 1 - bellekteki kilit işlemi (takas giriş / çıkışını azaltmak için)

Apaçi

  • yumurtlama yöntemini değiştirme (örneğin, mpm olarak)
  • mümkünse günlükleri devre dışı bırak
  • AllowOverride None - mümkün olduğunda .htaccess'i devre dışı bırakın. Kullanılmadığı takdirde .htaccess dosyalarını aramak için apache'yi durdurur, böylece bir dosya arama isteği kaydeder
  • SendBufferSize - İşletim sistemi varsayılanına ayarla. Sıkışık ağlarda, bu parametreyi normalde indirilen en büyük dosyanın boyutuna yakın ayarlamanız gerekir
  • KeepAlive Kapalı (varsayılan Açık) - ve ağ bağlantılarını düzgün bir şekilde kapatmak için lingerd'yi yükleyin ve daha hızlı
  • DirectoryIndex index.php - Dosya listesini olabildiğince kısa ve mutlak tutun.
  • Seçenekler FollowSymLinks - Apache'deki dosya erişim işlemini basitleştirmek için
  • Mod_rewrite veya en azından karmaşık normal ifadeler kullanmaktan kaçının
  • ServerToken = eşya

PHP

  • variable_order = "GPCS" (Ortam değişkenlerine ihtiyacınız yoksa)
  • register_globals = Kapalı - güvenlik riski olmanın yanı sıra performans etkisi de vardır
  • İnclude_path komutunu olabildiğince az tutun (fazladan dosya sistemi aramalarını önler)
  • display_errors = Kapalı - Hata göstermeyi devre dışı bırak. Tüm üretim sunucuları için önemle önerilir (bir sorun olması durumunda çirkin hata mesajları göstermez).
  • magic_quotes_gpc = Kapalı
  • magic_quotes _ * = Kapalı
  • output_buffering = Açık
  • Mümkünse günlüğe kaydetmeyi devre dışı bırak
  • expose_PHP = Off
  • register_argc_argv = Kapalı
  • always_populate_raw_post_data = Kapalı
  • php ilk olarak arayacağı php.ini dosyasını yerleştirin.
  • session.gc_divisor = 1000 veya 10000
  • session.save_path = "N; / path" - Büyük siteler için kullanmayı düşünün. Oturum dosyalarını alt dizinlere böler

OS Tweaks

  • Kullanılan sabit diskleri -o noatime seçeneğiyle bağlayın (erişim süresi yok). Bu seçeneği / etc / fstab dosyasına da ekleyin.
  • En iyi sonuçların ne olduğunu görmek için / proc / sys / vm / swappiness (0'dan 100'e kadar) ayarını yapın
  • RAM Diskleri Kullan - mount --bind -ttmpfs / tmp / tmp

Bu güzel bir liste, zaten bunların çoğuna sahiptim ve kalan şeyleri eklediğimde performans artmadı. Darboğaz, PHP ve MySQL arasında sorgu önbelleğinden saniyede 800'den fazla isteği işleyememe gibi görünüyor ...
BarsMonster

Tamam, veritabanına nasıl bağlanırsınız (mysql_connect () yerine mysql_pconnect ())? Kalıcı bağlantılar kullanıyor musunuz? her iki yolu da deneyin ...
Ivan Peevski

Ben zaten pconnect ve bağlantı havuzu php.ini etkinleştirildi ...: -S
BarsMonster

Sadece bütünlük için, sadece bağlanmayı denerdim. Daha iyi performans gösteren durumlar (özellikle yük testinde) gördüm.
Ivan Peevski

1

Darboğaz CPU değilse, IO - ağ veya disk. Yani .. Ne kadar GÇ gittiğini görmelisin. (10mbps yarı dubleks bağlantıda değilseniz, ancak otomatik algılama işini doğru yapmıyorsa anahtarı kontrol etmeye değer olmadığı sürece) ağını düşünmezdim.

Bu, özellikle VPS'lerde büyük bir faktör olabilecek disk IO'sunu bırakır. Disklere göz atmak için sar veya iostat kullanın, ardından diskiniz yoğun bir şekilde kullanılıyorsa Google'a nasıl daha fazla ayrıntı bulacağınız.


Evet, Ağ sorunu değil - ab'yi yerel sunucudan çalıştırdığınızda performans aynıdır. Ben iowait süresini kontrol ettim -% 0,01'in altında - temelde her şey disk önbelleğinde ve işleme isteğinde yer alan hiçbir disk yazımı yok (tüm günlükler devre dışı).
BarsMonster

1

Nginx ( memcached ) veya Vernik ile önbellekleme içine bakmak istiyorum .

En azından SaveTheRbtz gibi Nginx ile statik dosyaları sunucu gerekir.


Bunlar dinamik sayfalardır, bu yüzden onları önbelleğe almamayı tercih ederim.
BarsMonster

1
memcached geleneksel bir önbellek uygulaması değildir ve dinamik sayfalar için harikalar yaratabilir. DB ve uygulamanız arasında oturur. Uygulamanız ilk önce bir nesne için memcached sorgular, eğer orada değilse, DB'den yüklenir. Net etki, DB'de çok daha yavaş kalıcı depolama yerine DB isteklerinizi sunmak için RAM kullanmanızdır.
jamieb

Memcache, bilinen bir özellik olan nginx ile kullanılabilir. Daha yavaş kalıcı depolama alanı kullanılmaz, hepsi MySQL'de sorgu önbelleğinde bulunur.
BarsMonster

Memcached ve MySQL'in sorgu önbelleği gerçekten karşılaştırılabilir değildir; aynı şeyi bile yapmıyorlar. Burada yayınlanan her öneriyi anlamak için uğraşmadan hemen hemen aşağı çekebilirsiniz. Biraz daha açık fikirli olmanızı tavsiye ederim.
jamieb

Memcached ve MySQL sorgu önbelleği arasındaki farkı açıkça anlıyorum. Ancak her şeyin% 100 isabet oranıyla Sorgu önbelleğinde olması nedeniyle, buna "yavaş kalıcı depolama" demezdim. Dünkü yanıt, tüm sayfaları önbelleğe almak için oldukça yaygın bir senaryo olan NginX + Memcached'ı kullanmaktı. Tek tek nesneleri önbelleğe almak başka, tamamen farklı bir senaryodur. Memcached MySQL ön masada kullanırken, ben şimdilik o olmadan daha fazla meyve suyu elde etmeyi düşünüyorum (oldukça biraz kod değişiklikleri gerektirir gibi).
BarsMonster

1

Sunucu sorunlu görünmediğinden, belki de yük üreteci olabilir. Birkaç makinede çalıştırmayı deneyin.


Sunucunun kendisinden çalıştırsam bile performans aynıdır. Eşzamanlı bağlantı nasıl yapılır - 10 veya 50. Yük testi ab -c 10 -t 10
BarsMonster

1

Bana Apache'nin izin verdiği maksimum bağlantı sayısına ulaşıyormuş gibi geliyor. Apache yapılandırmanıza bir göz atın. G / Ç veya bellek gibi başka bir sınıra bağlı değilseniz, sunucu sınırını ve maksimum istemcileri artırmak yardımcı olacaktır. Mpm_prefork_module veya mpm_worker_module için mevcut olan değerlere bakın ve ihtiyaçlarınıza göre ayarlayın.

ServerLimit 512
MaxClients 512

Eh, ben gerçekten daha sahip fazla bir sence .... fiziksel çekirdekler 2 Apache2 süreçleri * daha var inanıyoruz yüzden apache2 önünde nginx olması bu sağlanan gerekiyor
BarsMonster

Sadece bunu doğruladım. Apache2 işlemlerinin sayısının 4'ten 16'ya çıkarılması performansı hiç iyileştirmedi (hatta% 0,5 düştü). Nginx çalışanlarının sayısını 2 veya 4'e çıkarmak hiçbir şeyi iyileştirmedi.
BarsMonster

1
Verileriniz oldukça statikse, yani diğer tüm sayfa yüklerini güncellemiyorsa, sorgu_ önbelleğinizi artırabilirsiniz. MySQL sonuç kümesini bu şekilde tutacak ve bellekten çekecektir. Ancak, önbelleğe alınan tablo bu süre içinde herhangi bir yazma alırsa, önbelleği geçersiz kılar (veriler etkilenmese bile), boşa harcanmasını sağlar.
Erik Giberti

Şu anda% 100 sorgu önbellek isabet oranı görüyorum ve MySQL hala yavaş hissediyor ...
BarsMonster

1
MySQL yapılandırma dosyanıza skip-name-resol ekleyin. Bu, sunucuya yapılan her bağlantıda bir DNS aramasını kaydedecektir. Buradaki dezavantaj, tüm bağlantıların IP ile kilitlenmesi gerekeceğidir ('%' kullanmadığınız varsayılarak). SQL aynı sunucudaysa ve localhost dışında bir yere erişilmesi gerekmiyorsa, TCP / IP yığının tamamını kapatmak için atlama ağı da ekleyebilirsiniz. Ancak, darboğazın Apache olduğunu düşünüyorum.
Erik Giberti

0

Bu yük bir araç veya gerçek dünya yükleri tarafından mı oluşturuldu?

Memcached'ı kontrol etmek isteyebilirsiniz. Uygulamada gecikmeye neden olan yüksek bağlantı oranlarında sorunlar gördüm.

Bir yük jeneratörü kullanıyorsanız, küçük bir statik sayfaya bastığınızda ne elde edersiniz?

Yükler sırasında ağ yığınını TIME_WAIT koşulları açısından kontrol etmek isteyebilirsiniz. Belki de bağlantı kuyruğunuzu dolduruyorsunuzdur.

Bakabileceğiniz yaklaşık 100 neden ve öğe daha var, ancak daha fazla bilgi olmadan, sadece bu noktada tahminler atıyorum.


Ab-c 10 -t 10 URL ile test edildi Sunucunun kendisinden kıyaslama yapıyorum, bu yüzden ağ sorunu olmamalı. İsteğiniz başına daha fazla referans gönderdim.
BarsMonster

Ben ab ile ayarlama çok fazla çaba harcamak olmaz. Gerçek dünya performansına iyi dönüşmediğini görebilirsiniz. Yapmak isteyebileceğiniz şey, uygulamanızı incelemek ve her bir bileşeni test etmektir. Örneğin, apache sunucusuna doğrudan çok küçük bir statik sayfa ile vurun. Bu size ve arka uçta maksimum gereksinim / sn hakkında fikir verecektir. Nginx'i öne koyun, aynı arka uç dosyasını çağırarak yeniden test edin. Sonra basit bir "merhaba dünya" türü php sayfası ile test Bazen tüm katmanlar basit bir şey maskeleyebilir. Ayrıca, test sırasında bağlantıları izleyin. Ağ yığınınızın dolmadığından emin olun.
jeffatrackaid

Bu kriterleri dün yaptım ve güncellenmiş orijinal soru açıklamasındalar. Ayrıca, localhost üzerinde testler yapılır, bu yüzden ağ bir sorun değildir.
BarsMonster

Yerel bir ana bilgisayarda yapıldığında bile ağ bir sorun olabilir. Sizin durumunuzda olması muhtemel değil ama sorunlara neden olabilir. En azından şu anki PHP kurulumunuzla ~ 450 req / sn üst sınırınız var. Bir sonraki adım, bir veritabanı çağrısını bırakmak ve bunun nasıl değiştiğini görmektir. Yüksek düzeyde ayarlama yaparken bunu parçalamayı seviyorum çünkü gerçekten en çok soruna neden olan katmanı belirlemenize yardımcı olabilir.
jeffatrackaid

-1

Bunun gibi zaman sorunlarının yüzde 99'u veritabanına geri dönecektir. Öncelikle isabet endekslerinizin olduğundan emin olun. Bu işe yaramazsa, yapabileceğiniz her şeyi önbelleğe almaya başlayın.


Tüm dizinler ve dediğim gibi, vakaların% 100'ünde MySQL sorgu önbelleğine bile çarpıyor
BarsMonster

-1

Veritabanını web uygulamalarınıza bağlı tutmak için (mümkünse) bir bağlantı havuzu kullanmanızı öneririm (her istekte yeniden bağlantı kurmanıza gerek yoktur). Bu çok büyük bir hız farkı yaratabilir.

Ayrıca, tüm sorgularınızı EXPLAIN ile analiz etmeye çalışın (ve neden sorgularınızı SHOW PROFILE ile profillendirmiyorsunuz?).


Tüm sorgular dizin kullanır. MySQL Bağlantı havuzu kullanılır.
BarsMonster
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.