Mobil ve web geliştirmesi, son yıllarda büyük bir evrim geçirdi. Modern uygulamalar, yalnızca güçlü özelliklere sahip olmakla kalmıyor, aynı zamanda geleneksel barındırma hizmetlerinin ötesinde daha kapsamlı bir altyapıya ihtiyaç duyuyor. Bu noktada, dev şirketler like Amazon ve Google, tüm bu gereksinimleri karşılamak adına kapsamlı çözümler sunuyorlar. AWS ve Firebase gibi platformlar arasında geçiş yaparken, her adımın dikkatle planlanması ve bu karmaşık entegrasyon sürecinin doğru bir şekilde yönetilmesi, projelerin başarılı bir şekilde sunucusuz mimarilere uyum sağlaması gerekmektedir. Bu yazıda, temel aldığım AWS akışını Firebase servisleri kullanarak Firebase platformuna aktarma sürecini anlatacağım. Bu konuyu açıklarken, Firebase ve AWS platformlarının aslında birbirine ne kadar benzer yapılar sunduğunu keşfedeceğiz. Ayrıca Firebase Bulut Mesajlaşma(Firebase Cloud Messaging) servisi ile de kullanıcıya nasıl bildirim göndereceğimizi inceleyeceğiz.
AWS Akışının Tanımı
Şekil 1’deki AWS akışında kullanıcıdan bir girdi bilgisi ve bağlantı id bilgisi alınmaktadır. Alınan bu bilgiler AWS Lambda fonksiyonu ile makine öğrenmesi modellerini bulut ortamında çalıştıran Replicate servisine gitmektedir. Replicate kullanılacak olan makine öğrenmesi modellerini Uygulama Programlama Arabirimi(Application Programming Interface) veya Docker formatında kullanıcılara sunmaktadır. Biz bu yazımızda kullanacağımız modelleri UPA formatında kullanacağız. Replicate UPA’larında web kancası servisi(Webhook) yapısını kullanabilmekteyiz. Web kancası servisi yardımı ile Replicate UPA’sı üzerinden gelen dönüş farklı bir URL’e yönlendirilmektedir. Web kancası servisi ile gelen dönüş AWS Lambda ile AWS S3 bucket içerisine kaydedilmektedir. Kaydedilen dönüş Websocket yardımı ile kullanıcıya döndürülmektedir.
Yukarıda açıklanan Şekil 1’deki AWS akışı aşağıdaki adımlara firebase yapısına çevrilmiştir.
- Flask Uygulaması Kurulumu:
- Temel bir Flask projesi oluşturarak başlanır.
- Firebase Bulut Mesajlaşma Entegrasyonu:
- Flask projesinde FBM jeton(token) bilgilerin Firebase Bulut Mesajlaşma konfigürasyonları ile elde edilir.
- AWS Replicate Fonksiyonu Dönüşümü:
- AWS Replicate’e Yolla Lambda fonksiyonunu Firebase Bulut Fonksiyonları ile bulut fonksiyonu haline getirilir.
- Fonksiyon içerisinde Replicate’de kullanılan UPA’nın konfigürasyonları yapılmaktadır, bunlara ek olarak FBM jeton bilgisi ve web kancası servisi URL’i de UPA üzerinden gönderilmektedir.
- Web Kancası Servisi URL İşleme:
- Replicate’ e gönderilen Web kancası servisi URL’i Şekil 1’deki AWS S3’ye kaydet lambda fonksiyonun karşılığı olan, UPA’dan gelen resimi Google Bulut Depolama’ya kaydeden fonksiyona gönderilmektedir.
- AWS S3’ye Kaydet Fonksiyonu Dönüşümü:
- Firebase Bulut Fonksiyonu içinde:
- Replicate’ten alınan resim Google Bulut Depolama’da kaydedilir.
- Resim URL’i ve FBM jeton bilgisi çıkarılır.
- Uygulama içinde bildirim gönderen Firebase Fonksiyona POST request ile resim URL’i ve FBM jeton bilgileri gönderilmektedir.
- Firebase Bulut Fonksiyonu içinde:
- Firebase Bildirim Gönderme Fonksiyonu:
- Bu fonksiyon, FBM aracılığıyla bir bildirim göndermeyi sağlar. İsteğin JSON verisi içindeki image_url ve jeton bilgilerini alır, ardından bu bilgileri kullanarak belirtilen cihaza bir bildirim gönderir.
Flask Uygulaması
Kullanıcıya bildirim gönderebilmek için kullanıcı tarafında bir yapı olması gerektiği için basit bir Flask uygulaması oluşturuldu. Flask uygulaması içinde, kullanıcıdan gelen girdi bilgisini bir Replicate UPA’sına iletmek için, Şekil 2’deki gibi kullanıcıdan girdi alınmaktadır. Metin olarak alınan girdi bilgisi ve sayfa ilk açıldığında oluşturulan FBM jeton bilgisi Flask sunucu tarafında AWS Replicate’e Yolla Lambda fonksiyonunun karşılığı olan fonksiyona gönderilmektedir.
Firebase Bulut Mesajlaşma Entegrasyonu
Firebase Yazılım Geliştirme Seti(Software Development Kit) Oluşturma
Öncelikle Firebase konsoluna giriş yapıyoruz ardından Şekil 3’deki gösterilen şekilde yeni bir Firebase projesi oluşturuyoruz.
Oluşturduğumuz projenin içerisinde yer alan proje ayarları bölümüne geliyoruz. Proje ayarları bölümünde servis hesapları sekmesinde yeni özel anahtar oluştur diyoruz. Yönetici YGK yapılandırma bölümünde projede kullandığımız dil yapısına uygun olan şekilde indirdiğimiz özel anahtar dosyasını nasıl kullanacağımız gösterilmektedir.
Örnek bir özel anahtar dosyasının içerisindekiler aşağıdaki gibidir.
{
"type": "service_account",
"project_id": "your_project_id",
"private_key_id": "your_private_key_id",
"private_key": "your_private_key",
"client_email": "your_client_email.com",
"client_id": "your_client_id",
"auth_uri": "your_auth_uri",
"token_uri": "your_token_uri",
"auth_provider_x509_cert_url": "auth_provider_x509_cert_url",
"client_x509_cert_url": "client_x509_cert_url",
"universe_domain": "universe_domain"
}
Aynı ayarlar sayfasında General sekmesinde uygulamanız içerisine firebase YGK’sını nasıl yükleyeceğiniz Şekil 4’deki gibi gösterilmektedir. YGK bağlantısı için Şekil 4’de gösterilen bilgiler ile firebase-messaging-sw.js konfigürasyon dosyasını oluşturmamız gerekmektedir. Bu dosya projenin kök klasör lokasyonunda bulunmalıdır.
YGK Dosyasının Flask Uygulamasına Ekleme
Flask uygulamamız içerisinde FBM jeton bilgisini alabilmek için bir Javascript fonksiyonu yazmamız gerekmektedir. Aşağıda bulunan “Firebase FBM Jeton Oluşturma” kodu, FBM kullanarak tarayıcıda anlık bildirimleri almak için gerekli işlemleri gerçekleştirmektedir. İlk olarak, firebaseConfig
ile Firebase’i başlatmakta ve ardından messaging
örneği oluşturarak bildirimlerle etkileşim kurmayı sağlamaktadır. registerServiceWorker
fonksiyonu, tarayıcıda bir Servis işçisi(Service worker) kaydeder. Servis işçisi, genellikle çevrimdışı erişim ve bildirimler gibi özellikleri etkinleştirmek için kullanılır. Servis işçisi başarıyla kaydedildiğinde, konsola kapsam bilgisini yazdırır; hata durumunda ise bir hata mesajı konsola yazdırılır. Bu kod, kullanıcıya anlık bildirimleri gönderme yeteneğini etkinleştirirken, olası hata durumlarını ele alarak güvenli bir şekilde işlem yapmayı sağlar. Öncelikle firebase ile servis işçisi oluşturuyoruz ve firebase bulut mesajlaşma servisine cihazımızı kaydediyoruz. Firebase Bulut Mesajlaşma servisi bize cihaza özgü eşsiz bir jeton bilgisi dönmektedir. Bu jeton sayesinde cihaza bildirim göndermemiz mümkün olmaktadır. Ardından bu FBM jeton bilgisini sunucu tarafında python fonksiyonuna gönderiyoruz. Python fonksiyonu ise bu jeton bilgisini ve kullanıcıdan girdi olarak gelen bilgi firebase bulut fonksiyonuna göndermektedir.
firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
function registerServiceWorker() {
return navigator.serviceWorker.register('/firebase-messaging-sw.js')
.then((registration) => {
console.log('Service Worker registered with scope:', registration.scope);
return registration;
})
.catch((error) => {
console.error('Service Worker registration failed:', error);
throw error;
});
}
function requestAndSendFCMToken() {
return messaging.requestPermission()
.then(async () => {
const token = await messaging.getToken();
console.log('FCM token:', token);
return token;
})
.catch((error) => {
console.error('Error requesting permission or getting FCM token:', error);
throw error;
});
}
AWS Replicate Fonksiyonu Dönüşümü
Google Bulut Fonksiyonları ile Bulut Fonksiyonu Oluşturma
Google Bulut konsoluna giriş yapıyoruz. Giriş yaptıktan sonra sol üst kısımdan Firebase üzerinden oluşturduğumuz projemizi seçiyoruz ve arama çubuğuna Google Bulut Fonksiyonları yazarak servise gidiyoruz.
Bulut Fonksiyonları servisinde yeni bir fonksiyon oluşturmak için fonksiyon oluştur(create function) butonuna tıklıyoruz. Şekil 5 gösterilen bölümleri fonksiyonunuzun yapısına göre düzenliyoruz.
Şekil 6’da gösterildiği gibi Google Bulut Fonksiyonları birden fazla dilde yazılabilmektedir. Başlangıç noktası olarak isimlendiren bölümde yazdığımız fonksiyonun içerisindeki ana çalışacak olan fonksiyonun ismini vermekteyiz.
Google Bulut Fonksiyonları ile Replicate UPA’sına Sorgu Gönderme Fonksiyonu
Bu projede oluşturulan tüm fonksiyonlar Python dilinde yazılmış olup Python 3.10 versiyonu kullanılmıştır. Fonksiyon için kullanacağımız dili seçtikten sonra python diline özel bir requirements.txt dosyası oluşturuyoruz. Fonksiyonumuzun bulunacağı .py dosyasına aşağıdaki örnekteki gibi bir Replicate sorgusu yazıyoruz. “Firebase Bulut Fonksiyonu – Replicate’e Sorgu Gönderme” fonksiyonunda , Flask tarafından gelen jeton bilgisi ve kullanıcıdan girdi bilgisi Replicate sitesinde bulunan stable diffusion modeline sorgu atılmaktadır. Sorgudan bir cevap beklemeden fonksiyon bitmektedir. Cevap geldiğinde ise web kancası servisi linkinde belirtilen adrese gönderilmektedir. Bunun için de Replicate servisinin bize oluşturduğu UPA jetonu bilgisini kullanarak Replicate servisi ile bağlantı kurulmaktadır.
import os
import threading
import requests
import replicate
os.environ["REPLICATE_API_TOKEN"] = "YOUR_API_TOKEN"
def replicate_request(request):
request_json = request.get_json()
prompt = request_json.get('prompt', 'default_prompt')
user_id = request_json.get('user_id', 'default_user_id')
model = replicate.models.get("stability-ai/stable-diffusion")
version = model.versions.get("27b93a2413e7f36cd83da926f3656280b2931564ff050bf9575f1fdf9bcd7478")
prediction = replicate.predictions.create(
version=version,
input={"prompt": prompt, "user_id": user_id},
webhook="https://example.com/your-webhook",
webhook_events_filter=["completed"])
return {"message": "Input sended to replicate."}
AWS S3’ye Kaydet Fonksiyonu Dönüşümü
Google Depolama Servisi üzerinden öncelikle bir bucket oluşturuyoruz. Kaydedeceğimiz görüntüler bu bucket içerisine kayıt edilecektir. Bu işlemler için aşağıdaki “Firebase Bulut Depoalama – Gelen Resim Bilgisini PNG olarak kaydetme” fonksiyonunu oluşturmaktayız.İlk olarak, belirli bir Google Bulut Depolama kovası adı BUCKET_NAME
tanımlanır. Ardından, download_image
fonksiyonu, verilen bir URL’den bir görüntüyü indirir ve Pillow (PIL) kütüphanesini kullanarak bir görüntü nesnesine dönüştürür. convert_image_to_array
fonksiyonu, Pillow kütüphanesini kullanarak bir görüntü nesnesini NumPy dizisine dönüştürür. upload_to_gcs
fonksiyonu, bu NumPy dizisini Google Bulut Depolama’ya yükler. Bu işlem için geçici bir dosya oluşturulur, görüntü bu dosyaya kaydedilir, ardından Google Bulut Depolama’ya yüklenir ve geçici dosya silinir. Son olarak, process_replicate_webhook
fonksiyonu, bir giriş isteği alır ve bu isteği işleyerek görüntüyü indirir, işler, Google Bulut Depolama’ya yükler. Replicate UPA sorgusundan gelen resim url’i ve jeton bilgisi ise bildirim gönderen yeni oluşturacağımız bulut fonksiyonuna gönderilmektedir
import os
import tempfile
from google.cloud import storage
from PIL import Image
import numpy as np
from io import BytesIO
import requests
import json
BUCKET_NAME = 'your_bucket_name'
def download_image(image_url):
print("url:",image_url)
response = requests.get(image_url)
print("url:",image_url)
image = Image.open(BytesIO(response.content))
return image
def convert_image_to_array(image):
return np.array(image)
def upload_to_gcs(bucket_name, user_id, image_array):
client = storage.Client()
bucket = client.bucket(bucket_name)
_, temp_filename = tempfile.mkstemp()
Image.fromarray(image_array).save(temp_filename, format='PNG')
destination_blob_name = f"{user_id}/image.png"
blob = bucket.blob(destination_blob_name)
blob.upload_from_filename(temp_filename)
os.remove(temp_filename)
return f"gs://{bucket_name}/{destination_blob_name}"
def process_replicate_webhook(request):
request_json = request.get_json()
print("request:",request_json)
if not request_json:
return {"error": "Invalid JSON payload"}
user_id = request_json['input']['user_id']
status = request_json['status']
image_url = request_json['output'][0]
if not image_url or not user_id:
return {"error": "Missing image_url or user_id"}
image = download_image(image_url)
image_array = convert_image_to_array(image)
gcs_url = upload_to_gcs(BUCKET_NAME, user_id, image_array)
print("Received Replicate webhook:", user_id, status, image_url)
headers = {
"Content-Type": "application/json",
}
push_notificaiton_payload = {
"token": user_id,
"image_url": image_url
}
response_push_notification = requests.post("your_notification_function_url", data=json.dumps(push_notificaiton_payload), headers=headers)
return {"message": f"Image saved to {gcs_url}"}
Firebase Bildirim Gönderme Fonksiyonu
“Firebase Bulut Bildirimi – Kullanıcıya Bildirim ile Sonuç Resmini Gönderme” kodu, Firebase Bulut Mesajlaşma ve Flask web uygulama çerçevesini kullanarak bir bildirim gönderme işlemini gerçekleştirir. İlk olarak, Firebase projesine erişim sağlamak için bir firebase_key.json
dosyasından alınan kimlik bilgileriyle bir Firebase uygulaması başlatılır. send_notification
fonksiyonu, gelen HTTP isteğini işler ve istekte bulunan cihazın FBM jetonunu ve bir görüntü URL’sini alır. Eğer FBM jetonu eksikse, hata mesajı ile birlikte 400 Geçersiz İstek durumu döner. Ardından, bir messaging.Message
nesnesi oluşturulur, bu nesne FBM jetonu , bildirim içeriği ve görüntü URL’sini içerir. Bu bildirim, başlık, gövde ve tıklama eylemi ile özelleştirilmiştir. Son olarak, bildirim gönderme işlemi messaging.send(message)
ile gerçekleştirilir. Başarılı bir gönderim durumunda başarı mesajı ve HTTP durumu 200 döner. Herhangi bir hata durumunda ise hatayı içeren bir mesaj ve HTTP durumu 500 döner.
import json
import firebase_admin
from firebase_admin import credentials, messaging
from flask import request
cred = credentials.Certificate('firebase_key.json')
firebase_admin.initialize_app(cred, options={'senderId': 'your_sender_id'})
def send_notification(request):
request_json = request.get_json()
image_url = request_json.get('image_url', '')
registration_token = request_json.get('token', '')
if not registration_token:
return 'Missing FCM token in the request', 400
message = messaging.Message(
token=registration_token,
data={'click_action': image_url,
'title':'Resminiz Hazır',
'body':'Resminiz Hazır Indirmek Için Tıklayın!'},
)
try:
response = messaging.send(message)
return f'Successfully sent message: {response}', 200
except Exception as e:
return f'Error sending message: {str(e)}', 500
Gönderilen bildirimin kullanıcı tarafında kullanıcıya gösterilmesi için firebase-messaging-sw.js dosyasına aşağıdaki “Javascript Bildirim Alma ve Kullanıcıya Gösterme” kod bloğunu eklememiz gerekmektedir. Bu kod, bir web tarayıcısında çalışan bir arka plan servisini temsil eder. messaging.onBackgroundMessage
fonksiyonu, tarayıcı arka planda iken gelen bildirim mesajlarını dinler ve taşıma verisi(payload
) içindeki verileri işler. Bu veriler arasında bildirim başlığı (notificationTitle
) ve tıklama eylemi (click_action
) bulunmaktadır. self.registration.showNotification
fonksiyonu, tarayıcıda bir bildirim gösterir. Gösterilen bildirimin başlığı notificationTitle
olarak, ve tıklama eylemi click_action
olarak belirlenir. self.addEventListener('notificationclick', function(event) { ... });
kısmı, kullanıcının bir bildirime tıkladığında yapılacak işlemleri belirler. Tıklanan bildirim kapatılır ve eğer daha önce tıklanan URL (lastClickedURL
) şu anki tıklanan URL ile aynı değilse, yeni bir pencere açılır ve payload.data.click_action
URL’sine yönlendirilir. Ayrıca, tıklanan URL, en son tıklanan URL olarak lastClickedURL
değişkenine atanır. Bu kod, arka planda çalışan bir servis aracılığıyla gelen FBM bildirimlerini dinler, bildirimleri gösterir ve kullanıcının tıkladığı zaman belirli bir URL’ye yönlendirir.
let lastClickedURL = '';
messaging.onBackgroundMessage(function(payload) {
console.log('Received background message ', payload);
const notificationTitle = payload.data.title;
const notificationOptions = {
click_action: payload.data.click_action,
notificationTitle: notificationTitle,
};
self.registration.showNotification(notificationTitle, notificationOptions);
console.log('test2', payload.data.click_action);
self.addEventListener('notificationclick', function(event) {
const clickedNotification = event.notification;
clickedNotification.close();
if (payload.data.click_action !== lastClickedURL) {
event.waitUntil(
clients.openWindow(payload.data.click_action)
);
lastClickedURL = payload.data.click_action;
}
});
});
Demo
Sonuç
Bu yazıda, Flask kullanarak geliştirilen bir web uygulamasının Firebase ve AWS arasında geçiş yapma sürecini açıkladım. AWS’deki bir akışın, Firebase servisleri kullanılarak nasıl uyarlandığını detaylı bir şekilde anlattım. Firebase ile geçişte, öncelikle Flask uygulamasına Firebase Bulut Mesajlaşma entegrasyonu eklendi. Kullanıcıya bildirim gönderebilmek için kullanıcı tarafında bir yapı oluşturuldu ve FBM jetonu alınarak Flask uygulamasına iletildi. Ardından, AWS Lambda fonksiyonları yerine Google Bulut Fonksiyonları kullanılarak Replicate UPA’sına sorgu gönderme işlemleri Firebase üzerinde gerçekleştirildi. Gelen cevaplar Google Bulut Depolama’ya kaydedildi ve bu süreç Firebase Bulut Fonksiyonları ile yönetildi.Son olarak, kullanıcıya gönderilen resim URL’si ve FBM jetonu ile birlikte Firebase Bulut Mesajlaşma üzerinden bir bildirim gönderme işlemi gerçekleştirildi. Bu adımların detaylı açıklamalarıyla birlikte, geçiş süreci adım adım anlatıldı ve örnek kod parçacıkları ile desteklendi.