giriiş
Flask, küçük ve orta ölçekli uygulamalar oluşturmak için hafif ve esnek bir web çerçevesidir. Basit kişisel bloglardan REST API'leri, SaaS platformları, e-ticaret web siteleri ve veri odaklı panolar gibi daha karmaşık uygulamalara kadar çeşitli projelerde yaygın olarak kullanılır.
Ancak, uygulamanızın trafiği veya karmaşıklığı arttıkça performans darboğazları yaşayabilirsiniz. İster bir içerik yönetim sistemi (CMS), ister bir mobil uygulama için bir API veya gerçek zamanlı veri görselleştirme aracı geliştiriyor olun, Flask performansını optimize etmek, duyarlı ve ölçeklenebilir bir kullanıcı deneyimi sunmak için çok önemlidir.
Bu eğitimde, bir Flask uygulamasının performansını optimize etmek için teknikleri ve en iyi uygulamaları keşfedeceksiniz.
Ön koşullar
- Ubuntu çalıştıran bir sunucu ve sudo ayrıcalıklarına ve etkin bir güvenlik duvarına sahip, kök olmayan bir kullanıcı. Kurulum talimatları için lütfen bu listeden dağıtımınızı seçin ve Sunucuya Başlarken kılavuzumuzu izleyin. Lütfen desteklenen bir Ubuntu sürümü çalıştırdığınızdan emin olun.
- Linux Komut Satırını Tanımak Komut satırına giriş veya bilgilerinizi tazelemek için Linux Komut Satırı Kılavuzu'ndaki bu kılavuza göz atabilirsiniz.
- Python programlamanın temel bilgisi.
- Ubuntu sisteminizde Python 3.7 veya üzeri yüklü olmalıdır. Ubuntu'da Python betiklerinin nasıl çalıştırılacağını öğrenmek için Ubuntu'da Python betiklerinin nasıl çalıştırılacağına dair eğitimimize başvurabilirsiniz.
Flask ortamınızı kurma
Ubuntu 24.04, varsayılan olarak Python 3 ile birlikte gelir. Python 3 kurulumunuzu tekrar kontrol etmek için bir terminal açın ve aşağıdaki komutu çalıştırın:
root@ubuntu:~# python3 --version
Python 3.12.3Bilgisayarınızda Python 3 yüklüyse, yukarıdaki komut Python 3 kurulumunun güncel sürümünü döndürür. Yüklü değilse, aşağıdaki komutu çalıştırıp Python 3 kurulumunu alabilirsiniz:
root@ubuntu:~# sudo apt install python3
Daha sonra sisteminize pip paket yükleyicisini kurmanız gerekiyor:
root@ubuntu:~# sudo apt install python3-pip
Pip'i kurduktan sonra Flask'ı kuralım.
Flask'ı pip aracılığıyla kuracaksınız. Sisteminizdeki diğer paketlerle çakışmaması için bunu sanal bir ortamda yapmanız önerilir.
root@ubuntu:~# python3 -m venv myprojectenv root@ubuntu:~# source myprojectenv/bin/activate
root@ubuntu:~# pip install Flask
Bir Flask uygulaması oluşturun
Bir sonraki adım, Flask uygulaması için Python kodunu yazmaktır. Yeni bir betik oluşturmak için istediğiniz dizine gidin:
root@ubuntu:~# cd ~/path-to-your-script-directory
Dizine girdikten sonra, app.py adında yeni bir Python dosyası oluşturun ve Flask'ı içe aktarın. Ardından, bir Flask uygulaması başlatın ve bir kök yolu oluşturun.
root@ubuntu:~# nano app.py
Boş bir metin düzenleyici açılacaktır. Mantığınızı buraya yazın veya aşağıdaki kodu kopyalayın:
from flask import Flask, jsonify, request
app = Flask(__name__)
# Simulate a slow endpoint
@app.route('/slow')
def slow():
import time
time.sleep(2) # to simulate a slow response
return jsonify(message="This request was slow!")
# Simulate an intensive database operation
@app.route('/db')
def db_operation():
# This is a dummy function to simulate a database query
result = {"name": "User", "email": "[email protected]"}
return jsonify(result)
# Simulate a static file being served
@app.route('/')
def index():
return "<h1>Welcome to the Sample Flask App</h1>"
if __name__ == '__main__':
app.run(debug=True)Şimdi Flask uygulamasını çalıştıralım:
root@ubuntu:~# flask run
Aşağıdaki curl komutlarıyla uç noktaları test edebilirsiniz:
/ uç noktasını test edin (statik içerik döndürür):
root@ubuntu:~# curl http://127.0.0.1:5000/[secondary_lebel Output]
<h1>Welcome to the Sample Flask App</h1>%Son noktayı test et/yavaş (yavaş bir tepkiyi simüle eder):
root@ubuntu:~# time curl http://127.0.0.1:5000/db
Bu yavaş uç noktayı kontrol etmek için Linux'taki time komutunu kullanırız. time komutu, belirli bir komutun veya programın yürütme süresini ölçmek için kullanılır. Üç ana bilgi sağlar:
- Gerçek Zaman: Komutun başlangıcından sonuna kadar geçen gerçek zaman.
- Kullanıcı Süresi: Kullanıcı modunda harcanan CPU süresi miktarı.
- Sistem Zamanı: Çekirdek modunda harcanan CPU zamanı miktarı.
Bu, yavaş uç noktamızın harcadığı gerçek süreyi ölçmemize yardımcı olacaktır. Çıktı şuna benzer olabilir:
Output
{"message":"This request was slow!"}
curl http://127.0.0.1:5000/slow 0.00s user 0.01s system 0% cpu 2.023 totalBu isteğin yanıtlanması yaklaşık 2 saniye sürer, çünkü time.sleep(2) çağrısı yavaş bir yanıtı simüle eder.
/db uç noktasını test edelim (veritabanı işlemlerini simüle eder):
root@ubuntu:~# curl http://127.0.0.1:5000/db
Output
{"email":"[email protected]","name":"User"}Bu uç noktaları curl kullanarak test ederek Flask uygulamanızın doğru şekilde çalıştığını ve yanıtların beklendiği gibi olduğunu doğrulayabilirsiniz.
Bir sonraki bölümde çeşitli teknikleri kullanarak uygulama performansını nasıl optimize edeceğinizi öğreneceksiniz.
Üretime hazır bir WSGI sunucusu kullanın
Flask'ın yerleşik geliştirme sunucusu üretim ortamları için tasarlanmamıştır. Eşzamanlı istekleri etkili bir şekilde yönetmek için Gunicorn gibi üretime hazır bir WSGI sunucusuna geçmelisiniz.
Gunicorn'u kurun ve başlatın
Gunicorn'u kuralım.
root@ubuntu:~# pip install gunicornFlask uygulamasını Gunicorn kullanarak 4 çalışan işlemle çalıştırın:
root@ubuntu:~# gunicorn -w 4 -b 0.0.0.0:8000 app:app
Output
% /Library/Python/3.9/bin/gunicorn -w 4 -b 0.0.0.0:8000 app:app
[2024-09-13 18:37:24 +0530] [99925] [INFO] Starting gunicorn 23.0.0
[2024-09-13 18:37:24 +0530] [99925] [INFO] Listening at: http://0.0.0.0:8000 (99925)
[2024-09-13 18:37:24 +0530] [99925] [INFO] Using worker: sync
[2024-09-13 18:37:24 +0530] [99926] [INFO] Booting worker with pid: 99926
[2024-09-13 18:37:25 +0530] [99927] [INFO] Booting worker with pid: 99927
[2024-09-13 18:37:25 +0530] [99928] [INFO] Booting worker with pid: 99928
[2024-09-13 18:37:25 +0530] [99929] [INFO] Booting worker with pid: 99929
[2024-09-13 18:37:37 +0530] [99925] [INFO] Handling signal: winch
^C[2024-09-13 18:38:51 +0530] [99925] [INFO] Handling signal: int
[2024-09-13 18:38:51 +0530] [99927] [INFO] Worker exiting (pid: 99927)
[2024-09-13 18:38:51 +0530] [99926] [INFO] Worker exiting (pid: 99926)
[2024-09-13 18:38:51 +0530] [99928] [INFO] Worker exiting (pid: 99928)
[2024-09-13 18:38:51 +0530] [99929] [INFO] Worker exiting (pid: 99929)
[2024-09-13 18:38:51 +0530] [99925] [INFO] Shutting down: MasterGunicorn kullanmanın faydaları şunlardır:
- Eşzamanlı istek işleme: Gunicorn, birden fazla çalışan işlem kullanılarak birden fazla isteğin aynı anda işlenmesine olanak tanır.
- Yük Dengeleme: Çalışan süreçler arasında gelen istekleri dengeler ve sunucu kaynaklarının optimum şekilde kullanılmasını sağlar.
- Asenkron çalışanlar: gevent gibi asenkron çalışanlarla, diğer istekleri engellemeden uzun süren görevler verimli bir şekilde yürütülebilir.
- Ölçeklenebilirlik: Gunicorn, daha fazla eşzamanlı isteği işlemek için çalışan süreçlerin sayısını artırarak yatay olarak ölçeklenebilir.
- Hata toleransı: Tepki vermeyen veya arızalı çalışanları otomatik olarak değiştirir ve yüksek kullanılabilirlik sağlar.
- Üretime Hazır: Flask geliştirme sunucusunun aksine, Gunicorn daha iyi güvenlik, kararlılık ve performans özellikleriyle üretim ortamları için optimize edilmiştir.
Üretim için Gunicorn'a geçerek Flask uygulamanızın verimini ve yanıt verme hızını önemli ölçüde iyileştirebilir, onu gerçek dünya trafiğini verimli bir şekilde işlemeye hazırlayabilirsiniz.
Yükü azaltmak için önbelleğe almayı etkinleştirin.
Önbelleğe alma, ek yükü azaltarak Flask performansını artırmanın en iyi yollarından biridir. Burada, yavaş yolun sonucunu önbelleğe almak için Flask-Caching özelliğini eklersiniz.
Redis ile Flask-Caching'i yükleyin ve yapılandırın
Gerekli paketleri kurun:
Yavaş/yol'a önbellek eklemek için app.py'yi güncelleyin
Editörü açın ve app.py dosyasını aşağıdaki komutla güncelleyin:
root@ubuntu:~# nano app.py
from flask_caching import Cache
app = Flask(__name__)
# Configure Flask-Caching with Redis
app.config['CACHE_TYPE'] = 'redis'
app.config['CACHE_REDIS_HOST'] = 'localhost'
app.config['CACHE_REDIS_PORT'] = 6379
cache = Cache(app)
@app.route('/slow')
@cache.cached(timeout=60)
def slow():
import time
time.sleep(2) # Simulate a slow response
return jsonify(message="This request was slow!")/slow'a yapılan ilk istekten sonraki istekler, time.sleep() fonksiyonu atlanarak 60 saniye içinde önbellekten karşılanır. Bu, sunucu yükünü azaltır ve yanıt hızını artırır.
Not: Bu eğitimde Redis ana bilgisayarı olarak localhost kullanıyoruz. Ancak, üretim ortamında DigitalOcean Managed Redis gibi yönetilen bir Redis hizmeti kullanmanız önerilir. Bu, depolama ihtiyaçlarınız için daha iyi ölçeklenebilirlik, güvenilirlik ve güvenlik sağlar. DigitalOcean Managed Redis'i üretim düzeyindeki bir uygulamaya entegre etme hakkında daha fazla bilgiyi Uygulama Platformunda DigitalOcean Redis Kullanarak Depolama adlı bu eğitimde bulabilirsiniz.
Verilerin önbelleğe alınıp alınmadığını kontrol etmek için /slow uç noktası için aşağıdaki komutları çalıştırıyoruz.
Bu, /slow uç noktasına yapılan ilk istektir. Bu istek tamamlandıktan sonra, /slow rotasının sonucu önbelleğe alınır.
root@ubuntu:~# time curl http://127.0.0.1:5000/slow
Output
{"message":"This request was slow!"}
curl http://127.0.0.1:5000/slow 0.00s user 0.01s system 0% cpu 2.023 totalBu, 60 saniye içinde /slow uç noktasına yapılan sonraki bir istektir:
root@ubuntu:~# time curl http://127.0.0.1:5000/slow
Output
{"message":"This request was slow!"}
curl http://127.0.0.1:5000/slow 0.00s user 0.00s system 0% cpu 0.015 totalVeritabanı sorgularını optimize edin
Veritabanı sorguları genellikle performans darboğazına neden olabilir. Bu bölümde, SQLAlchemy ve birleştirme havuzunu kullanarak veritabanı sorgu optimizasyonunu simüle edeceksiniz.
Birleştirme toplamasıyla bir veritabanı sorgusunun simülasyonu
Öncelikle SQLAlchemy’i kuralım.
root@ubuntu:~# pip install Flask-SQLAlchemy
Bağlantı entegrasyonunu yapılandırmak için app.py'yi güncelleyin.
rom flask_sqlalchemy import SQLAlchemy
from sqlalchemy import text
# Simulate an intensive database operation
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_POOL_SIZE'] = 5 # Connection pool size
db = SQLAlchemy(app)
@app.route('/db1')
def db_operation_pooling():
# Simulate a database query
result = db.session.execute(text('SELECT 1')).fetchall()
return jsonify(result=str(result))Şimdi curl isteğini db1 yoluna uyguladığımızda aşağıdaki çıktıyı görmeliyiz:
root@ubuntu:~# curl http://127.0.0.1:5000/db1
output
{"result":"[(1,)]"}Üretim ortamında bağlantı havuzunu uygulayarak Flask uygulamanızın performansını önemli ölçüde optimize edebilirsiniz. Bağlantı havuzu, uygulamanın her istek için yeni bağlantılar oluşturmak yerine mevcut veritabanı bağlantılarını yeniden kullanmasına olanak tanır. Bu, yeni bağlantılar oluşturmanın getirdiği ek yükü azaltarak daha hızlı yanıt süreleri ve gelişmiş ölçeklenebilirlik sağlar.
Daha önce belirlediğimiz SQLALCHEMY_POOL_SIZE yapılandırması, havuzdaki bağlantı sayısını sınırlar. Bu değeri, üretim ortamında özel ihtiyaçlarınıza ve sunucu kapasitenize göre ayarlamalısınız. Ayrıca, havuz doluysa ek bağlantılara izin vermek için SQLALCHEMY_MAX_OVERFLOW ve bir isteğin bağlantı için ne kadar beklemesi gerektiğini belirtmek için SQLALCHEMY_POOL_TIMEOUT gibi diğer entegrasyon seçeneklerini de değerlendirebilirsiniz.
Örneğimiz basitlik açısından SQLite kullansa da, gerçek dünya senaryosunda muhtemelen PostgreSQL veya MySQL gibi daha sağlam bir veritabanı kullanıyorsunuzdur. Bu veritabanlarının, daha iyi performans için SQLAlchemy entegrasyonuyla birlikte kullanılabilen kendi bağlantı havuzlama mekanizmaları vardır.
Bağlantı havuzlamasının dikkatli bir şekilde yapılandırılması ve kullanılmasıyla, Flask uygulamanızın yoğun yük altında bile veritabanı işlemlerini verimli bir şekilde gerçekleştirmesini sağlayabilir ve böylece genel performansını önemli ölçüde artırabilirsiniz.
Gzip sıkıştırmasını etkinleştir
Yanıtlarınızı sıkıştırmak, sunucunuz ve istemcileriniz arasında aktarılan veri miktarını önemli ölçüde azaltabilir ve performansı artırabilir.
Flask-Compress'i yükleyin ve yapılandırın
Flask-compress paketini kuralım.
root@ubuntu:~# pip install Flask-Compress
Şimdi sıkıştırmayı etkinleştirmek için app.py'yi güncelleyelim.
from flask_compress import Compress
# This below command enables Gzip compression for the Flask app
# It compresses responses before sending them to clients,
# reducing data transfer and improving performance
Compress(app)
@app.route('/compress')
def Compress():
return "<h1>Welcome to the optimized Flask app !</h1>"Bu, 500 bayttan büyük yanıtları otomatik olarak sıkıştırır ve büyük yanıtların iletim süresini azaltır.
Üretim ortamında Gzip sıkıştırması, özellikle HTML, CSS ve JavaScript gibi metin tabanlı içerikler için sunucu ile istemciler arasında aktarılan veri miktarını önemli ölçüde azaltabilir.
Veri aktarımındaki bu azalma, daha hızlı sayfa yükleme süreleri, gelişmiş kullanıcı deneyimi ve daha düşük bant genişliği maliyetleriyle sonuçlanır. Ayrıca, birçok modern web tarayıcısı Gzip sıkıştırmasını otomatik olarak destekler ve bu da onu tamamen uyumlu bir optimizasyon tekniği haline getirir. Gzip sıkıştırmasını etkinleştirerek, istemci tarafında herhangi bir değişiklik yapmanıza gerek kalmadan Flask uygulamanızın performansını ve ölçeklenebilirliğini etkili bir şekilde artırabilirsiniz.
Yoğun görevlerin Celery'e yüklenmesi
E-posta gönderme veya büyük veri kümelerini işleme gibi kaynak yoğun işlemler için, bunları Celery kullanarak arka plan işlerine aktarmak en iyisidir. Bu, uzun süreli görevlerin gelen istekleri engellemesini önler.
Celery, zaman alıcı görevleri eşzamansız olarak yürütmenizi sağlayan güçlü bir dağıtılmış görev sıralama sistemidir. Yoğun işlemleri Celery'e devrederek, Flask uygulamanızın yanıt hızını ve ölçeklenebilirliğini önemli ölçüde artırabilirsiniz. Celery, görevleri ayrı makinelerde çalışabilen çalışan süreçlere devrederek daha iyi kaynak kullanımı ve paralel işleme olanağı sağlar.
Kerevizin başlıca faydaları şunlardır:
- Kullanıcı isteklerine yanıt verme süresini iyileştirin
- Daha iyi ölçeklenebilirlik ve kaynak yönetimi
- Ana programı engellemeden karmaşık ve zaman alıcı görevleri gerçekleştirme yeteneği
- Görev planlama ve başarısız görevleri yeniden deneme için yerleşik destek
- RabbitMQ veya Redis gibi çeşitli mesaj aracılarıyla kolay entegrasyon
Celery'i kullanarak, Flask uygulamanızın hesaplama yoğunluğu yüksek veya G/Ç gerektiren görevlerle uğraşırken bile duyarlı kalmasını sağlayabilirsiniz.
Arka plan görevleri için Celery'i yapılandırın
Celery'i kuralım.
root@ubuntu:~# pip install Celery
Şimdi, Celery'i asenkron görevler için yapılandırmak üzere app.py'yi güncelleyelim:
from celery import Celery
celery = Celery(app.name, broker='redis://localhost:6379/0')
@celery.task
def long_task():
import time
time.sleep(10) # Simulate a long task
return "Task Complete"
@app.route('/start-task')
def start_task():
long_task.delay()
return 'Task started'Ayrı bir terminalde Celery işçisini başlatın:
root@ubuntu:~# celery -A app.celery worker --loglevel=info
Output
------------- celery@your-computer-name v5.2.7 (dawn-chorus)
--- ***** -----
-- ******* ---- Linux-x.x.x-x-generic-x86_64-with-glibc2.xx 2023-xx-xx
- *** --- * ---
- ** ---------- [config]
- ** ---------- .> app: app:0x7f8b8c0b3cd0
- ** ---------- .> transport: redis://localhost:6379/0
- ** ---------- .> results: disabled://
- *** --- * --- .> concurrency: 8 (prefork)
-- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
--- ***** -----
-------------- [queues]
.> celery exchange=celery(direct) key=celery
[tasks]
. app.long_task
[2023-xx-xx xx:xx:xx,xxx: INFO/MainProcess] Connected to redis://localhost:6379/0
[2023-xx-xx xx:xx:xx,xxx: INFO/MainProcess] mingle: searching for neighbors
[2023-xx-xx xx:xx:xx,xxx: INFO/MainProcess] mingle: all alone
[2023-xx-xx xx:xx:xx,xxx: INFO/MainProcess] celery@your-computer-name ready.Şimdi /start-task yoluna ulaşmak için curl komutunu çalıştırın, çıktı aşağıdaki gibi olacaktır:
root@ubuntu:~# curl http://127.0.0.1:5000/start-task
Output
Task startedBu, arka plan işi hala çalışıyor olsa bile, hemen hemen anında "Görev başlatıldı" mesajını döndürecektir.
start_task() fonksiyonu iki şey yapar:
- Celery görevini eşzamansız olarak başlatan long_task.delay() işlevini çağırır. Bu, görevin arka planda çalışmak üzere sıraya alındığı, ancak işlevin tamamlanmasını beklemediği anlamına gelir.
- Hemen "Görev başlatıldı" dizesini döndürür.
Dikkat edilmesi gereken önemli bir nokta, uzun süreli görevin (10 saniyelik uykuyla simüle edilen) Celery tarafından eşzamansız olarak yürütülmesidir. Flask rotası, isteğe yanıt vermeden önce bu görevin tamamlanmasını beklemez.
Yani bu uç noktayı bozduğunuzda hemen "iş başladı" yanıtını alırsınız, ancak gerçek iş arka planda 10 saniye boyunca çalışmaya devam eder.
Arka plan işi tamamlandıktan 10 saniye sonra şu rapor mesajını görmelisiniz:
Çıktı şuna benzer olacaktır:
[2024-xx-xx xx:xx:xx,xxx: INFO/MainProcess] Task app.long_task[task-id] received
[2024-xx-xx xx:xx:xx,xxx: INFO/ForkPoolWorker-1] Task app.long_task[task-id] succeeded in 10.xxxs: 'Task Complete'Bu örnek, Celery'nin uzun süre çalışan görevleri eşzamansız olarak yürüterek ana uygulamanın yanıt vermesini sağlayarak bir Flask uygulamasının performansını nasıl iyileştirdiğini göstermektedir. Uzun süre çalışan görev arka planda çalışarak Flask uygulamasını diğer istekleri işlemek üzere serbest bırakır.
Üretim ortamında Celery'i çalıştırmak aşağıdakileri içerir:
- RabbitMQ gibi sağlam bir mesaj aracısı kullanma
- Özel bir sonuç arka ucu (örneğin, PostgreSQL) kullanma
- Çalışanları süreç kontrol sistemleriyle yönetin (örneğin, süpervizör)
- İzleme araçlarını uygulayın (örneğin çiçekler) Hata işleme ve günlüğe kaydetmeyi artırın
- Arttırılmış hata işleme ve günlük kaydı
- Görev önceliklendirmesini kullanın
- Farklı makinelerde birden fazla çalışanla ölçeklendirme
- Uygun güvenlik önlemlerinin sağlanması
Sonuç
Bu eğitimde, çeşitli performans iyileştirme tekniklerini uygulayarak Flask uygulamanızı nasıl optimize edeceğinizi öğrendiniz. Bu adımları izleyerek, Flask uygulamanızın performansını, ölçeklenebilirliğini ve yanıt verme hızını iyileştirebilir ve ağır yükler altında bile verimli bir şekilde çalışmasını sağlayabilirsiniz.









