gRPC-Python'u kullanmaya başlama

1. Giriş

Bu codelab'de, Python'da yazılmış bir rota eşleme uygulamasının temelini oluşturan bir istemci ve sunucu oluşturmak için gRPC-Python'ı kullanacaksınız.

Eğitimin sonunda, haritada belirli koordinatlarda bulunan yerin adını veya posta adresini almak için gRPC kullanarak uzak bir sunucuya bağlanan bir istemciniz olacak. Tam teşekküllü bir uygulama, bir rota üzerindeki önemli yerleri listelemek veya özetlemek için bu istemci-sunucu tasarımını kullanabilir.

Hizmet, istemci ve sunucu için standart kod oluşturmak üzere kullanılacak bir Protocol Buffers dosyasında tanımlanır. Böylece, bu işlevselliği uygularken zamandan ve emekten tasarruf edersiniz.

Oluşturulan bu kod, yalnızca sunucu ile istemci arasındaki iletişimin karmaşıklıklarını değil, aynı zamanda veri serileştirme ve seri durumdan çıkarma işlemlerini de ele alır.

Neler öğreneceksiniz?

  • Hizmet API'sini tanımlamak için Protocol Buffers'ı kullanma.
  • Otomatik kod oluşturma kullanarak bir Protokol Arabellek tanımından gRPC tabanlı istemci ve sunucu oluşturma.
  • gRPC ile istemci-sunucu iletişimi hakkında bilgi sahibi olmanız gerekir.

Bu codelab, gRPC'ye yeni başlayan veya gRPC ile ilgili bilgilerini tazelemek isteyen Python geliştiricilerin yanı sıra dağıtılmış sistemler oluşturmakla ilgilenen herkes için hazırlanmıştır. Daha önce gRPC deneyimi gerekmez.

2. Başlamadan önce

İhtiyacınız olanlar

  • Python 3.9 veya sonraki sürümler. Python 3.13'ü öneririz. Platforma özel yükleme talimatları için Python Kurulumu ve Kullanımı başlıklı makaleyi inceleyin. Alternatif olarak, uv veya pyenv gibi araçları kullanarak sistem dışı bir Python yükleyin.
  • Python paketlerini yüklemek için pip.
  • Python sanal ortamları oluşturmak için venv.

ensurepip ve venv paketleri, Python Standart Kitaplığı'nın bir parçasıdır ve genellikle varsayılan olarak kullanılabilir.

Ancak Ubuntu da dahil olmak üzere bazı Debian tabanlı dağıtımlar, python'u yeniden dağıtırken bunları hariç tutmayı tercih eder. Paketleri yüklemek için şu komutu çalıştırın:

sudo apt install python3-pip python3-venv

Kodu alın

Bu codelab, öğrenme sürecinizi kolaylaştırmak için başlamanıza yardımcı olacak önceden oluşturulmuş bir kaynak kodu iskeleti sunar. Aşağıdaki adımlar, grpc_tools.protoc Protocol Buffer derleyici eklentisini kullanarak gRPC kodu oluşturma da dahil olmak üzere uygulamayı tamamlama konusunda size yol gösterecektir.

grpc-codelabs

Bu codelab'in iskele kaynak kodu, codelabs/grpc-python-getting-started/start_here dizininde bulunur. Kodu kendiniz uygulamayı tercih etmezseniz tamamlanmış kaynak kodu completed dizininde bulabilirsiniz.

Öncelikle codelab çalışma dizinini oluşturun ve bu dizine gidin:

mkdir grpc-python-getting-started && cd grpc-python-getting-started

Codelab'i indirip ayıklayın:

curl -sL https://github.com/grpc-ecosystem/grpc-codelabs/archive/refs/heads/v1.tar.gz \
  | tar xvz --strip-components=4 \
  grpc-codelabs-1/codelabs/grpc-python-getting-started/start_here

Alternatif olarak, yalnızca codelab dizinini içeren .zip dosyasını indirebilir ve manuel olarak sıkıştırmasını açabilirsiniz.

3. Hizmeti tanımlama

İlk adımınız, Protocol Buffers arayüz tanımı dilini kullanarak uygulamanın gRPC hizmetini, RPC yöntemini ve istek ile yanıt mesajı türlerini tanımlamaktır. Hizmetinizde sunulacaklar:

  • Sunucunun uyguladığı ve istemcinin çağırdığı GetFeature adlı bir RPC yöntemi.
  • Point ve Feature mesaj türleri, GetFeature yöntemi kullanılırken istemci ile sunucu arasında değiştirilen veri yapılarıdır. İstemci, sunucuya gönderdiği GetFeature isteğinde harita koordinatlarını Point olarak sağlar ve sunucu, bu koordinatlarda bulunan her şeyi açıklayan ilgili bir Feature ile yanıt verir.

Bu RPC yöntemi ve mesaj türleri, sağlanan kaynak kodun protos/route_guide.proto dosyasında tanımlanır.

Protocol Buffers genellikle protobuf olarak bilinir. gRPC terminolojisi hakkında daha fazla bilgi için gRPC'nin Temel kavramlar, mimari ve yaşam döngüsü başlıklı makalesine bakın.

Mesaj türleri

Kaynak kodun protos/route_guide.proto dosyasında önce Point mesaj türünü tanımlayın. Point, haritadaki bir enlem-boylam koordinat çiftini temsil eder. Bu codelab'de koordinatlar için tam sayıları kullanın:

message Point {
  int32 latitude = 1;
  int32 longitude = 2;
}

1 ve 2 sayıları, message yapısındaki her alan için benzersiz kimlik numaralarıdır.

Ardından, Feature mesaj türünü tanımlayın. Bir Feature, Point ile belirtilen bir konumdaki bir şeyin adı veya posta adresi için string alanını kullanır:

message Feature {
  // The name or address of the feature.
  string name = 1;

  // The point where the feature is located.
  Point location = 2;
}

Hizmet yöntemi

route_guide.proto dosyasında, uygulamanın hizmeti tarafından sağlanan bir veya daha fazla yöntemi tanımlayan RouteGuide adlı bir service yapısı bulunur.

rpc yöntemini RouteGuide tanımının içine ekleyin.GetFeature Daha önce açıklandığı gibi, bu yöntem belirli bir koordinat kümesinden bir konumun adını veya adresini arar. Bu nedenle, belirli bir Point için GetFeature işlevinin Feature döndürmesini sağlayın:

service RouteGuide {
  // Definition of the service goes here

  // Obtains the feature at a given position.
  rpc GetFeature(Point) returns (Feature) {}
}

Bu, tekli bir UPÇ yöntemidir: İstemcinin sunucuya istek gönderdiği ve yanıtın geri gelmesini beklediği basit bir UPÇ'dir (yerel bir işlev çağrısı gibi).

4. İstemci ve sunucu kodunu oluşturma

Ardından, protokol arabelleği derleyicisini kullanarak .proto dosyasından hem istemci hem de sunucu için standart gRPC kodunu oluşturun.

gRPC Python kod üretimi için grpcio-tools'u oluşturduk. Şunları içermektedir:

  1. message tanımlarından Python kodu oluşturan normal protoc derleyicisi.
  2. service tanımlarından Python kodu (istemci ve sunucu saplamaları) oluşturan gRPC protobuf eklentisi.

grpcio-tools Python paketini pip kullanarak yükleyeceğiz. Projenizin bağımlılıklarını sistem paketlerinden ayırmak için yeni bir Python sanal ortamı (venv) oluşturalım:

python3 -m venv --upgrade-deps .venv

Sanal ortamı bash/zsh kabuğunda etkinleştirmek için:

source .venv/bin/activate

Windows ve standart dışı kabuklar için https://docs.python.org/3/library/venv.html#how-venvs-work adresindeki tabloya bakın.

Ardından, grpcio-tools'u yükleyin (bu işlem grpcio paketini de yükler):

pip install grpcio-tools

Python standart kodunu oluşturmak için aşağıdaki komutu kullanın:

python -m grpc_tools.protoc --proto_path=./protos  \
 --python_out=. --pyi_out=. --grpc_python_out=. \
 ./protos/route_guide.proto

Bu işlem, route_guide.proto içinde tanımladığımız arayüzler için aşağıdaki dosyaları oluşturur:

  1. route_guide_pb2.py, message tanımlarından oluşturulan sınıfları dinamik olarak oluşturan kodu içerir.
  2. route_guide_pb2.pyi, message tanımlarından oluşturulan bir "stub dosyası" veya "tür ipucu dosyası"dır. Yalnızca imzaları içerir ve uygulama içermez. Stub dosyaları, IDE'ler tarafından daha iyi otomatik tamamlama ve hata algılama sağlamak için kullanılabilir.
  3. route_guide_pb2_grpc.py, service tanımlarından oluşturulur ve gRPC'ye özgü sınıflar ve işlevler içerir.

gRPC'ye özel kod şunları içerir:

  1. RouteGuideStub, gRPC istemcisi tarafından RouteGuide RPC'lerini çağırmak için kullanılabilir.
  2. RouteGuideServicer hizmetinin uygulamaları için arayüzü tanımlar.RouteGuide
  3. add_RouteGuideServicer_to_server işlevi, RouteGuideServicer öğesini gRPC sunucusuna kaydetmek için kullanılır.

5. Hizmeti oluşturun

Öncelikle RouteGuide sunucuyu nasıl oluşturduğunuza bakalım. RouteGuide sunucusu oluşturma ve çalıştırma iki iş öğesine ayrılır:

  • Hizmet tanımımızdan oluşturulan hizmet arayüzünü, hizmetin gerçek "işini" yapan işlevlerle uygulama.
  • İstemcilerden gelen istekleri dinlemek ve yanıtları iletmek için belirli bir bağlantı noktasında gRPC sunucusu çalıştırma.

İlk RouteGuide sunucusunu start_here/route_guide_server.py içinde bulabilirsiniz.

RouteGuide'ı uygulama

route_guide_server.py, oluşturulan sınıf route_guide_pb2_grpc.RouteGuideServicer'ı alt sınıfa ayıran bir RouteGuideServicer sınıfına sahip:

# RouteGuideServicer provides an implementation
# of the methods of the RouteGuide service.
class RouteGuideServicer(route_guide_pb2_grpc.RouteGuideServicer):

RouteGuideServicer, tüm RouteGuide hizmet yöntemlerini uygular.

Basit bir RPC uygulamasını ayrıntılı olarak inceleyelim. Yöntem GetFeature, istemciden Point alır ve veritabanından ilgili özellik bilgilerini Feature olarak döndürür.

def GetFeature(self, request, context):
    feature = get_feature(self.db, request)
    if feature is None:
        return route_guide_pb2.Feature(name="", location=request)
    else:
        return feature

Yönteme, RPC için bir route_guide_pb2.Point istek ve zaman aşımı sınırları gibi RPC'ye özgü bilgileri sağlayan bir grpc.ServicerContext nesnesi iletilir. route_guide_pb2.Feature yanıtı döndürülür.

Sunucuyu başlatma

Tüm RouteGuide yöntemlerini uyguladıktan sonraki adım, istemcilerin hizmetinizi gerçekten kullanabilmesi için bir gRPC sunucusu başlatmaktır:

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    route_guide_pb2_grpc.add_RouteGuideServicer_to_server(
        RouteGuideServicer(),
        server,
    )
    listen_addr = "localhost:50051"
    server.add_insecure_port(listen_addr)
    print(f"Starting server on {listen_addr}")
    server.start()
    server.wait_for_termination()

Sunucu start() yöntemi engelleme yapmaz. İstekleri işlemek için yeni bir iş parçacığı oluşturulur. server.start() işlevini çağıran iş parçacığı, bu süre zarfında genellikle başka bir iş yapmaz. Bu durumda, sunucu sonlandırılana kadar arama iş parçacığını temiz bir şekilde engellemek için server.wait_for_termination() numaralı telefonu arayabilirsiniz.

6. İstemciyi oluşturma

Bu bölümde, RouteGuide hizmetimiz için istemci oluşturma konusunu ele alacağız. İlk müşteri kodunu start_here/route_guide_client.py bölümünde görebilirsiniz.

Taslak oluşturma

Hizmet yöntemlerini çağırmak için önce bir taslak oluşturmamız gerekir.

route_guide_client.py dosyasındaki .proto öğemizden oluşturulan route_guide_pb2_grpc modülünün RouteGuideStub sınıfını başlatırız.

channel = grpc.insecure_channel("localhost:50051")
stub = route_guide_pb2_grpc.RouteGuideStub(channel)

Arama hizmeti yöntemleri

Tek bir yanıt döndüren RPC yöntemleri (response-unary yöntemleri olarak bilinir) için gRPC Python hem eşzamanlı (engelleyici) hem de eşzamansız (engelleyici olmayan) kontrol akışı semantiğini destekler.

Simple RPC

Öncelikle, hizmeti çağırmak için bir Point tanımlayalım. Bu işlem, route_guide_pb2 paketinden bazı özelliklere sahip bir nesne oluşturmak kadar basit olmalıdır:

point = route_guide_pb2.Point(latitude=412346009, longitude=-744026814)

Basit RPC GetFeature için yapılan senkronize bir çağrı, yerel bir yöntemi çağırmak kadar basittir. RPC çağrısı, sunucunun yanıt vermesini bekler ve yanıt döndürür veya istisna oluşturur. Yöntemi şu şekilde çağırabilir ve yanıtı görebiliriz:

feature = stub.GetFeature(point)
print(feature)

Özellik nesnesinin alanlarını inceleyebilir ve isteğin sonucunu çıkış olarak verebilirsiniz:

if feature.name:
    print(f"Feature called '{feature.name}' at {format_point(feature.location)}")
else:
    print(f"Found no feature at at {format_point(feature.location)}")

7. Deneyin

Sunucuyu çalıştırın:

python route_guide_server.py

Farklı bir terminalden sanal ortamı tekrar etkinleştirin ve istemciyi çalıştırın:

python route_guide_client.py

Aşağıdakine benzer bir çıkış görürsünüz. Zaman damgaları, netlik için çıkarılmıştır:

name: "16 Old Brook Lane, Warwick, NY 10990, USA"
location {
  latitude: 412346009
  longitude: -744026814
}

Feature called '16 Old Brook Lane, Warwick, NY 10990, USA' at latitude: 412346009, longitude: -744026814

8. Sırada ne var?