Кратко про Nameko Python

от автора

Привет, Хабр!

Nameko, как фреймворк для Python, предлагает удобные абстракции и инструменты для создания микросервисов, ориентированных на сообщения и события.

С Nameko можно получить не только инструмент для создания микросервисов, но и платформу для реализации распределенных систем с поддержкой Dependency Injection, позволяющей легко интегрировать различные компоненты приложения.

Установим через пип:

pip install nameko

Это установит Nameko и все зависимости.

После установки проверим:

nameko --version

Если выдало версию — все ок.

Встроенные расширения

AMQP — это протокол обмена сообщениями, который Nameko использует для межсервисного взаимодействия. Встроенное расширение AMQP позволяет настроить и использовать очереди сообщений для связи между сервисами:

from nameko.messaging import Publisher, rpc  class ServiceA:     name = "service_a"      publisher = Publisher()      @rpc     def send_message(self, message):         self.publisher.publish(message)  class ServiceB:     name = "service_b"      @rpc     def process_message(self, message):         print("Received message:", message)

ServiceA отправляет сообщение через очередь, а ServiceB принимает и обрабатывает его.

DependencyProvider позволяет инжектировать зависимости в ваши сервисы, обеспечивая более чистый и модульный код. Создадим сервис, который использует БД:

from nameko.dependency_providers import DependencyProvider  class DatabaseWrapper:     def __init__(self, db_url):         self.db_url = db_url      def execute_query(self, query):         # Execute query logic here         pass  class DatabaseProvider(DependencyProvider):     def setup(self):         self.database = DatabaseWrapper(self.container.config['DATABASE_URL'])      def get_dependency(self, worker_ctx):         return self.database  class MyService:     name = "my_service"      db = DatabaseProvider()      def some_method(self):         result = self.db.execute_query("SELECT * FROM table")         return result

Юзаем DatabaseProvider для предоставления экземпляра DatabaseWrapper в сервис.

Встроенное расширение HTTP позволяет создавать веб-сервисы на базе Nameko, обеспечивая взаимодействие с внешними клиентами через HTTP. Например:

from nameko.web.handlers import http  class HttpService:     name = "http_service"      @http('GET', '/hello')     def hello_world(self, request):         return 200, "Hello, World!"

RPC также нашло свою реализацию в nameko, пример:

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

GreetingService предоставляет метод greet, который может быть вызван удаленно другими сервисами.

Events позволяет сервисам подписываться на события и реагировать на них:

from nameko.events import event_handler  class NotificationService:     name = "notification_service"      @event_handler("email_service", "email_sent")     def handle_email_sent(self, payload):         print("Email sent:", payload)

NotificationService подписывается на событие email_sent от сервиса email_service и обрабатывает его.

Timer позволяет создавать периодические задачи в приложении:

from nameko.timer import timer  class CleanupService:     name = "cleanup_service"      @timer(interval=60)  # Выполнять каждую минуту     def cleanup(self):         print("Performing cleanup...")         # Логика очистки данных

Сервис будет выполнять метод cleanup каждую минуту.

Что там с тестами?

Для написания unit-тестов в Nameko можно использовать стандартные фреймворки для тестирования Python, какpytest или unittest. Для этого создаем экземпляр сервиса в тестовой среде и вызываем его методы для проверки их поведения. Предположим, у нас есть простой сервис для работы с мат. операциями:

# math_service.py from nameko.rpc import rpc  class MathService:     name = "math_service"      @rpc     def add(self, x, y):         return x + y

Напишем unit-тест для этого сервиса с использованием pytest:

# test_math_service.py from math_service import MathService  def test_add():     service = MathService()     assert service.add(2, 3) == 5

Интеграционные тесты в Nameko позволяют проверить взаимодействие между различными сервисами и убедиться, что они взаимодействуют правильно в рамках системы. Для этого можно использовать механизм запуска сервисов в тестовом режиме и проверять их взаимодействие через RPC вызовы или события. Пример интеграционного теста с использованием pytest:

# test_order_service.py from nameko.testing.services import entrypoint_hook  from order_service import OrderService from product_service import ProductService  def test_create_order():     # создаем экземпляр сервиса OrderService     order_service = OrderService()      # создаем экземпляр сервиса ProductService     product_service = ProductService()      # входим в контекст сервиса OrderService     with entrypoint_hook(order_service, "create_order") as create_order:         # вызываем метод create_order         order_id = create_order(user_id=1, product_id=1, quantity=2)          # проверяем, что заказ успешно создан         assert order_id is not None

Иногда может потребоваться использовать mock объекты для имитации зависимостей в тестах. В Nameko это можно реализовать с помощью entrypoint механизма:

# test_email_service.py from nameko.testing.services import entrypoint_hook from unittest.mock import Mock  from email_service import EmailService  def test_send_email():     # создаем экземпляр сервиса EmailService     email_service = EmailService()      # создаем mock объект для отправки email     mock_send_email = Mock()      # подменяем реальный метод отправки email на mock объект     email_service.send_email = mock_send_email      # входим в контекст сервиса EmailService     with entrypoint_hook(email_service, "send_email") as send_email:         # вызываем метод send_email         send_email(recipient="test@example.com", subject="Test", body="This is a test email")          # проверяем, что метод send_email был вызван с правильными аргументами         mock_send_email.assert_called_once_with("test@example.com", "Test", "This is a test email")

Написание расширений

Путем написания расширений можнонастраивать поведение Nameko под конкретные потребности.

Допустим, нужно добавить механизм аутентификации к сервисам Nameko. Можно написать расширение, которое будет обрабатывать проверку подлинности запросов к сервисам:

from nameko.extensions import Extension  class AuthExtension(Extension):     def __init__(self, auth_service):         self.auth_service = auth_service      def bind(self, container):         super(AuthExtension, self).bind(container)         self.container.auth = self      def get_dependency(self, worker_ctx):         return AuthServiceWrapper(self.auth_service)  class AuthServiceWrapper:     def __init__(self, auth_service):         self.auth_service = auth_service      def authenticate(self, token):         # логика аутентификации         pass

Или к примеру хотим добавить мониторинг производительности в сервисы Nameko. Можно написать расширение, которое будет собирать статистику о времени выполнения запросов и других метриках:

from nameko.extensions import Extension  class MonitoringExtension(Extension):     def __init__(self, statsd_client):         self.statsd_client = statsd_client      def bind(self, container):         super(MonitoringExtension, self).bind(container)         self.container.monitoring = self      def record_request_time(self, service_name, method_name, time_taken):         metric_name = f"{service_name}.{method_name}.request_time"         self.statsd_client.timing(metric_name, time_taken)

После написания расширения, можно использовать его в своих сервисах. Для этого просто добавляем его в контейнер Nameko:

from nameko.rpc import rpc from my_extensions import AuthExtension  class MyService:     name = "my_service"      auth = AuthExtension()      @rpc     def my_method(self, request):         # проверка аутентификации         self.auth.authenticate(request.token)         # логика метода

Статья подготовлена в рамках набора на курс Python Developer. Professional. По ссылке вы сможете узнать о курсе подробнее, а также зарегистрироваться на бесплатный вебинар.


ссылка на оригинал статьи https://habr.com/ru/articles/798913/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *