1. Genel Bakış
Serverless Migration Station serisi codelab'ler (kendi hızınızda ilerleyebileceğiniz, uygulamalı eğitimler) ve ilgili videolar, Google Cloud sunucusuz geliştiricilerin öncelikle eski hizmetlerden uzaklaşarak bir veya daha fazla taşıma işlemi yapmalarına rehberlik ederek uygulamalarını modernleştirmelerine yardımcı olmayı amaçlar. Bu sayede uygulamalarınız daha taşınabilir hale gelir, daha fazla seçenek ve esneklik elde edersiniz. Böylece daha geniş bir Cloud ürün yelpazesiyle entegrasyon yapabilir, bu ürünlere erişebilir ve yeni dil sürümlerine daha kolay yükseltebilirsiniz. Başlangıçta öncelikle App Engine (standart ortam) geliştiricileri olmak üzere en eski Cloud kullanıcılarına odaklanılsa da bu seri, Cloud Functions ve Cloud Run gibi diğer sunucusuz platformları veya uygun olduğu durumlarda başka platformları da kapsayacak kadar geniştir.
Bu codelab'de, 1. Modül codelab'indeki örnek uygulamaya App Engine Memcache'i nasıl ekleyeceğiniz ve kullanacağınız açıklanmaktadır. Bu 12. modül eğitiminde Memcache kullanımını ekliyoruz. Ardından 13. modülde Cloud Memorystore'a geçiş yapacağız.
Bu demoda aşağıdaki işlemleri yapmayı öğreneceksiniz:
- App Engine Memcache API'sini/kitaplığını kullanma
- Temel bir Python 2 Flask App Engine NDB uygulamasına önbelleğe alma ekleme
İhtiyacınız olanlar
- Etkin bir GCP faturalandırma hesabına sahip bir Google Cloud Platform projesi
- Temel Python becerileri
- Yaygın Linux komutları hakkında çalışma bilgisi
- App Engine uygulamalarını geliştirme ve dağıtma hakkında temel bilgiler
- Çalışan bir 1. Modül App Engine uygulaması (codelab'ini tamamlayın [önerilir] veya uygulamayı depodan kopyalayın)
Anket
Bu eğitimi nasıl kullanacaksınız?
Python ile ilgili deneyiminizi nasıl değerlendirirsiniz?
Google Cloud hizmetlerini kullanma deneyiminizi nasıl değerlendirirsiniz?
2. Arka plan
App Engine Memcache'ten geçiş yapmak için 1. Modül codelab'i sonucunda oluşan mevcut Flask ve App Engine NDB uygulamasına kullanımını ekleyin. Örnek uygulama, kullanıcının en son on ziyaretini gösterir. Aynı kullanıcı tarayıcısını yenilerse sürekli olarak yeni Ziyaret öğeleri oluşturmak ve en son ziyaretleri Datastore'dan getirmek ideal olmaz. Bu nedenle, en son ziyaretleri önbelleğe alacağız.
Aynı ziyaretçi sayfayı ziyaret ederse bu ziyaretler önbellekten döndürülür. Yeni bir kullanıcı siteyi ziyaret ederse veya bir saat geçerse önbellek temizlenir ve en son girişlerle değiştirilir (yeni bir ziyaret kaydedilir). Bu App Engine Memcache entegrasyonu uygulandıktan sonra, bir sonraki (13. modül) codelab'de Cloud Memorystore'a taşıyabiliriz.
Bu eğitimde aşağıdaki adımlar yer almaktadır:
- Kurulum/Ön Hazırlık
- Yapılandırmayı güncelleyin
- Uygulama kodunu değiştirme
3. Kurulum/Ön Hazırlık
Eğitimin ana bölümüne geçmeden önce projemizi oluşturalım, kodu alalım ve temel uygulamayı dağıtalım. Böylece, çalışır durumda olan bir kodla başladığımızı biliriz.
1. Proje oluşturma
1. Modül codelab'ini tamamladıysanız aynı projeyi (ve kodu) yeniden kullanmanızı öneririz. Alternatif olarak, yepyeni bir proje oluşturabilir veya mevcut başka bir projeyi yeniden kullanabilirsiniz. Projenin etkin bir faturalandırma hesabına sahip olduğundan ve App Engine'in etkinleştirildiğinden emin olun.
2. Temel örnek uygulamayı edinme
Bu codelab'in ön koşullarından biri, çalışan bir 1. Modül örnek uygulamasına sahip olmaktır. Çalışan bir örnek uygulamanız yoksa buraya geçmeden önce yukarıdaki bağlantılardan birini kullanarak eğitimi tamamlayın. Aksi takdirde, içeriğine aşinaysanız aşağıdaki 1. Modül kodunu kullanmaya başlayabilirsiniz.
Sizinkini veya bizimkini kullanıyor olsanız da 1. Modül kodunu KULLANMAYA BAŞLAYACAĞIZ. Bu codelab, her adımda size yol gösterir ve 11. modülün depo klasöründeki (FINISH) koda benzer bir kodla sonuçlanır.
- BAŞLANGIÇ: Module 1 folder (Python 2)
- BİTİRME: Module 12 folder (Python 2)
- Deponun tamamı (ZIP dosyasını klonlamak veya indirmek için)
1. Modül BAŞLANGIÇ dosyalarının dizini (sizinki veya bizimkisi) şu şekilde görünmelidir:
$ ls README.md main.py templates app.yaml requirements.txt
3. Temel uygulamayı (yeniden) dağıtma
Şimdi yapmanız gereken kalan ön hazırlık adımları:
gcloudkomut satırı aracı hakkında bilgi edinin- Örnek uygulamayı
gcloud app deployile yeniden dağıtın. - Uygulamanın App Engine'de sorunsuz çalıştığını onaylayın.
Bu adımları başarıyla uygulayıp web uygulamanızın çalıştığını (aşağıdakine benzer bir çıkışla) gördüğünüzde, uygulamanıza önbelleğe alma özelliğini eklemeye hazırsınız demektir.

4. Yapılandırmayı güncelleyin
Standart App Engine yapılandırma dosyalarında (app.yaml, requirements.txt, appengine_config.py) herhangi bir değişiklik yapılması gerekmez.
5. Uygulama dosyalarını değiştirme
Yalnızca bir App Engine API eklediğimiz için harici paketler kullanılmaz. Bu nedenle, yapılandırma dosyalarının (app.yaml, requirements.txt, appengine_config.py) güncellenmesi gerekmez. Yalnızca bir uygulama dosyası (main.py) olduğundan bu bölümdeki tüm değişiklikler yalnızca bu dosyayı etkiler.
İçe aktarılanlar
En önemli adım, Memcache kitaplığını (google.appengine.api.memcache) içe aktarmaktır. En son ziyaretleri bir saat boyunca önbelleğe alacağımız için bir saatteki saniye sayısını da sabit olarak ekleyelim. Aşağıda, kodunuzun bu değişiklikten önce ve sonraki görünümü yer almaktadır:
ÖNCESİ:
from flask import Flask, render_template, request
from google.appengine.ext import ndb
app = Flask(__name__)
SONRASI:
from flask import Flask, render_template, request
from google.appengine.api import memcache
from google.appengine.ext import ndb
app = Flask(__name__)
HOUR = 3600
Memcache desteğiyle önbelleğe alma ekleme
En önemli değişiklik, uygulamamızda önbelleğe almanın kullanılmasıdır. Daha spesifik olarak, en son ziyaretleri önbelleğe almalı, önbelleğe alınan ziyaretlerin kullanılabilir olup olmadığını kontrol etmeli ve planımız göz önüne alındığında önbelleğe alınan sonuçları mümkün olduğunca kullanmaya çalışmalıyız. Uygulamanın hedefimize ulaşmak için atacağı adımlar şunlardır:
- Mevcut ziyareti ayarlayın ve
visitorolarak adlandırın. - Önbellekten en son
visits'yı getirmeyi deneme - Önbellek boşsa veya en son ziyaretçi (
visits[0]['visitor']) mevcutvisitor'den farklıysa: Bu en yeni ziyareti saklayın, en son ziyaretleri getirin ve bunları bir saat boyunca önbelleğe alın. - Web şablonu aracılığıyla kullanıcıya
visitsdeğerini gösterme
Bu güncellemelerden önce ve sonraki görünümü aşağıda bulabilirsiniz:
ÖNCESİ:
@app.route('/')
def root():
'main application (GET) handler'
store_visit(request.remote_addr, request.user_agent)
visits = fetch_visits(10)
return render_template('index.html', visits=visits)
SONRASI:
@app.route('/')
def root():
'main application (GET) handler'
# check for (hour-)cached visits
ip_addr, usr_agt = request.remote_addr, request.user_agent
visitor = '{}: {}'.format(ip_addr, usr_agt)
visits = memcache.get('visits')
# register visit & run DB query if cache empty or new visitor
if not visits or visits[0]['visitor'] != visitor:
store_visit(ip_addr, usr_agt)
visits = list(fetch_visits(10))
memcache.set('visits', visits, HOUR) # set() not add()
return render_template('index.html', visits=visits)
Yapılan değişikliklerin resimli gösterimi aşağıda verilmiştir:

App Engine memcache kullanımını 1. Modül örnek uygulamasına eklemek için gerekli tüm değişiklikler tamamlandı. Çalıştığını görmek için bu uygulamayı oluşturup dağıtalım.
6. Özet/Temizleme
Bu bölümde, uygulamayı dağıtarak, amaçlandığı gibi çalıştığını ve yansıtılan tüm çıktılarda çalıştığını doğrulayarak bu codelab'i tamamlıyoruz. Uygulama doğrulandıktan sonra temizleme adımlarını uygulayın ve sonraki adımları göz önünde bulundurun.
Uygulamayı dağıtma ve doğrulama
Uygulamanızı gcloud app deploy ile yeniden dağıtın ve uygulamanın çalıştığını onaylayın. Kodunuz artık FINISH'teki Module 12 folder ile eşleşmelidir. Çıkış, daha önce dağıttığınız 1. Modül uygulamasıyla aynı olmalıdır:

Tek yaptığımız, aynı kullanıcının deneyimini hızlandırmaktı. Yenilendiklerinde sonuçları doğrudan önbellekten alırsınız. Bu işlem ne yeni bir ziyaret oluşturur ne de Datastore'dan veri getirir.
Örnek uygulamamıza App Engine memcache hizmetinin kullanımını eklemeyle ilgili 12. modül codelab'ini tamamladığınız için tebrik ederiz. Artık bonus adımda bu Python 2 uygulamasını Python 3'e taşıma seçeneğiniz var.
Temizleme
Genel
Şimdilik işiniz bittiyse faturalandırmayı önlemek için App Engine uygulamanızı devre dışı bırakmanızı öneririz. Ancak biraz daha test veya deneme yapmak isterseniz App Engine platformunda ücretsiz kota bulunur. Bu nedenle, kullanım katmanını aşmadığınız sürece sizden ücret alınmaz. Bu, işlem için geçerlidir ancak ilgili App Engine hizmetleri için de ücret alınabilir. Daha fazla bilgi için fiyatlandırma sayfasını inceleyin. Bu taşıma işlemine başka Cloud hizmetleri de dahilse bunlar ayrı olarak faturalandırılır. Her iki durumda da varsa aşağıdaki "Bu codelab'e özel" bölümüne bakın.
Tam açıklama yapmak gerekirse App Engine gibi bir Google Cloud sunucusuz bilgi işlem platformuna dağıtım yapıldığında küçük derleme ve depolama maliyetleri oluşur. Cloud Build ve Cloud Storage'ın kendi ücretsiz kotaları vardır. Bu görüntünün depolanması, kotanın bir kısmını kullanır. Ancak, böyle bir ücretsiz katmanın olmadığı bir bölgede yaşıyor olabilirsiniz. Bu nedenle, olası maliyetleri en aza indirmek için depolama alanı kullanımınıza dikkat edin. İncelemeniz gereken belirli Cloud Storage "klasörleri" şunlardır:
console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/imagesconsole.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com- Yukarıdaki depolama bağlantıları,
PROJECT_IDve *LOC*ınıza bağlıdır. Örneğin, uygulamanız ABD'de barındırılıyorsa "us" olur.
Öte yandan, bu uygulamaya veya ilgili diğer taşıma codelab'lerine devam etmeyecekseniz ve her şeyi tamamen silmek istiyorsanız projenizi kapatın.
Bu codelab'e özel
Aşağıda listelenen hizmetler bu codelab'e özeldir. Daha fazla bilgi için her ürünün belgelerine bakın:
- App Engine Memcache hizmeti, her biri kendi fiyatlandırma yapısına sahip iki farklı türde sunulur. Bu nedenle, faturalandırmayla ilgili olarak bu kullanımı izlemeniz gerekir.
- App Engine Datastore hizmeti, ücretsiz katmanı da olan Cloud Datastore (Datastore modunda Cloud Firestore) tarafından sağlanır. Daha fazla bilgi için fiyatlandırma sayfasına bakın.
Sonraki adımlar
Bir sonraki mantıksal taşıma işlemi 13. Modül'de ele alınmaktadır. Bu modülde, geliştiricilere App Engine memcache hizmetinden Cloud Memorystore'a nasıl geçiş yapacakları gösterilmektedir. Bu taşıma işlemlerinin tümü isteğe bağlıdır ve uygulamalarını modernize etmek için çeşitli adımlar atmak isteyen kullanıcılar tarafından kullanılabilir. Cloud Memorystore hizmeti, birçok nedenden dolayı App Engine'in memcache hizmetine kıyasla önemli bir yükseltmedir:
- Cloud Memorystore sunucusuz değildir. Bu, önbellek için bir sunucu ayırmanız gerektiği anlamına gelir. Cloud Memorystore'un ücretsiz katmanı da yoktur. Bu iki faktörün maliyet üzerinde önemli bir etkisi olabilir.
- Cloud Memorystore, iki farklı temel depolama mekanizmasını (önbelleğe alma motorları) destekler: Redis ve Memcached.
- Cloud Memorystore (Redis için), App Engine Memcache'ten çok daha zengin ve ayrıntılı bir özellik kümesine sahiptir.
- Cloud Memorystore'u kullanmak için bir Cloud Memorystore sunucusu oluşturmanız, bunu bir Google Cloud VPC ağına eklemeniz ve ardından App Engine uygulamanızın Memorystore sunucunuzla iletişim kurmak için bu ağı kullanmasını sağlamanız gerekir.
Cloud Memorystore'da sunulan tüm özelliklere ihtiyacınız olmadığını düşünüyorsanız veya maliyet üzerindeki etkileri konusunda endişeleriniz varsa App Engine Memcache'i kullanmaya devam edebilirsiniz.
13. modülün ötesinde Cloud NDB ve Cloud Datastore veya Cloud Tasks gibi bir dizi başka olası taşıma işlemi vardır. Cloud Run ve Cloud Functions'a ürünler arası geçişler de vardır. Tümünü taşıma deposunda bulabilirsiniz.
Bir sonraki olası adım, Python 3'e taşıma işlemidir. Bu işlem, bir sonraki bölümde isteğe bağlı bir adım olarak ele alınmıştır.
7. BONUS: Python 3'e taşıma
Genel Bakış
Bu bölümde, yukarıda tamamladığımız 12. modül uygulamasının Python 3'e taşınmasıyla ilgili isteğe bağlı bonus içerikler yer almaktadır. Önce yapılandırma, ardından uygulama ile başlıyoruz.
app.yaml dosyasını basitleştirme
Python 3 çalışma zamanının avantajlarından biri, app.yaml'nın önemli ölçüde basitleştirilebilmesidir.
ÖNCESİ:
12. Modülün sonunda app.yaml bölümünde yer alanlar aşağıda verilmiştir:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
Python 3 çalışma zamanı, web çerçevelerinin kendi yönlendirmelerini yapmasını gerektirdiğinden app.yaml içindeki tüm rota işleyiciler auto olarak değiştirilmelidir. Sunulan statik dosya yoksa kullanıcılar handlers: bölümünün tamamını kaldırabilir. Ayrıca hem threadsafe hem de api_version kullanımdan kaldırıldı.
SONRASI:
Gerekli değişiklikler yapıldıktan sonra Python 3'ün yerine kullanılacak app.yaml:
runtime: python39
app_engine_apis: true
Açıklama gerektiren tek satır app_engine_apis: true. Eski App Engine hizmetleri 2021'de ikinci nesil çalışma zamanlarında kullanıma sunulduğunda Python 3 dahil bazı çalışma zamanlarının ndb, taskqueue ve memcache gibi API'lere erişmek için ek önyükleme yapması gerekiyordu. Yapılandırmadaki bu satır, bu amaca hizmet eder.
requirements.txt dosyasını güncelleme
requirements.txt içinde orijinal API'lerin başka bir başlatılması gerekir: Yeni App Engine SDK'sına erişim dahil edilmelidir.
ÖNCESİ:
12. Modülün sonunda app.yaml bölümünde yer alanlar aşağıda verilmiştir:
flask
SONRASI:
App Engine Python SDK'sını eklemeniz yeterlidir. Bu durumda aşağıdakilere sahip olursunuz:
flask
appengine-python-standard
appengine_config.py ve lib dosyalarını silin.
Yeni nesil App Engine çalışma zamanları, üçüncü taraf paket kullanımını yeniliyor:
- Yerleşik kitaplıklar, Google tarafından incelenen ve App Engine sunucularında kullanıma sunulan kitaplıklardır. Bunun nedeni, geliştiricilerin buluta dağıtmasına izin verilmeyen C/C++ kodu içermeleridir. Bu kitaplıklar artık 2. nesil çalışma zamanlarında kullanılamaz.
- Yerleşik olmayan kitaplıkların (bazen "vendoring" veya "self-bundling" olarak da adlandırılır) kopyalanması artık 2. nesil çalışma zamanlarında gerekli değildir. Bunun yerine, derleme sistemi tarafından dağıtım sırasında sizin adınıza otomatik olarak yüklendikleri
requirements.txtiçinde listelenmelidirler.
Üçüncü taraf paket yönetimiyle ilgili bu değişiklikler sonucunda appengine_config.py dosyası ve lib klasörü gerekmediğinden bunları silin. 2. nesil çalışma zamanlarında App Engine, requirements.txt içinde listelenen üçüncü taraf paketlerini otomatik olarak yükler. Özetleme:
- Paketlenmiş veya kopyalanmış üçüncü taraf kitaplıkları yoksa bunları
requirements.txtiçinde listeleyin. pip install,libklasörüne taşınmaz. Yanilibklasörü yoktur.app.yamliçinde listelenen yerleşik üçüncü taraf kitaplıkları yok (bu nedenlelibrariesbölümü yok); bunlarırequirements.txtiçinde listeleyin.- Uygulamanızda referans verilecek üçüncü taraf kitaplıkları yoksa
appengine_config.pydosyası da yoktur.
requirements.txt içinde istenen tüm üçüncü taraf kitaplıklarını listelemek, geliştiricinin tek gereksinimidir.
Uygulamayı App Engine SDK'yı kullanacak şekilde güncelleme
Yukarıda belirtildiği gibi, Python 3 uygulamalarının App Engine paket hizmetlerine erişebilmesi için bazı değişiklikler yapılması gerekir:
- App Engine SDK'sını paketleyin (
requirements.txtiçinde) - App Engine SDK'sını etkinleştirme (
app.yamliçinde) - WSGI nesnesini sarmalama (
main.pyiçinde)
İlk iki koşul yukarıda tamamlandı. Bu nedenle, son koşul main.py değerini güncellemek.
ÖNCESİ:
Aşağıda, 12. Modülün sonunda yer alan Python 2 main.py bulunmaktadır:
from flask import Flask, render_template, request
from google.appengine.api import memcache
from google.appengine.ext import ndb
app = Flask(__name__)
HOUR = 3600
SONRASI:
Python 3 bağlantı noktası için SDK'yı içe aktarın ve Flask uygulama nesnesini SDK ile (SDK sarmalayıcı) sarmalayın. Sonuç olarak aşağıdaki kod elde edilir:
from flask import Flask, render_template, request
from google.appengine.api import memcache, wrap_wsgi_app
from google.appengine.ext import ndb
app = Flask(__name__)
app.wsgi_app = wrap_wsgi_app(app.wsgi_app)
HOUR = 3600
Geliştiricilerin, 2.x'ten 3.x'e taşıma işlemi yaparken paketlenmiş hizmetlere erişmek için Python uygulamalarında bu değişiklikleri yapması gerekir. Flask kullanmıyorsanız dokümanlarda Django ve Pyramid örnekleri de vardır. Python 2 kodunuz bir web uygulaması değilse Python 3'e taşıma işlemi sırasında yalnızca SDK paketini eklemeniz yeterli olur. Uygulama kodumuz başlangıçta Python 2 ve 3'te çalışacak şekilde tasarlandığından ek uyumluluk değişikliği yapılması gerekmez.
Uygulamayı dağıtma
Yukarıdaki değişiklikleri tamamladıktan sonra güncellenen örnek uygulamayı dağıtabilirsiniz. (Uygulamanızın Python 3 sürümünü aynı GCP projesindeki orijinal Python 2 sürümü üzerine dağıtırken herhangi bir sorun yaşanmaz.) Uygulama davranışı aynı kalmalıdır. Güncellenen uygulamanızı bizim uygulamamızla karşılaştırmanız gerekiyorsa taşıma deposundaki Module 12b klasörüne bakın. Python 3 gibi en yeni çalışma zamanlarında App Engine paketlenmiş hizmetlerinin desteği hakkında daha fazla bilgi edinmek için özellik lansmanı duyurusunun yanı sıra 17. Modül Codelab'e bakın.
12. modüldeki bonus adımı tamamladığınız için tebrikler. Ayrıca Python 3 çalışma zamanı için yapılandırma dosyalarını hazırlama ile ilgili dokümanları da inceleyin. Sonraki adımlar ve temizleme için yukarıdaki Özet/Temizleme bölümünü inceleyin.
8. Ek kaynaklar
Bu veya ilgili geçiş modülünü ve ilgili ürünleri daha ayrıntılı incelemek isteyen geliştiriciler için ek kaynaklar aşağıda listelenmiştir. Bu sayfada, içerikle ilgili geri bildirimde bulunabileceğiniz yerler, kod bağlantıları ve faydalı bulabileceğiniz çeşitli belgeler yer alır.
Codelab ile ilgili sorunlar/geri bildirimler
Bu codelab ile ilgili sorun bulursanız lütfen göndermeden önce sorununuzu arayın. Arama yapma ve yeni sorunlar oluşturma bağlantıları:
Taşıma kaynakları
2. Modül (BAŞLANGIÇ) ve 12. Modül (BİTİŞ) ile ilgili depo klasörlerinin bağlantılarını aşağıdaki tabloda bulabilirsiniz. Bu dokümanlara, tüm App Engine codelab'lerinin taşındığı depodan da erişebilirsiniz. Bu depoyu klonlayabilir veya ZIP dosyası olarak indirebilirsiniz.
Codelab | Python 2 | Python 3 |
kod (bu eğitimde yer almaz) | ||
12. Modül (bu codelab) |
Online referanslar
Bu eğitimle ilgili olabilecek online kaynakları aşağıda bulabilirsiniz:
App Engine
- App Engine belgeleri
- Python 2 App Engine (standart ortam) çalışma zamanı
- Python 3 App Engine (standart ortam) çalışma zamanı
- Python 2 ve 3 App Engine (standart ortam) çalışma zamanları arasındaki farklar
- Python 2'den 3'e App Engine (standart ortam) taşıma kılavuzu
- App Engine fiyatlandırma ve kota bilgileri
- İkinci nesil App Engine platformunun kullanıma sunulması (2018)
- Birinci ve ikinci nesil platformları karşılaştırma
- Eski çalışma zamanları için uzun süreli destek
- Belge taşıma örnekleri deposu
- Topluluk tarafından gönderilen taşıma örnekleri deposu
Cloud Memorystore ve Cloud Datastore
- Cloud Memorystore ürün sayfası
- Redis için Cloud Memorystore belgeleri
- Cloud Memorystore for Memcached belgeleri
- Cloud Memorystore (Redis için) fiyatlandırma bilgileri
- Cloud Datastore belgeleri
- Cloud Datastore fiyatlandırma bilgileri
Diğer Cloud bilgileri
- Google Cloud Platform'da Python
- Google Cloud Python istemci kitaplıkları
- Google Cloud "Her Zaman Ücretsiz" katmanı
- Google Cloud SDK (
gcloudkomut satırı aracı) - Tüm Google Cloud belgeleri
Videolar
- Sunucusuz Taşıma İstasyonu
- Sunucusuz Expeditions
- Google Cloud Tech kanalına abone olun.
- Google Developers'a abone olun.
Lisans
Bu çalışma, Creative Commons Attribution 2.0 Genel Amaçlı Lisans ile lisans altına alınmıştır.