App Engine Blobstore'dan Cloud Storage'a Taşıma (Modül 16)

1. Genel Bakış

Sunucusuz Taşıma İstasyonu codelab'leri serisi (kendi kendine ilerleyen, uygulamalı eğiticiler) ve ilgili videolar, Google Cloud sunucusuz geliştiricilerinin uygulamalarını bir veya daha fazla taşıma işleminde yönlendirerek uygulamalarını modernleştirmelerine yardımcı olmayı amaçlar. Bu videolar genellikle eski hizmetlerden uzaklaştırılır. Bu sayede uygulamalarınızı daha taşınabilir hale getirir, daha fazla seçenek ve esneklik elde edebilir, daha geniş bir Cloud ürünü yelpazesiyle entegrasyon ve erişim elde edebilir, ayrıca yeni dil sürümlerine kolayca geçiş yapabilirsiniz. Başlangıçta özellikle App Engine (standart ortam) geliştiricileri olmak üzere ilk Cloud kullanıcılarına odaklanan bu seri, Cloud Functions ve Cloud Run gibi diğer sunucusuz platformları veya uygun olduğu durumlarda diğer sunucusuz platformları ya da diğer platformları kapsayacak kadar geniş kapsamlıdır.

Bu codelab'de App Engine Blobstore'dan Cloud Storage'a nasıl geçiş yapacağınızı öğrenebilirsiniz. Ayrıca, aşağıdakilerden örtülü taşıma işlemleri de yapılır:

Adım adım açıklamalı daha fazla bilgi için ilgili taşıma modüllerine bakın.

Demoda aşağıdaki işlemleri yapmayı öğreneceksiniz:

  • App Engine Blobstore API/kitaplığının kullanımını ekleyin
  • Kullanıcının yüklemelerini Blobstore hizmetine depolama
  • Cloud Storage'a geçiş işleminin bir sonraki adımına hazırlanın

Gerekenler

Anket

Bu eğiticiden nasıl yararlanacaksınız?

Yalnızca okuma Okuyun ve alıştırmaları tamamlayın

Python deneyiminizi nasıl değerlendirirsiniz?

Acemi Orta Yeterli

Google Cloud hizmetlerini kullanma deneyiminizi nasıl değerlendirirsiniz?

Acemi Orta Yeterli

2. Arka plan

Bu codelab, Modül 15'teki örnek uygulamayla başlar ve Blobstore'dan (ve NDB) Cloud Storage'a (ve Cloud NDB'ye) geçişin nasıl yapılacağını gösterir. Taşıma sürecinde, App Engine'in eski paketlenmiş hizmetlerindeki bağımlılıklar değiştirilir. Bu sayede, isterseniz uygulamalarınızı başka bir Cloud sunucusuz platformuna veya başka bir barındırma platformuna taşıyabilirsiniz.

Bu taşıma işlemi, bu serideki diğer taşıma işlemlerine kıyasla biraz daha fazla çaba gerektirir. Blobstore'un orijinal web uygulaması çerçevesine bağımlıları olduğundan örnek uygulama, Flask yerine webapp2 çerçevesini kullanmaktadır. Bu eğiticide Cloud Storage, Cloud NDB, Flask ve Python 3'e taşıma işlemleri açıklanmaktadır.

Uygulama hâlâ son kullanıcı "ziyaretlerini" kaydetmeye devam ediyor ve en son on öğeyi görüntüler ancak önceki (Modül 15) codelab'i Blobstore kullanımına uygun yeni bir işlev eklemiştir: Uygulama, son kullanıcılardan "ziyaretlerine" karşılık gelen bir yapı (dosya) yüklemelerini ister. Kullanıcılar bunu yapabilir veya "atla"yı seçebilir. tıklayın. Kullanıcının kararından bağımsız olarak sonraki sayfa, bu uygulamanın önceki enkarnasyonlarıyla aynı çıktıyı verir ve en son ziyaretleri görüntüler. Bir ekstra farkla, ilgili yapılar içeren ziyaretlerde "görünüm" bir ziyaretin yapısını görüntüleme bağlantısı. Bu codelab'de daha önce bahsedilen taşıma işlemleri uygulanırken açıklanan işlevler korunur.

3. Kurulum/Ön Çalışma

Eğiticinin ana bölümüne geçmeden önce projemizi oluşturalım, kodu alın ve çalışan bir kodla başladığımızı öğrenmemiz için temel uygulamayı dağıtın.

1. Proje oluşturun

Daha önce Modül 15 uygulamasını dağıttıysanız aynı projeyi (ve kodu) yeniden kullanmanızı öneririz. Alternatif olarak, yeni bir proje oluşturabilir veya mevcut başka bir projeyi yeniden kullanabilirsiniz. Projenin etkin bir faturalandırma hesabı olduğundan ve App Engine'in etkin olduğundan emin olun.

2. Temel örnek uygulamayı al

Bu codelab'in ön koşullarından biri, çalışan bir Modül 15 örnek uygulamasına sahip olmaktır. Bu SDK'ya sahip değilseniz Modül 15'ten "START" alabilirsiniz. (bağlantıyı aşağıdaki bağlantı) tıklayın. Bu codelab'de, Modül 16'daki "FINISH"tekine benzeyen bir kod bulunmaktadır. Son adım ise her adımda yol gösterir. tıklayın.

Modül 15 STARTing dosyalarının dizini şu şekilde görünmelidir:

$ ls
README.md       app.yaml        main-gcs.py     main.py         templates

main-gcs.py dosyası, Modül 15'teki main.py ürününün alternatif bir sürümüdür. Bir Cloud Storage paketinin, proje kimliğine (PROJECT_ID.appspot.com) göre uygulamaya atanan URL'nin varsayılanından farklı bir şekilde seçilmesine olanak tanır. Bu dosya, bu (Modül 16) codelab'inde yer almamaktadır. Yalnızca istenirse ilgili dosyaya benzer taşıma teknikleri uygulanabilir.

3. Temel uygulamayı (yeniden) dağıtma

Hemen yürütmek için kalan ön çalışma adımlarınız:

  1. gcloud komut satırı aracını yeniden tanıma
  2. Örnek uygulamayı gcloud app deploy ile yeniden dağıtın
  3. Uygulamanın App Engine'de sorunsuz çalıştığını onaylayın

Bu adımları başarıyla tamamladıktan sonra Modül 15 uygulamanızın çalıştığını onaylayın. İlk sayfada, kullanıcılara "atla" seçeneğiyle birlikte yüklemek üzere bir ziyaret yapı dosyası isteyen bir form gösteriliyor. düğmesini, devre dışı bırakmak için:

f5b5f9f19d8ae978.png

Kullanıcılar bir dosya yükledikten veya atladıktan sonra, uygulama, aşina oldukları "en son ziyaretleri" oluşturur sayfa:

f5ac6b98ee8a34cb.png

Bir yapı içeren ziyaretler "görüntüleme"ye sahip olur bağlantıyı, yapıyı görüntülemek (veya indirmek) için ziyaret zaman damgasının sağında bulunur. Uygulamanın işlevselliğini onayladıktan sonra eski App Engine hizmetlerinden (webapp2, NDB, Blobstore) çıkıp modern alternatiflere (Flask, Cloud NDB, Cloud Storage) geçmeye hazırsınız demektir.

4. Yapılandırma dosyalarını güncelleme

Uygulamamızın güncellenmiş sürümü için üç yapılandırma dosyası işler. Gerekli görevler şunlardır:

  1. app.yaml uygulamasında gerekli yerleşik 3. taraf kitaplıklarını güncelleyin ve Python 3 taşıma işlemine açık bırakın
  2. Yerleşik olmayan tüm gerekli kitaplıkları belirten requirements.txt ekleyin
  3. Uygulamanın hem yerleşik hem de yerleşik olmayan üçüncü taraf kitaplıkları desteklemesi için appengine_config.py paketini ekleyin

app.yaml

libraries bölümünü güncelleyerek app.yaml dosyanızı düzenleyin. jinja2 adlı kullanıcıyı kaldırıp grpcio, setuptools ve ssl adlı kullanıcıları ekleyin. Üç kitaplık için de kullanılabilir en son sürümü seçin. Python 3 runtime yönergesini de ekleyin, ancak yorum yapmadınız. İşiniz bittiğinde (Python 3.9'u seçtiyseniz) kod aşağıdaki gibi görünmelidir:

ÖNCE:

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

libraries:
- name: jinja2
  version: latest

SONRA:

#runtime: python39
runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

libraries:
- name: grpcio
  version: latest
- name: setuptools
  version: latest
- name: ssl
  version: latest

Değişiklikler ağırlıklı olarak App Engine sunucularında bulunan Python 2 yerleşik kitaplıkları ile ilgilidir (böylece bunları kendi başınıza gruplandırmanız gerekmez). Jinja2'yi, reqs.txt dosyasına ekleyeceğimiz Flask ile birlikte geldiği için kaldırdık. Cloud NDB ve Cloud Storage gibi Google Cloud istemci kitaplıkları her kullanıldığında grpcio ve setuptools gerekir. Son olarak, Cloud Storage'ın kendisi için SSL kitaplığı gerekir. Üstteki yorumlu çalışma zamanı yönergesi, bu uygulamayı Python 3'e taşımaya hazır olduğunuzda içindir. Bu konuyu bu eğiticinin sonunda ele alacağız.

requirements.txt

Flask çerçevesi ile hiçbiri yerleşik olmayan Cloud NDB ve Cloud Storage istemci kitaplıkları gerektiren bir requirements.txt dosyası ekleyin. Dosyayı şu içerikle oluşturun:

flask
google-cloud-ndb
google-cloud-storage

Python 2 App Engine çalışma zamanı, yerleşik olmayan üçüncü taraf kitaplıkların kendi kendine paketlenmesini gerektirir. Bu nedenle, aşağıdaki komutu yürüterek bu kitaplıkları lib klasörüne yükleyin:

pip install -t lib -r requirements.txt

Geliştirme makinenizde hem Python 2 hem de 3 varsa bu kitaplıkların Python 2 sürümlerini aldığınızdan emin olmak için pip2 komutunu kullanmanız gerekebilir. Python 3'e geçiş yaptıktan sonra artık paketinizi oluşturmanız gerekmez.

appengine_config.py

Yerleşik ve yerleşik olmayan üçüncü taraf kitaplıkları destekleyen bir appengine_config.py dosyası ekleyin. Dosyayı şu içerikle oluşturun:

import pkg_resources
from google.appengine.ext import vendor

# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
# Add libraries to pkg_resources working set to find the distribution.
pkg_resources.working_set.add_entry(PATH)

Az önce tamamlanan adımlar, App Engine belgelerinin Python 2 uygulamaları için kitaplık yükleme bölümünde listelenen adımlara benzer veya aynı olmalıdır. Daha açık olmak gerekirse appengine_config.py içeriğinin içeriği buradaki 5. adımda belirtilenlerle eşleşmelidir.

Yapılandırma dosyalarıyla ilgili çalışmalar tamamlandığından, uygulamaya geçelim.

5. Uygulama dosyalarını değiştirme

İçe aktarılanlar

main.py ile ilgili ilk değişiklik grubu, değiştirilen tüm öğelerin değiştirilmesini içeriyor. Değişiklikler aşağıda belirtilmiştir:

  1. webapp2, Flask ile değiştirildi
  2. webapp2_extras Jinja2'yi kullanmak yerine Flask ile birlikte gelen Jinja2'yi kullanın
  3. App Engine Blobstore ve NDB, yerini Cloud NDB ve Cloud Storage'a bırakıyor
  4. webapp içindeki Blobstore işleyicilerin yerini io standart kitaplık modülü, Flask ve werkzeug yardımcı programlarının bir kombinasyonu aldı
  5. Varsayılan olarak Blobstore, adını uygulamanızın URL'sinden (PROJECT_ID.appspot.com) alan bir Cloud Storage paketine yazar. Cloud Storage istemci kitaplığına taşıma yaptığımız için google.auth, aynı paket adını belirtmek amacıyla proje kimliğini almak için kullanılır. (Artık koda gömülü olmadığı için paket adını değiştirebilirsiniz.)

ÖNCE:

import webapp2
from webapp2_extras import jinja2
from google.appengine.ext import blobstore, ndb
from google.appengine.ext.webapp import blobstore_handlers

main.py alan adındaki mevcut içe aktarma bölümünü aşağıdaki kod snippet'iyle değiştirerek yukarıdaki listede yer alan değişiklikleri uygulayın.

SONRA:

import io

from flask import (Flask, abort, redirect, render_template,
        request, send_file, url_for)
from werkzeug.utils import secure_filename

import google.auth
from google.cloud import exceptions, ndb, storage

Başlatma ve gereksiz Jinja2 desteği

Değiştirilecek sonraki kod bloğu, webapp2_extras kaynağından Jinja2 kullanımını belirten BaseHandler kodudur. Jinja2'nin Flask ile birlikte gelmesi ve varsayılan şablon oluşturma motoru olması nedeniyle bu gerekli değildir, bu nedenle kaldırın.

Modül 16 tarafında, eski uygulamada bulunmayan nesneleri örneklendirebilirsiniz. Buna Flask uygulamasının başlatılması ve Cloud NDB ve Cloud Storage için API istemcileri oluşturulması dahildir. Son olarak, Cloud Storage paketi adını yukarıdaki içe aktarmalar bölümünde açıklandığı gibi derledik. Bu güncellemelerin uygulanmadan önceki ve sonraki adımları aşağıda verilmiştir:

ÖNCE:

class BaseHandler(webapp2.RequestHandler):
    'Derived request handler mixing-in Jinja2 support'
    @webapp2.cached_property
    def jinja2(self):
        return jinja2.get_jinja2(app=self.app)

    def render_response(self, _template, **context):
        self.response.write(self.jinja2.render_template(_template, **context))

SONRA:

app = Flask(__name__)
ds_client = ndb.Client()
gcs_client = storage.Client()
_, PROJECT_ID = google.auth.default()
BUCKET = '%s.appspot.com' % PROJECT_ID

Datastore erişimini güncelleme

Cloud NDB, App Engine NDB ile büyük ölçüde uyumludur. Daha önce ele aldığımız farklardan biri, API istemcisi ihtiyacıdır. Bir diğer olasılık ise Datastore erişiminin API istemcisinin Python bağlam yöneticisi tarafından kontrol edilmesini gerektirir. Esasen bu, Cloud NDB istemci kitaplığını kullanan tüm Datastore erişim çağrılarının yalnızca Python with blokları içinde gerçekleşebileceği anlamına gelir.

Yani bir değişiklik söz konusudur. diğeri ise Blobstore ve nesneleri (ör. BlobKey, Cloud Storage tarafından desteklenmediğinden file_blob değerini ndb.StringProperty olacak şekilde değiştirin. Aşağıda, veri modeli sınıfı ve bu değişiklikleri yansıtan güncellenmiş store_visit() ve fetch_visits() işlevleri verilmiştir:

ÖNCE:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)
    file_blob = ndb.BlobKeyProperty()

def store_visit(remote_addr, user_agent, upload_key):
    'create new Visit entity in Datastore'
    Visit(visitor='{}: {}'.format(remote_addr, user_agent),
            file_blob=upload_key).put()

def fetch_visits(limit):
    'get most recent visits'
    return Visit.query().order(-Visit.timestamp).fetch(limit)

SONRA:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)
    file_blob = ndb.StringProperty()

def store_visit(remote_addr, user_agent, upload_key):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent),
                file_blob=upload_key).put()

def fetch_visits(limit):
    'get most recent visits'
    with ds_client.context():
        return Visit.query().order(-Visit.timestamp).fetch(limit)

Şimdiye kadar yapılan değişikliklerin resimli temsili:

a8f74ca392275822.png

İşleyicileri güncelleme

Yükleme işleyici

webapp2 bölgesindeki işleyiciler, Flask'ta işlev görürken sınıflardır. Flask, işlevi dekore etmek için HTTP fiil yöntemi yerine fiili kullanıyor. Blobstore ve webapp işleyicilerinin yerini, Cloud Storage'ın yanı sıra Flask ve yardımcı programındaki işlevler alıyor:

ÖNCE:

class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
    'Upload blob (POST) handler'
    def post(self):
        uploads = self.get_uploads()
        blob_id = uploads[0].key() if uploads else None
        store_visit(self.request.remote_addr, self.request.user_agent, blob_id)
        self.redirect('/', code=307)

SONRA:

@app.route('/upload', methods=['POST'])
def upload():
    'Upload blob (POST) handler'
    fname = None
    upload = request.files.get('file', None)
    if upload:
        fname = secure_filename(upload.filename)
        blob = gcs_client.bucket(BUCKET).blob(fname)
        blob.upload_from_file(upload, content_type=upload.content_type)
    store_visit(request.remote_addr, request.user_agent, fname)
    return redirect(url_for('root'), code=307)

Bu güncellemeyle ilgili bazı notlar:

  • Dosya yapıları artık blob_id yerine dosya adıyla (fname), varsa None ile tanımlanıyor (kullanıcı dosya yüklemeyi devre dışı bıraktı).
  • Blobstore işleyicileri, yükleme işlemini kullanıcılarından soyutlasa da Cloud Storage bunu yapmaz. Bu nedenle, dosyanın blob nesnesini ve konumunu (paket) ayarlayan yeni eklenen kodun yanı sıra gerçek yüklemeyi gerçekleştiren çağrıyı da görebilirsiniz. (upload_from_file()).
  • webapp2, uygulama dosyasının alt kısmında bir yönlendirme tablosu kullanırken Flask rotaları her bir dekore edilmiş işleyicide bulunur.
  • Her iki işleyici de ana sayfaya ( /) yönlendirerek işlevlerini tamamlarken POST isteğini HTTP 307 dönüş koduyla korur.

İşleyiciyi indir

İndirme işleyicinin güncellenmesi, yükleme işleyiciye benzer bir kalıp izler ve yalnızca çok daha az koda bakmanız gerekir. Blobstore ve webapp işlevini, Cloud Storage ve Flask eşdeğerleriyle değiştirin:

ÖNCE:

class ViewBlobHandler(blobstore_handlers.BlobstoreDownloadHandler):
    'view uploaded blob (GET) handler'
    def get(self, blob_key):
        self.send_blob(blob_key) if blobstore.get(blob_key) else self.error(404)

SONRA:

@app.route('/view/<path:fname>')
def view(fname):
    'view uploaded blob (GET) handler'
    blob = gcs_client.bucket(BUCKET).blob(fname)
    try:
        media = blob.download_as_bytes()
    except exceptions.NotFound:
        abort(404)
    return send_file(io.BytesIO(media), mimetype=blob.content_type)

Bu güncellemeyle ilgili notlar:

  • Yine Flask, işleyici işlevlerini kendi rotalarıyla süslerken webapp, bunu alttaki bir yönlendirme tablosunda yapar. Bu nedenle, Flask'ın ('/view/<path:fname>') ve ('/view/([^/]+)?' kalıp eşleştirme söz dizimini tanıyın.
  • Yükleme işleyicide olduğu gibi, Blobstore işleyicileri tarafından soyutlanan işlevler, yani söz konusu dosyanın (blob) tanımlanması ve ikili programın açık bir şekilde indirilmesi ve Blobstore işleyicinin tek send_blob() yöntem çağrısının karşılaştırılması için Cloud Storage tarafında da biraz daha fazla çalışma yapılması gerekir.
  • Her iki durumda da, yapı bulunmazsa kullanıcıya HTTP 404 hatası döndürülür.

Ana işleyici

Ana uygulamada yapılan son değişiklikler ana işleyicide gerçekleşir. webapp2 HTTP fiil yöntemleri, işlevlerini birleştiren tek bir işlevle değiştirilir. MainHandler sınıfını root() işleviyle değiştirin ve webapp2 yönlendirme tablosunu aşağıda gösterildiği gibi kaldırın:

ÖNCE:

class MainHandler(BaseHandler):
    'main application (GET/POST) handler'
    def get(self):
        self.render_response('index.html',
                upload_url=blobstore.create_upload_url('/upload'))

    def post(self):
        visits = fetch_visits(10)
        self.render_response('index.html', visits=visits)

app = webapp2.WSGIApplication([
    ('/', MainHandler),
    ('/upload', UploadHandler),
    ('/view/([^/]+)?', ViewBlobHandler),
], debug=True)

SONRA:

@app.route('/', methods=['GET', 'POST'])
def root():
    'main application (GET/POST) handler'
    context = {}
    if request.method == 'GET':
        context['upload_url'] = url_for('upload')
    else:
        context['visits'] = fetch_visits(10)
    return render_template('index.html', **context)

get() ve post() yöntemleri arasındaki ayrımlar, root() dilindeki bir if-else ifadesidir. Ayrıca, root() tek bir işlev olduğundan hem GET hem de POST için şablon oluşturmak üzere yalnızca bir çağrı gerçekleştirilir, ancak webapp2 içinde bu mümkün değildir.

main.py ile ilgili bu ikinci ve son değişiklik grubunun resimli temsili şu şekildedir:

5ec38818c32fec2.png

(isteğe bağlı) Geriye dönük uyumluluk "geliştirme"

Dolayısıyla yukarıda oluşturulan çözüm mükemmel bir şekilde çalışır. Ancak bu durum, yalnızca sıfırdan başlıyorsanız ve Blobstore tarafından oluşturulmuş dosyalarınız yoksa işe yarar. Uygulamayı, dosyaları BlobKey yerine dosya adına göre tanımlayacak şekilde güncellediğimiz için tamamlanan Modül 16 uygulaması, artık Blobstore dosyalarını görüntüleyemeyecek. Başka bir deyişle, bu taşıma işlemini gerçekleştirirken geriye dönük olarak uyumsuz bir değişiklik yaptık. Şimdi de main.py uygulamasının bu boşluğu doldurmaya çalışan main-migrate.py adlı (depoda bulunan) alternatif bir sürümünü sunuyoruz.

İlk "uzantı" bir BlobKeyProperty (Cloud Storage'da oluşturulan dosyalar için StringProperty öğesine ek olarak) içeren bir veri modelidir:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)
    file_blob = ndb.BlobKeyProperty()  # backwards-compatibility
    file_gcs  = ndb.StringProperty()

file_blob özelliği Blobstore tarafından oluşturulan dosyaları tanımlamak için kullanılır. file_gcs ise Cloud Storage dosyaları için kullanılır. Artık yeni ziyaret oluştururken file_blob yerine file_gcs içine bir değer açıkça girildiğinden store_visit biraz farklı görünür:

ÖNCE:

def store_visit(remote_addr, user_agent, upload_key):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent),
                file_blob=upload_key).put()

SONRA:

def store_visit(remote_addr, user_agent, upload_key):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent),
                file_gcs=upload_key).put()

En son ziyaretleri getirirken "normalize et"i seç verileri şablona göndermeden önce eklemeniz gerekir:

ÖNCE:

@app.route('/', methods=['GET', 'POST'])
def root():
    'main application (GET/POST) handler'
    context = {}
    if request.method == 'GET':
        context['upload_url'] = url_for('upload')
    else:
        context['visits'] = fetch_visits(10)
    return render_template('index.html', **context)

SONRA:

@app.route('/', methods=['GET', 'POST'])
def root():
    'main application (GET/POST) handler'
    context = {}
    if request.method == 'GET':
        context['upload_url'] = url_for('upload')
    else:
        context['visits'] = etl_visits(fetch_visits(10))
    return render_template('index.html', **context)

Ardından, file_blob veya file_gcs varlığının (ya da hiçbirinin) varlığını onaylayın. Kullanılabilir bir dosya varsa mevcut olanı seçin ve bu tanımlayıcıyı (Blobstore tarafından oluşturulan dosyalar için BlobKey, Cloud Storage tarafından oluşturulan dosyalar için dosya adı) kullanın. "Cloud Storage tarafından oluşturulan dosyalar" dediğimizde, Cloud Storage istemci kitaplığı kullanılarak oluşturulan dosyaları kastediyoruz. Blobstore, aynı zamanda Cloud Storage'a da yazar ancak bu durumda Blobstore tarafından oluşturulan dosyalar olur.

Daha da önemlisi, son kullanıcı için verileri normalleştirmek veya ETL (çıkarmak, dönüştürmek ve yüklemek) üzere kullanılan etl_visits() işlevi nedir? Şöyle görünür:

def etl_visits(visits):
    return [{
            'visitor': v.visitor,
            'timestamp': v.timestamp,
            'file_blob': v.file_gcs if hasattr(v, 'file_gcs') \
                    and v.file_gcs else v.file_blob
            } for v in visits]

Muhtemelen beklediğiniz gibi görünüyor: Kod, tüm ziyaretleri döngüye alır ve her ziyaret için ziyaretçi ve zaman damgası verilerini tam olarak alır, ardından file_gcs veya file_blob olup olmadığını kontrol eder. Varsa bunlardan birini seçer (veya ikisi de yoksa None).

main.py ile main-migrate.py arasındaki farkların bir örneği aşağıda verilmiştir:

718b05b2adadb2e1.png

Blobstore tarafından oluşturulan dosyalar olmadan sıfırdan başlıyorsanız main.py kullanın. Ancak hem Blobstore ve Cloud Storage tarafından oluşturulan dosyalara geçiş yapıyor ve bunları desteklemek istiyorsanız kendi uygulamalarınız için taşımaları planlamanıza yardımcı olmak gibi senaryoların nasıl ele alınacağına ilişkin bir örnek olarak main-migrate.py sayfasına göz atın. Karmaşık taşıma işlemleri yapılırken özel durumların ortaya çıkması olasılığı yüksektir. Dolayısıyla, bu örneğin, gerçek uygulamaları gerçek verilerle modernleştirmeye daha uygun olduğunu göstermek amaçlanmıştır.

6. Özet/Temizlik

Bu bölümde, uygulamayı dağıtıp amaçlandığı şekilde ve yansıtılan herhangi bir çıkışta çalıştığını doğrulayarak bu codelab'i özetledik. Uygulama doğrulamasından sonra temizlik adımlarını uygulayın ve sonraki adımları değerlendirin.

Uygulamayı dağıtma ve doğrulama

Uygulamanızı yeniden dağıtmadan önce, bu bağımsız üçüncü taraf kitaplıklarını lib klasöründe almak için pip install -t lib -r requirements.txt öğesini çalıştırdığınızdan emin olun. Geriye dönük uyumlu çözümü çalıştırmak istiyorsanız önce main-migrate.py öğesini main.py olarak yeniden adlandırın. Şimdi gcloud app deploy komutunu çalıştırın ve uygulamanın Modül 15 uygulamasıyla aynı şekilde çalıştığını onaylayın. Form ekranı şu şekilde görünür:

f5b5f9f19d8ae978.png

En son ziyaret edilen sayfa şuna benzer:

f5ac6b98ee8a34cb.png

App Engine Blobstore'u Cloud Storage, App Engine NDB'yi Cloud NDB ile ve webapp2 kodunu Flask ile değiştirerek bu codelab'i tamamladığınız için tebrik ederiz. Kodunuz artık FINISH (Modül 16) klasöründeki kodla eşleşmelidir. Bu klasörde alternatif main-migrate.py de mevcuttur.

Python 3 "taşıma"

Bu uygulamayı Python 3'e taşımak için gereken tek şey, app.yaml üst kısmındaki yorum eklenmiş Python 3 runtime yönergesidir. Kaynak kodun kendisi Python 3 ile uyumludur, dolayısıyla herhangi bir değişiklik gerekmez. Bunu bir Python 3 uygulaması olarak dağıtmak için aşağıdaki adımları yürütün:

  1. app.yaml üst kısmındaki Python 3 runtime yönergesinin açıklamasını kaldırın.
  2. app.yaml içindeki diğer tüm satırları silin.
  3. appengine_config.py dosyasını silin. (Python 3 çalışma zamanında kullanılmaz)
  4. Varsa lib klasörünü silin. (Python 3 çalışma zamanı ile gerekli değildir)

Temizleme

Genel

Şimdilik işiniz bittiyse faturalandırılma olmaması için App Engine uygulamanızı devre dışı bırakmanızı öneririz. Bununla birlikte, daha fazla test veya deneme yapmak isterseniz App Engine platformunun ücretsiz bir kotası vardır ve bu kullanım katmanını aşmadığınız sürece sizden ücret alınmaz. Burası işlem içindir, ancak ilgili App Engine hizmetleri için de ücret alınabilir. Daha fazla bilgi için fiyatlandırma sayfasına göz atın. Bu taşıma işlemi başka Cloud hizmetlerini içeriyorsa bunlar ayrı olarak faturalandırılır. Her iki durumda da (geçerliyse) "Bu codelab'e özel" bölümünü inceleyin bölümüne bakın.

Ayrıntılı açıklama için, App Engine gibi Google Cloud sunucusuz bilgi işlem platformuna dağıtım yapmak küçük derleme ve depolama maliyetleri gerektirir. Cloud Build'in ve Cloud Storage'ın kendi ücretsiz kotası vardır. Söz konusu resmin depolanması bu kotanın bir kısmını kullanır. Ancak, bu kadar ücretsiz katmanın olmadığı bir bölgede yaşıyor olabilirsiniz. Bu nedenle, olası maliyetleri en aza indirmek için depolama alanı kullanımınız konusunda dikkatli olun. Belirli Cloud Storage "klasörleri" şunları incelemeniz gerekir:

  • console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/images
  • console.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com
  • Yukarıdaki depolama alanı bağlantıları PROJECT_ID ve *LOC*ifadenize bağlıdır (örneğin, "us") Uygulamanız ABD'de barındırılıyorsa.

Öte yandan, bu uygulamayı veya diğer ilgili taşıma codelab'lerini kullanmayacak 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:

Modül 15'ten 16'ya geçiş yaptıysanız Blobstore'da verileriniz olmaya devam edeceğini unutmayın. Bu nedenle, fiyatlandırma bilgilerini yukarıda bulabilirsiniz.

Sonraki adımlar

Bu eğiticinin yanı sıra, eski paket servislerin kullanımdan kaldırılmasına odaklanan diğer taşıma modüllerini de göz önünde bulundurun:

  • Modül 2: App Engine ndb'den Cloud NDB'ye geçiş
  • Modüller 7-9: App Engine Görev Sırası push görevlerini Cloud Tasks'a taşıma
  • Modüller 12-13: App Engine Memcache'den Cloud Memorystore'a taşıma
  • Modül 18-19: App Engine Görev Sırası'ndan (görev alma) Cloud Pub/Sub'a geçiş

App Engine artık Google Cloud'daki tek sunucusuz platform değil. Küçük bir App Engine uygulamanız varsa veya sınırlı işlevselliğe sahip bir uygulamanız varsa ve bunu bağımsız bir mikro hizmete dönüştürmek ya da monolitik bir uygulamayı yeniden kullanılabilir birden fazla bileşene ayırmak istiyorsanız Cloud Functions'a geçmek için iyi nedenler olabilir. Container mimarisine alma işlemi, uygulama geliştirme iş akışınızın bir parçası haline geldiyse, özellikle de bir CI/CD (sürekli entegrasyon/sürekli teslim veya dağıtım) ardışık düzeninden oluşuyorsa Cloud Run'a geçiş yapmayı düşünün. Bu senaryolar aşağıdaki modüllerde ele alınmıştır:

  • App Engine'den Cloud Functions'a geçiş: Modül 11'e bakın
  • App Engine'den Cloud Run'a taşıma: Uygulamanızı Docker ile container mimarisine almak için Modül 4'e, bu işlemi container'lar, Docker bilgileri ya da Dockerfile olmadan yapmak için Modül 5'e bakın.

Başka bir sunucusuz platforma geçmek isteğe bağlıdır. Bu nedenle, herhangi bir değişiklik yapmadan önce uygulamalarınız ve kullanım alanlarınız için en iyi seçenekleri değerlendirmenizi öneririz.

Bir sonraki taşıma modülünden bağımsız olarak tüm Sunucusuz Taşıma İstasyonu içeriklerine (codelab'ler, videolar, kaynak kodu [kullanılabilir olduğunda]) açık kaynak deposundan erişebilirsiniz. Deponun README özelliği, hangi taşıma işlemlerinin göz önünde bulundurulacağı ve ilgili "siparişler" hakkında da bilgi sağlar. göz atmanızı öneririm.

7. Ek kaynaklar

Codelab sorunları/geri bildirimi

Bu codelab'de herhangi bir sorun bulursanız lütfen göndermeden önce sorununuzu arayın. Arama ve yeni sayı oluşturma bağlantıları:

Taşıma kaynakları

Modül 15 (START) ve Modül 16 (FINISH) için depo klasörlerinin bağlantılarını aşağıdaki tabloda bulabilirsiniz. Bunlara tüm App Engine codelab taşıma işlemleri için depodan da erişilebilir. Bu depoyu klonlayabilir veya ZIP dosyası indirebilirsiniz.

Codelab

Python 2

Python 3

Modül 15

kod

Yok

Modül 16 (bu codelab)

kod

(Python 2 ile aynı)

Çevrimiçi kaynaklar

Aşağıda, bu eğitim için alakalı olabilecek çevrimiçi kaynaklar verilmiştir:

App Engine Blobstore ve Cloud Storage

App Engine platformu

Diğer Cloud bilgileri

Python

Videolar

Lisans

Bu çalışma, Creative Commons Attribution 2.0 Genel Amaçlı Lisans ile lisans altına alınmıştır.