Nameko ile Python Mikro Hizmetlerine Giriş

Yayınlanan: 2022-03-11

Tanıtım

Mikro hizmetler mimari modeli , esnekliği ve dayanıklılığı göz önüne alındığında popülaritesi artan bir mimari stildir. Kubernetes gibi teknolojilerle birlikte, bir Mikroservis mimarisi kullanarak bir uygulamanın ön yüklemesini yapmak daha önce hiç olmadığı kadar kolaylaşıyor.

Martin Fowler'ın blogundaki klasik bir makaleye göre, Microservices mimari stili şu şekilde özetlenebilir:

Kısacası, mikro hizmet mimari stili, her biri kendi sürecinde çalışan ve genellikle bir HTTP kaynak API'si olan hafif mekanizmalarla iletişim kuran küçük hizmetler paketi olarak tek bir uygulama geliştirmeye yönelik bir yaklaşımdır. Bu hizmetler, iş yetenekleri etrafında inşa edilmiştir ve tam otomatik dağıtım makineleri tarafından bağımsız olarak dağıtılabilir.

Başka bir deyişle, bir mikro hizmet mimarisini izleyen bir uygulama, bir iletişim protokolü kullanarak birbirleriyle iletişim kuran birkaç bağımsız ve dinamik hizmetten oluşur. HTTP (ve REST) ​​kullanımı yaygındır, ancak göreceğimiz gibi, AMQP (Gelişmiş Mesaj Kuyruğa Alma Protokolü) üzerinden RPC (Uzaktan Yordam Çağrısı) gibi diğer iletişim protokolleri türlerini kullanabiliriz.

Mikro hizmet modeli, belirli bir SOA (hizmet yönelimli mimari) durumu olarak düşünülebilir. Ancak SOA'da, hizmetler arasındaki iletişimi yönetmek için bir ESB (kurumsal hizmet veri yolu) kullanmak yaygındır. ESB'ler genellikle oldukça karmaşıktır ve karmaşık mesaj yönlendirme ve iş kuralları uygulaması için işlevler içerir. Mikro hizmetlerde, alternatif bir yaklaşım kullanmak daha yaygındır: “akıllı uç noktalar ve aptal borular”, yani hizmetlerin tüm iş mantığını ve karmaşıklığını (yüksek uyum) içermesi gerektiği, ancak hizmetler arasındaki bağlantının aşağıdaki kadar basit olması gerektiğidir. mümkün (yüksek dekuplaj), yani bir hizmetin diğer hangi hizmetlerin kendisiyle iletişim kuracağını bilmesi gerekmediği anlamına gelir. Bu, mimari düzeyde uygulanan endişelerin bir ayrımıdır.

Mikro hizmetlerin bir başka yönü de, her hizmette hangi teknolojilerin kullanılması gerektiğine dair bir yaptırımın olmamasıdır. Diğer servislerle iletişim kurabilen herhangi bir yazılım yığını ile bir servis yazabilmelisiniz. Her hizmetin kendi yaşam döngüsü yönetimi de vardır. Tüm bunlar, bir şirkette ekiplerin farklı teknolojiler ve hatta yönetim metodolojileri ile ayrı hizmetler üzerinde çalışmasının mümkün olduğu anlamına gelir. Her ekip, daha çevik bir organizasyon oluşturmaya yardımcı olacak iş yetenekleriyle ilgilenecektir.

Python Mikro Hizmetler

Bu kavramları göz önünde bulundurarak, bu makalede Python kullanarak bir kavram kanıtı Microservices uygulaması oluşturmaya odaklanacağız. Bunun için bir Python mikro hizmet çerçevesi olan Nameko'yu kullanacağız. Dahili AMQP üzerinden RPC'ye sahiptir ve hizmetleriniz arasında kolayca iletişim kurmanıza olanak tanır. Ayrıca, bu eğitimde kullanacağımız HTTP sorguları için basit bir arayüze sahiptir. Ancak, bir HTTP uç noktasını açığa çıkaran Mikro Hizmetler yazmak için Flask gibi başka bir çerçeve kullanmanız önerilir. Flask kullanarak RPC üzerinden Nameko yöntemlerini çağırmak için, yalnızca Flask'ı Nameko ile birlikte çalıştırmak için oluşturulmuş bir sarmalayıcı olan flask_nameko'yu kullanabilirsiniz.

Temel Ortamı Ayarlama

Nameko web sitesinden alınmış olabilecek en basit örneği çalıştırarak başlayalım ve onu amaçlarımız için genişletelim. İlk olarak, Docker'ın kurulu olmasına ihtiyacınız olacak. Örneklerimizde Python 3 kullanacağız, bu yüzden onu da kurduğunuzdan emin olun. Ardından, bir python virtualenv oluşturun ve $ pip install nameko çalıştırın.

Nameko'yu çalıştırmak için RabbitMQ mesaj aracısına ihtiyacımız var. Nameko hizmetlerimiz arasındaki iletişimden sorumlu olacaktır. Endişelenmeyin, makinenize bir bağımlılık daha yüklemeniz gerekmemektedir. Docker ile önceden yapılandırılmış bir görüntüyü indirebilir, çalıştırabilir ve işimiz bittiğinde kapsayıcıyı durdurabiliriz. Arka plan programı, apt-get veya dnf install yok.

Nameko ile Python Microservices, RabbitMQ komisyoncusu ile konuşuyor

$ docker run -p 5672:5672 --hostname nameko-rabbitmq rabbitmq:3 bir RabbitMQ kapsayıcısını başlatın (bunu yapmak için Sudo'ya ihtiyacınız olabilir). Bu, en son sürüm 3 RabbitMQ'yu kullanarak bir Docker kapsayıcısını başlatacak ve onu varsayılan 5672 numaralı bağlantı noktası üzerinden gösterecek.

Mikroservislerle Merhaba Dünya

Devam edin ve aşağıdaki içeriğe sahip hello.py adlı bir dosya oluşturun:

 from nameko.rpc import rpc class GreetingService: name = "greeting_service" @rpc def hello(self, name): return "Hello, {}!".format(name)

Nameko hizmetleri sınıflardır. Bu sınıflar, uzantılar olarak uygulanan giriş noktalarını ortaya çıkarır. Yerleşik uzantılar, RPC yöntemlerini, olay dinleyicilerini, HTTP uç noktalarını veya zamanlayıcıları temsil eden giriş noktaları oluşturma yeteneğini içerir. Ayrıca PostgreSQL veritabanı, Redis vb. ile etkileşim için kullanılabilecek topluluk uzantıları da vardır. Kendi uzantılarınızı yazmanız mümkündür.

Devam edelim ve örneğimizi çalıştıralım. Varsayılan bağlantı noktasında RabbitMQ çalıştırıyorsanız, sadece $ nameko run hello . RabbitMQ'yu bulacak ve ona otomatik olarak bağlanacaktır. Ardından hizmetimizi test etmek için başka bir terminalde $ nameko shell çalıştırın. Bu, aynı RabbitMQ örneğine bağlanacak etkileşimli bir kabuk oluşturacaktır. Harika olan şey, Nameko'nun AMQP üzerinden RPC kullanarak otomatik hizmet keşfini gerçekleştirmesidir. Bir RPC yöntemini çağırırken nameko, karşılık gelen çalışan hizmeti bulmaya çalışacaktır.

RabbitMQ RPC aracılığıyla konuşan iki Nameko servisi

Nameko kabuğunu çalıştırırken, ad alanına eklenen n adlı özel bir nesne alacaksınız. Bu nesne, olayların gönderilmesine ve RPC çağrılarının yapılmasına izin verir. Hizmetimize bir RPC çağrısı yapmak için şunu çalıştırın:

 > >> n.rpc.greetingservice.hello(name='world') 'Hello, world!'

Eşzamanlı Aramalar

Bu hizmet sınıfları, çağrı yapıldığı anda somutlaştırılır ve çağrı tamamlandıktan sonra yok edilir. Bu nedenle, doğal olarak durumsuz olmalıdırlar, yani çağrılar arasında nesne veya sınıfta herhangi bir durumu tutmaya çalışmamalısınız. Bu, hizmetlerin kendilerinin vatansız olması gerektiği anlamına gelir. Tüm hizmetlerin durumsuz olduğu varsayımıyla Nameko, eventlet greenthreads kullanarak eşzamanlılıktan yararlanabilir. Örneklenen hizmetlere "işçiler" denir ve aynı anda çalışan yapılandırılmış maksimum sayıda işçi olabilir.

Nameko eşzamanlılığını pratikte doğrulamak için, yanıtı döndürmeden önce prosedür çağrısına bir uyku ekleyerek kaynak kodunu değiştirin:

 from time import sleep from nameko.rpc import rpc class GreetingService: name = "greeting_service" @rpc def hello(self, name): sleep(5) return "Hello, {}!".format(name)

Zaman uyumsuz etkin olmayan time modülünden sleep kullanıyoruz. Bununla birlikte, hizmetlerimizi nameko run kullanarak çalıştırırken, sleep(5) gibi aramaları engellemenin tetikleyici getirilerini otomatik olarak yamalayacaktır.

Artık bir prosedür çağrısından gelen yanıt süresinin yaklaşık 5 saniye sürmesi bekleniyor. Ancak, aşağıdaki snippet'i nameko kabuğundan çalıştırdığımızda davranışı ne olacak?

 res = [] for i in range(5): hello_res = n.rpc.greeting_service.hello.call_async(name=str(i)) res.append(hello_res) for hello_res in res: print(hello_res.result())

Nameko, her RPC giriş noktası için engellemeyen bir call_async yöntemi sağlar ve daha sonra sonucu için sorgulanabilecek bir proxy yanıt nesnesi döndürür. result yöntemi, yanıt proxy'sinde çağrıldığında, yanıt döndürülene kadar engellenecektir.

Beklendiği gibi, bu örnek yaklaşık beş saniye içinde çalışır. Her çalışan sleep çağrısının bitmesini beklerken engellenir, ancak bu başka bir çalışanın başlamasını engellemez. Bu sleep çağrısını, örneğin, kullanışlı bir engelleme I/O veritabanı çağrısı ile değiştirin ve son derece hızlı bir eşzamanlı hizmete sahip olursunuz.

Daha önce açıklandığı gibi, Nameko bir yöntem çağrıldığında işçiler yaratır. Maksimum çalışan sayısı yapılandırılabilir. Varsayılan olarak, bu sayı 10'a ayarlanmıştır. Yukarıdaki kod parçasındaki range(5) örneğin aralık(20) olarak değiştirmeyi test edebilirsiniz. Bu, hello yöntemini 20 kez çağıracak ve şimdi çalışması on saniye sürecektir:

 > >> res = [] > >> for i in range(20): ... hello_res = n.rpc.greeting_service.hello.call_async(name=str(i)) ... res.append(hello_res) > >> for hellores in res: ... print(hello_res.result()) Hello, 0! Hello, 1! Hello, 2! Hello, 3! Hello, 4! Hello, 5! Hello, 6! Hello, 7! Hello, 8! Hello, 9! Hello, 10! Hello, 11! Hello, 12! Hello, 13! Hello, 14! Hello, 15! Hello, 16! Hello, 17! Hello, 18! Hello, 19!

Şimdi, bu hello yöntemini çağıran çok fazla (10'dan fazla) eşzamanlı kullanıcı aldığınızı varsayalım. Bazı kullanıcılar yanıt için beklenen beş saniyeden fazla bekleyecek. Çözümlerden biri, örneğin bir yapılandırma dosyası kullanarak varsayılan ayarları geçersiz kılarak iş sayısını artırmaktı. Ancak, çağrılan yöntem bazı ağır veritabanı sorgularına dayandığından sunucunuz bu on çalışanla zaten sınırındaysa, çalışan sayısını artırmak yanıt süresinin daha da artmasına neden olabilir.

Hizmetimizi Ölçeklendirme

Daha iyi bir çözüm, Nameko Microservices yeteneklerini kullanmaktır. Şimdiye kadar, RabbitMQ'nun bir örneğini ve hizmetin bir örneğini çalıştıran yalnızca bir sunucu (bilgisayarınız) kullandık. Bir üretim ortamında, çok fazla çağrı alan hizmeti çalıştıran düğümlerin sayısını keyfi olarak artırmak isteyeceksiniz. Mesaj aracınızın daha güvenilir olmasını istiyorsanız, bir RabbitMQ kümesi de oluşturabilirsiniz.

Bir hizmet ölçeklendirmesini simüle etmek için, basitçe başka bir terminal açabilir ve hizmeti daha önce olduğu gibi $ nameko run hello kullanarak çalıştırabiliriz. Bu, on işçiyi daha çalıştırma potansiyeline sahip başka bir hizmet örneğini başlatacaktır. Şimdi bu parçacığı range(20) ile tekrar çalıştırmayı deneyin. Şimdi tekrar çalışması beş saniye sürmelidir. Çalışan birden fazla hizmet örneği olduğunda, Nameko mevcut örnekler arasında RPC isteklerini sıraya dizecektir.

Nameko, bir kümedeki bu yöntem çağrılarını sağlam bir şekilde işlemek için tasarlanmıştır. Bunu test etmek için, snipped'i çalıştırmayı deneyin ve bitmeden önce Nameko hizmetini çalıştıran terminallerden birine gidin ve Ctrl+C iki kez basın. Bu, işçilerin bitirmesini beklemeden ana bilgisayarı kapatırdı. Nameko, çağrıları başka bir uygun hizmet örneğine yeniden tahsis edecektir.

Pratikte, daha sonra yapacağımız gibi, hizmetlerinizi kapsayıcı hale getirmek için Docker'ı ve hizmeti çalıştıran düğümlerinizi ve ileti aracısı gibi diğer bağımlılıkları yönetmek için Kubernetes gibi bir düzenleme aracını kullanıyor olacaksınız. Kubernetes ile doğru bir şekilde yapılırsa, uygulamanızı beklenmeyen zirvelere karşı bağışık, sağlam bir dağıtılmış sistemde etkili bir şekilde dönüştürürsünüz. Ayrıca Kubernetes, sıfır kesintili dağıtımlara izin verir. Bu nedenle, bir hizmetin yeni bir sürümünün dağıtılması, sisteminizin kullanılabilirliğini etkilemeyecektir.

Bir üretim ortamında, özellikle dağıtım sırasında, aynı hizmetin birkaç farklı sürümünün aynı anda çalışması söz konusu olabileceğinden, bazı geriye dönük uyumlulukları göz önünde bulundurarak hizmetler oluşturmak önemlidir. Kubernetes kullanıyorsanız, dağıtım sırasında yalnızca yeterli sayıda çalışan yeni kapsayıcı olduğunda tüm eski sürüm kapsayıcılarını öldürür.

Nameko için aynı hizmetin aynı anda birkaç farklı sürümünün çalışması sorun değil. Çağrıları sıralı olarak dağıttığı için, çağrılar eski veya yeni sürümlerden geçebilir. Bunu test etmek için, hizmetimiz eski sürümü çalıştıran bir terminali tutun ve hizmet modülünü aşağıdaki gibi görünecek şekilde düzenleyin:

 from time import sleep from nameko.rpc import rpc class GreetingService: name = "greeting_service" @rpc def hello(self, name): sleep(5) return "Hello, {}! (version 2)".format(name)

Bu hizmeti başka bir terminalden çalıştırırsanız, aynı anda çalışan iki sürümü alırsınız. Şimdi test snippet'imizi tekrar çalıştırın ve her iki versiyonun da gösterildiğini göreceksiniz:

 > >> res = [] > >> for i in range(5): ... hello_res = n.rpc.greeting_service.hello.call_async(name=str(i)) ... res.append(hello_res) > >> for hellores in res: ... print(hello_res.result()) Hello, 0! Hello, 1! (version 2) Hello, 2! Hello, 3! (version 2) Hello, 4!

Birden Çok Örnekle Çalışma

Artık Nameko ile nasıl verimli çalışacağımızı ve ölçeklendirmenin nasıl çalıştığını biliyoruz. Şimdi bir adım daha ileri gidelim ve Docker ekosisteminden daha fazla araç kullanalım: docker-compose. Bu, tek bir sunucuya dağıtım yapıyorsanız işe yarar; Mikroservis mimarisinin birçok avantajından yararlanmayacağınız için bu kesinlikle ideal değildir. Yine, daha uygun bir altyapıya sahip olmak istiyorsanız, dağıtılmış bir kapsayıcı sistemini yönetmek için Kubernetes gibi bir düzenleme aracı kullanabilirsiniz. Öyleyse devam edin ve docker-compose'ı kurun.

Yine, tek yapmamız gereken bir RabbitMQ örneği dağıtmak ve tüm hizmetlerin bu RabbitMQ örneğine erişebilmesi koşuluyla Nameko gerisini halledecek. Bu örneğin tam kaynak kodu bu GitHub deposunda mevcuttur.

Nameko'nun yeteneklerini test etmek için basit bir seyahat uygulaması oluşturalım. Bu uygulama, havaalanlarının ve gezilerin kaydedilmesine izin verir. Her havaalanı basitçe havaalanının adı olarak saklanır ve yolculuk, başlangıç ​​ve varış havalimanlarının kimliklerini depolar. Sistemimizin mimarisi şuna benzer:

Seyahat uygulama illüstrasyonu

İdeal olarak, her mikro hizmetin kendi veritabanı örneğine sahip olması gerekir. Ancak, basit olması için hem Geziler hem de Havaalanları mikro hizmetlerinin paylaşacağı tek bir Redis veritabanı oluşturdum. Ağ Geçidi mikro hizmeti, HTTP isteklerini REST benzeri basit bir API aracılığıyla alacak ve Havaalanları ve Geziler ile iletişim kurmak için RPC'yi kullanacak.

Ağ Geçidi mikro hizmetiyle başlayalım. Yapısı basittir ve Flask gibi bir çerçeveden gelen herkes için çok tanıdık olmalıdır. Temel olarak, her biri hem GET hem de POST yöntemlerine izin veren iki uç nokta tanımlarız:

 import json from nameko.rpc import RpcProxy from nameko.web.handlers import http class GatewayService: name = 'gateway' airports_rpc = RpcProxy('airports_service') trips_rpc = RpcProxy('trips_service') @http('GET', '/airport/<string:airport_id>') def get_airport(self, request, airport_id): airport = self.airports_rpc.get(airport_id) return json.dumps({'airport': airport}) @http('POST', '/airport') def post_airport(self, request): data = json.loads(request.get_data(as_text=True)) airport_id = self.airports_rpc.create(data['airport']) return airport_id @http('GET', '/trip/<string:trip_id>') def get_trip(self, request, trip_id): trip = self.trips_rpc.get(trip_id) return json.dumps({'trip': trip}) @http('POST', '/trip') def post_trip(self, request): data = json.loads(request.get_data(as_text=True)) trip_id = self.trips_rpc.create(data['airport_from'], data['airport_to']) return trip_id

Şimdi Havaalanları hizmetine bir göz atalım. Beklendiği gibi, iki RPC yöntemi sunar. get yöntemi, yalnızca Redis veritabanını sorgulayacak ve verilen kimlik için havaalanını döndürecektir. create yöntemi rastgele bir kimlik oluşturacak, havaalanı bilgilerini depolayacak ve kimliği döndürecektir:

 import uuid from nameko.rpc import rpc from nameko_redis import Redis class AirportsService: name = "airports_service" redis = Redis('development') @rpc def get(self, airport_id): airport = self.redis.get(airport_id) return airport @rpc def create(self, airport): airport_id = uuid.uuid4().hex self.redis.set(airport_id, airport) return airport_id

nameko_redis uzantısını nasıl kullandığımıza dikkat edin. Topluluk uzantıları listesine bir göz atın. Uzantılar, bağımlılık enjeksiyonunu kullanan bir şekilde uygulanır. Nameko, her çalışanın kullanacağı gerçek uzantı nesnesini başlatmayla ilgilenir.

Havaalanları ve Trips mikro hizmetleri arasında pek bir fark yoktur. Trips mikro hizmetinin nasıl görüneceği aşağıda açıklanmıştır:

 import uuid from nameko.rpc import rpc from nameko_redis import Redis class AirportsService: name = "trips_service" redis = Redis('development') @rpc def get(self, trip_id): trip = self.redis.get(trip_id) return trip @rpc def create(self, airport_from_id, airport_to_id): trip_id = uuid.uuid4().hex self.redis.set(trip_id, { "from": airport_from_id, "to": airport_to_id }) return trip_id

Her bir mikro hizmet için Dockerfile de çok basittir. Tek bağımlılık nameko ve Havaalanları ve Geziler hizmetlerinde de nameko-redis kurulumuna ihtiyaç vardır. Bu bağımlılıklar, her hizmette requirements.txt dosyasında verilmiştir. Havaalanları hizmeti için Dockerfile şöyle görünür:

 FROM python:3 RUN apt-get update && apt-get -y install netcat && apt-get clean WORKDIR /app COPY requirements.txt ./ RUN pip install --no-cache-dir -r requirements.txt COPY config.yml ./ COPY run.sh ./ COPY airports.py ./ RUN chmod +x ./run.sh CMD ["./run.sh"]

Bununla diğer hizmetler için Dockerfile arasındaki tek fark, buna göre değiştirilmesi gereken kaynak dosyadır (bu durumda airports.py ).

run.sh betiği RabbitMQ'ya kadar beklemeyi halleder ve Airports and Trips servislerinde Redis veritabanı hazırdır. Aşağıdaki pasaj, havaalanları için run.sh içeriğini gösterir. Yine, diğer hizmetler için aiports gateway veya buna göre trips geçmeniz yeterlidir:

 #!/bin/bash until nc -z ${RABBIT_HOST} ${RABBIT_PORT}; do echo "$(date) - waiting for rabbitmq..." sleep 1 done until nc -z ${REDIS_HOST} ${REDIS_PORT}; do echo "$(date) - waiting for redis..." sleep 1 done nameko run --config config.yml airports

Hizmetlerimiz artık çalışmaya hazır:

$ docker-compose up

Sistemimizi test edelim. Komutu çalıştırın:

 $ curl -i -d "{\"airport\": \"first_airport\"}" localhost:8000/airport HTTP/1.1 200 OK Content-Type: text/plain; charset=utf-8 Content-Length: 32 Date: Sun, 27 May 2018 05:05:53 GMT f2bddf0e506145f6ba0c28c247c54629

Bu son satır, havaalanımız için oluşturulan kimliktir. Çalışıp çalışmadığını test etmek için şunu çalıştırın:

 $curl localhost:8000/airport/f2bddf0e506145f6ba0c28c247c54629 {"airport": "first_airport"} Great, now let's add another airport: $ curl -i -d "{\"airport\": \"second_airport\"}" localhost:8000/airport HTTP/1.1 200 OK Content-Type: text/plain; charset=utf-8 Content-Length: 32 Date: Sun, 27 May 2018 05:06:00 GMT 565000adcc774cfda8ca3a806baec6b5

Şimdi iki hava limanımız var, bu bir yolculuk oluşturmaya yeter. Şimdi bir gezi oluşturalım:

 $ curl -i -d "{\"airport_from\": \"f2bddf0e506145f6ba0c28c247c54629\", \"airport_to\": \"565000adcc774cfda8ca3a806baec6b5\"}" localhost:8000/trip HTTP/1.1 200 OK Content-Type: text/plain; charset=utf-8 Content-Length: 32 Date: Sun, 27 May 2018 05:09:10 GMT 34ca60df07bc42e88501178c0b6b95e4

Daha önce olduğu gibi, bu son satır yolculuk kimliğini temsil eder. Doğru yerleştirilip yerleştirilmediğini kontrol edelim:

 $ curl localhost:8000/trip/34ca60df07bc42e88501178c0b6b95e4 {"trip": "{'from': 'f2bddf0e506145f6ba0c28c247c54629', 'to': '565000adcc774cfda8ca3a806baec6b5'}"}

Özet

RabbitMQ'nun yerel çalışan bir örneğini oluşturarak, ona bağlanarak ve birkaç test gerçekleştirerek Nameko'nun nasıl çalıştığını gördük. Daha sonra edindiğimiz bilgileri bir Mikroservis mimarisi kullanarak basit bir sistem oluşturmak için uyguladık.

Son derece basit olmasına rağmen, sistemimiz üretime hazır bir dağıtımın nasıl görüneceğine çok yakındır. Tercihen, Falcon veya Flask gibi HTTP isteklerini işlemek için başka bir çerçeve kullanırsınız. Her ikisi de harika seçeneklerdir ve örneğin Ağ Geçidi hizmetinizi kırmak istemeniz durumunda diğer HTTP tabanlı mikro hizmetler oluşturmak için kolayca kullanılabilir. Flask, Nameko ile etkileşim kurmak için zaten bir eklentiye sahip olma avantajına sahiptir, ancak nameko-proxy'yi doğrudan herhangi bir çerçeveden kullanabilirsiniz.

Nameko'nun test edilmesi de çok kolaydır. Basit olması için burada test etme konusunu ele almadık, ancak Nameko'nun test belgelerine bakın.

Bir mikro hizmet mimarisi içindeki tüm hareketli parçalarla, sağlam bir kayıt sistemine sahip olduğunuzdan emin olmak istersiniz. Bir tane oluşturmak için bkz. Python Logging: An In-Deepth Tutorial by Toptaler ve Python Developer: Son Nguyen Kim.