• Главная
  • DataScience
  • CloudServicesEngineer
  • Поиск
Data Science

AG. ПР. Создание HTTP API с помощью Cloud Functions и API Gatewa

ПР. Создание HTTP API с помощью Cloud Functions и API Gatewa

Кратко:

  • Создание HTTP API с помощью Cloud Functions и API Gateway.
  • Создание спецификации hello-world.yaml для API-шлюза.
  • Тестирование запроса с параметрами на API-шлюзе.
  • Создание функции function-for-user-requests.py для работы с PostgreSQL.
  • Обновление спецификации API Gateway для предоставления публичного доступа к функции.
  • Тестирование функции в браузере и проверка работы с параметрами.

Практическая работа. Создание HTTP API с помощью Cloud Functions и API Gateway

На предыдущем практическом занятии мы создали простую систему, которая проверяет доступность сайта yandex.ru и измеряет время ответа на запрос. Полученную информацию функция записывала в базу данных PostgreSQL. На этом уроке мы доработаем начатый проект и добавим REST API, который позволит получать до 50 результатов проверки из базы данных.

Шаг 1. Проверить наличие сервисного аккаунта

Для работы нам понадобится сервисный аккаунт с именем service-account-for-cf и ролями editor, serverless.mdbProxies.user, который мы создали ранее.

Шаг 2. Yandex API Gateway

Создание спецификации
В рабочем каталоге создадим спецификацию hello-world.yaml:
openapi: "3.0.0"
info:
  version: 1.0.0
  title: Test API
paths:
  /hello:
    get:
      summary: Say hello
      operationId: hello
      parameters:
        - name: user
          in: query
          description: User name to appear in greetings
          required: false
          schema:
            type: string
            default: 'world'
      responses:
        '200':
          description: Greeting
          content:
            'text/plain':
              schema:
                type: "string"
      x-yc-apigateway-integration:
        type: dummy
        http_code: 200
        http_headers:
          'Content-Type': "text/plain"
        content:
          'text/plain': "Hello, {user}!\n"
Мы можем создать API-шлюз с помощью консоли управления, но сейчас воспользуемся CLI.
Инициализация спецификации
Чтобы развернуть API-шлюз, используем спецификацию hello-world.yaml:
yc serverless api-gateway create \
  --name hello-world \
  --spec=hello-world.yaml \
  --description "hello world"
В результате успешного создания API-шлюза получим значение параметра domain:
yc serverless api-gateway list

yc serverless api-gateway get --name hello-world
Скопируем служебный домен, чтобы проверить работоспособность API-шлюза. Вставим его в адресную строку браузера и допишем в конец /hello. Должно получиться следующее:
https://<идентификатор API Gateway>.apigw.yandexcloud.net/hello
Теперь протестируем запрос с параметрами. Добавьте к предыдущему запросу ?user=my_user. Должно получиться следующее:
https://<идентификатор API Gateway>.apigw.yandexcloud.net/hello?user=my_user
В первом случае в окне браузера вы увидите «Hello, world!», во втором «Hello, my_user!».

Шаг 3. Создание функции

Работа с библиотеками и переменными
До этого момента мы использовали рантайм python37, который не требовал явного указания библиотек, но начиная с версии python39, нужно указывать библиотеки явно. Для работы с requirements.txt можно воспользоваться удобной Python-библиотекой pipreqs: чтобы сгенерировать requirements.txt с помощью pipreqs, достаточно указать рабочий каталог.
 
👉 Чтобы сформировать файл requirements.txt, команда pipreqs анализирует все Python-скрипты в текущей папке и вычисляет нужные зависимости. Поэтому создавайте для выполнения практических работ этого курса отдельные папки.
 
В большинстве интерпретаторов Linux для указания текущего каталога предусмотрена переменная $PWD. Если файл requirements.txt уже существует, актуализируйте его с помощью флага --force, например:
pip install pipreqs
pipreqs $PWD --print
pipreqs $PWD --force
Чтобы создать функцию, проверим доступность переменных для инициации подключения CONNECTION_ID, DB_USER, DB_HOST, которые мы создали в предыдущей работе с помощью следующих команд:
echo "export CONNECTION_ID=<CONNECTION_ID>" >> ~/.bashrc && . ~/.bashrc
echo "export DB_USER=<DB_USER>" >> ~/.bashrc && . ~/.bashrc
echo "export DB_HOST=<DB_HOST>" >> ~/.bashrc && . ~/.bashrc
Создание функции
Создадим функцию function-for-user-requests.py:
import json
import logging
import requests
import os
 
#Эти библиотеки нужны для работы с PostgreSQL
import psycopg2
import psycopg2.errors
import psycopg2.extras
 
CONNECTION_ID = os.getenv("CONNECTION_ID")
DB_USER = os.getenv("DB_USER")
DB_HOST = os.getenv("DB_HOST")
 
# Настраиваем функцию для записи информации в журнал функции
# Получаем стандартный логер языка Python
logger = logging.getLogger()
logger.setLevel(logging.INFO)
# Вычитываем переменную VERBOSE_LOG, которую мы указываем в переменных окружения
verboseLogging = eval(os.environ['VERBOSE_LOG'])  ## Convert to bool
 
#Функция log, которая запишет текст в журнал выполнения функции, если в переменной окружения VERBOSE_LOG будет значение True
def log(logString):
    if verboseLogging:
        logger.info(logString)
 
#Запись в базу данных
def save(result, time, context):
    connection = psycopg2.connect(
        database=CONNECTION_ID, # Идентификатор подключения
        user=DB_USER, # Пользователь БД
        password=context.token["access_token"],
        host=DB_HOST, # Точка входа
        port=6432,
        sslmode="require")
 
    cursor = connection.cursor()   
    postgres_insert_query = """INSERT INTO measurements (result, time) VALUES (%s,%s)"""
    record_to_insert = (result, time)
    cursor.execute(postgres_insert_query, record_to_insert)
    connection.commit()
 
#Формируем запрос
def generateQuery():
    select = f"SELECT * FROM measurements LIMIT 50"
    result = select
    return result
 
#Получаем подключение
def getConnString(context):
    """
    Extract env variables to connect to DB and return a db string
    Raise an error if the env variables are not set
    :return: string
    """
    connection = psycopg2.connect(
        database=CONNECTION_ID, # Идентификатор подключения
        user=DB_USER, # Пользователь БД
        password=context.token["access_token"],
        host=DB_HOST, # Точка входа
        port=6432,
        sslmode="require")   
    return connection
 
def handler(event, context):
    try:
        secret = event['queryStringParameters']['secret']
        if secret != 'cecfb23c-bc86-4ca2-b611-e79bc77e5c31':
            raise Exception()
    except Exception as error:
        logger.error(error)
        statusCode = 401
        return {
            'statusCode': statusCode
        }
 
    sql = generateQuery()
    log(f'Exec: {sql}')
 
    connection = getConnString(context)
    log(f'Connecting: {connection}')
    cursor = connection.cursor()
    try:
        cursor.execute(sql)
        statusCode = 200
        return {
            'statusCode': statusCode,
            'body': json.dumps(cursor.fetchall()),
        }
    except psycopg2.errors.UndefinedTable as error:
        connection.rollback()
        logger.error(error)
        statusCode = 500
    except Exception as error:
        logger.error(error)
        statusCode = 500
    cursor.close()
    connection.close()
 
    return {
        'statusCode': statusCode,
        'body': json.dumps({
            'event': event,
        }),
    }
Обратите внимание, в коде функции мы заложили параметр secret и его значение cecfb23c-bc86-4ca2-b611-e79bc77e5c31, при котором функция будет выполняться. Таким образом мы обеспечиваем дополнительную защиту при доступе к БД.
При создании функции сразу зададим все необходимые переменные и сервисный аккаунт:
yc serverless function create \
  --name function-for-user-requests \
  --description "function for response to user"
 
yc serverless function version create \
  --function-name=function-for-user-requests \
  --memory=256m \
  --execution-timeout=5s \
  --runtime=python37 \
  --entrypoint=function-for-user-requests.handler \
  --service-account-id $SERVICE_ACCOUNT_ID \
  --environment VERBOSE_LOG=True \
  --environment CONNECTION_ID=$CONNECTION_ID \
  --environment DB_USER=$DB_USER \
  --environment DB_HOST=$DB_HOST \
  --source-path function-for-user-requests.py

Шаг 4. Обновление спецификации API Gateway

Наша функция готова, но по умолчанию она не является публичной. Предоставим доступ к этой функции с помощью API-шлюза — обновим ранее созданную спецификацию hello-world.yaml. Не забудьте вставить в файл идентификаторы вашей функции и вашего сервисного аккаунта:
openapi: "3.0.0"
info:
  version: 1.0.0
  title: Updated API
paths:
  /results:
    get:
      x-yc-apigateway-integration:
        type: cloud-functions
        function_id: <идентификатор функции>
        service_account_id: <идентификатор сервисного аккаунта>
      operationId: function-for-user-requests
Вызовем перезагрузку нашей спецификации:
yc serverless api-gateway update \
  --name hello-world \
  --spec=hello-world.yaml
Для тестирования вызовем функцию в браузере сначала без параметра secret, а затем — с ним:
https://<идентификатор API Gateway>.apigw.yandexcloud.net/results
https://<идентификатор API Gateway>.apigw.yandexcloud.net/results?secret=cecfb23c-bc86-4ca2-b611-e79bc77e5c31
В ответе увидим результаты тестирования сервиса yandex.ru из базы данных.
Иногда приходится тестировать функцию в процессе разработки: для этого в консоли управления на странице функции перейдите на вкладку Тестирование, в поле Шаблон данных выберите HTTPS-вызов. Нажмите кнопку Запустить тест, и вы увидите код ошибки.
image
Код функции проверяет параметр secret для авторизации, то есть при вызове вы должны передать секретную последовательность, чтобы функция выдала результат. Добавим secret в параметры запроса в поле Входные данные:
    "queryStringParameters": {
        "a": "2",
        "b": "1",
        "secret": "cecfb23c-bc86-4ca2-b611-e79bc77e5c31"
    }, 
Запустим тест ещё раз. В ответе отобразятся данные из базы, как и с запросами через браузер.
image
Проверьте себя
Что выдаёт наше тестовое API при вызове метода /hello без параметров?
 
Правильный ответ:
  • Hello, world!
Какой код ошибки выдаёт функция, если не указан секрет?
 
Правильный ответ:
  • 401
Среди способов обработки запросов API-шлюзом есть следующие:
 
Правильный ответ:
  • Статический ответ
  • Вызов Cloud Function
  • Обращение в Object Storage
  • Перенаправление запроса на другой URL
Для работы с API Gateway можно использовать:
 
Правильный ответ:
  • Консоль управления
  • Yandex Cloud REST API
Спецификацию шлюза можно написать на основе спецификации:
 
Правильный ответ:
  • OpenAPI 3.0 

 

Категория: Cloud Services Engineer
Просмотров: 760

AG. Расширения OpenAPI

Расширения OpenAPI

Кратко:

  • Расширения OpenAPI включают статические ответы, вызов облачных функций, обращение по HTTP и интеграцию с Object Storage.
  • Статический ответ возвращает фиксированное содержимое без участия стороннего сервиса.
  • Вызов облачной функции вызывает указанную облачную функцию, которая получает информацию об HTTP-запросе и значения параметров.
  • Обращение по HTTP перенаправляет запрос в указанный URL.
  • Интеграция с Object Storage передает управление обработки запроса в Object Storage для раздачи статических файлов.
  • Жадные параметры позволяют не перечислять каждый файл по отдельности, а использовать знак плюс после имени параметра.
  • Обобщенный HTTP-метод позволяет все вызовы по одному URL направлять в соответствии с одной и той же интеграцией.
  • Использование сервисного аккаунта необходимо для взаимодействия с сервисами в Yandex Cloud.

Расширения OpenAPI

На прошлом уроке мы разобрались с базовой структурой спецификаций OpenAPI в сервисе API Gateway. Теперь давайте посмотрим на структуру её расширений.

Статический ответ

Расширение x-yc-apigateway-integration:dummy возвращает фиксированное содержимое с указанным кодом ответа и необходимыми заголовками без участия стороннего сервиса.
Структура этого расширения выглядит следующим образом:
x-yc-apigateway-integration:
  type: dummy
  http_code: <HTTP-код ответа>
  http_headers:
    <Список заголовков ответа>
  content:
    <Содержимое тела ответа>
Вот пример скрипта, который возвращает ответ в формате JSON с кодом 302:
x-yc-apigateway-integration:
  type: dummy
  http_code: 302
  http_headers:
    Location: "/some/location"
  content:
    "application/json": "{ \"message\": \"You've been redirected.\" }"
Вы можете использовать широкий спектр параметров и механик спецификации OpenAPI и делать сложные конструкции для статических ответов. Например, следующий скрипт меняет ответ в зависимости от параметров запроса:
openapi: "3.0.0"
info:
  version: 1.0.0
  title: Test API
paths:
  /hello:
    get:
      summary: Say hello
      operationId: hello
      parameters:
        - name: user
          in: query
          description: User name to appear in greetings
          required: false
          schema:
            type: string
            default: 'world'
      responses:
        '200':
          description: Greeting
          content:
            'text/plain':
               schema:
                 type: "string"
      x-yc-apigateway-integration:
        type: dummy
        http_code: 200
        http_headers:
          'Content-Type': "text/plain"
        content:
          'text/plain': "Hello, {user}!\n"
Подробнее о том, как использовать расширение, рассказывается в документации.

Вызов облачной функции

Расширение x-yc-apigateway-integration:cloud_functions вызывает указанную облачную функцию. В качестве входных данных функция получает информацию об HTTP-запросе и значения параметров, указанных в спецификации. На выходе клиенту возвращается результат выполнения функции.
Информация о запросе передается в том же формате, что и в текущей версии HTTP-интеграции при вызове функции с указанием параметра строки запроса integration=raw, который по большей части совместим с форматом AWS API Gateway. Значения параметров, указанных в спецификации, передаются в поле params параметра data.
Вот общая структура расширения:
x-yc-apigateway-integration:
  type: cloud-functions
  function_id: <идентификатор функции>
  tag: <Тег функции>
  service_account: <идентификатор сервисного аккаунта>
Давайте посмотрим на параметры:
  • Среди них обязательным является только function_id. , который ссылается на идентификатор облачной функции.
  • Параметр tag указывает версию функции, которую вы хотите вызвать. Он может быть опущен, и тогда будет вызвана самая последняя версия функции с тегом $latest.
  • Параметр service_account указывает на сервисный аккаунт, от имени которого будет вызвана функция. Он также может быть опущен, и тогда будет использовано значение, которое вы указали для всей спецификации в параметре верхнего уровня. Если же вы не указали параметр верхнего уровня, функция будет вызываться без авторизации.
Вот пример скрипта для этого расширения:
x-yc-apigateway-integration:
  type: cloud-functions
  function_id: b095c95icnvbuf4v755l
  tag: stable
  service_account: ajehfe41hhliq4n93q1g
Подробнее о том, как использовать расширение, читайте в документации.

Обращение по HTTP

Расширение x-yc-apigateway-integration:http перенаправляет запрос в указанный URL. Вот его структура:
x-yc-apigateway-integration:
  type: http
  url: <URL для вызова>
  method: <Метод вызова>
  headers:
     <Массив заголовков вызова>
  timeouts:
     <Таймаут вызова>
Обязательными параметрами здесь являются url и headers. Если method не указан, то система будет использовать метод запроса к Yandex API Gateway. При отсутствии timeouts будут использованы значения по умолчанию.
Пример скрипта для данного расширения:
x-yc-apigateway-integration:
  type: http
  url: https://example.com/backend1
  method: POST
  headers:
    Authorization: Basic ZjTqBB3f$IF9gdYAGlMrs2fuINjHsz
  timeouts:
    connect: 0.5
    read: 5
Подробнее о том, как использовать расширение, читайте в документации.

Интеграция с Object Storage

Расширение x-yc-apigateway-integration:object_storage передает управление обработки запроса в Object Storage с целью раздачи статических файлов. Оно позволяет управлять ключом для доступа к объекту и реализует возможность раздавать статические данные напрямую из Object Storage, используя перенаправление на подписанный URL.
Структура расширения такова:
x-yc-apigateway-integration:
        type: object-storage
        bucket: <Имя бакета>
        object: <Имя объекта>
        presigned_redirect: <Генерация пре-подписанного url>
        service_account: <идентификатор сервисного аккаунта, от имени которого идет обращение к Yandex Object Storage>
Параметр service_account является единственным необязательным. Он работает так же, как и в функциях. Если он отсутствует, то будет использовано значение для всего скрипта в параметре верхнего уровня. Если параметр верхнего уровня не указан, то обращение будет выполнено без авторизации. При этом бакет должен быть публичным.
Если значение параметра presigned_redirect задано как true, то для запроса будет сгенерирован специальный тип URL, который содержит все данные для авторизации. Любой клиент сможет скачать этот файл вне зависимости от наличия у него данных для авторизации.
Вот пример скрипта для этого расширения:
/static/{file}:
    get:
      summary: Serve static file from Yandex Cloud Object Storage
      parameters:
        - name: file
          in: path
          required: true
          schema:
            type: string
      x-yc-apigateway-integration:
        type: object-storage
        bucket: my-example-bucket
        object: 'my-object'
        presigned_redirect: true
        service_account: ajehfe41hhliq4n93q1g
Подробнее о том, как использовать расширение, читайте в документации.

Жадные параметры

Предположим, что все JS и CSS файлы вашего сайта должны быть доступны по URL с одинаковым префиксом /static/js/ и /static/CSS/соответственно. Чтобы не перечислять в спецификации каждый файл по отдельности и не писать для него дублирующиеся интеграции, вы может использовать так называемые жадные параметры.
Чтобы описать все файлы, доступные по URL с префиксом /static на любом уровне вложенности, добавьте знак плюс после имени параметра. Вот пример спецификации:
/static/{file+}:
    get:
      summary: Serve static file from Yandex Cloud Object Storage
      parameters:
        - name: file
          in: path
          required: true
          schema:
            type: string
      x-yc-apigateway-integration:
        type: object_storage
        bucket: my-example-bucket
        object: '{file}'
        error_object: error.html

Обобщенный HTTP-метод

Если вам необходимо все ваши вызовы по одному URL для всех HTTP-методов  направить в соответствии с одной и той же интеграцией, например в одну функцию, вы можете использовать расширение x-yc-apigateway-any-method. Оно позволяет избежать дублирования одинаковых интеграций в спецификации для каждого HTTP-метода, делает спецификацию короче и понятнее.
Вот пример спецификации, где применяется это расширение:
/example/{ID}:
    x-yc-apigateway-any-method:
      summary: Operating with examples
      operationId: example
      tags:
        - example
      parameters:
        - name: ID
          in: path
          description: Return ID
          required: true
          schema:
            type: string
      x-yc-apigateway-integration:
        type: cloud_functions
        function_id: b095c95icnvbuf4v755l
        tag: "$latest"
        service_account_id: ajehfe41hhliq4n93q1g

Использование сервисного аккаунта

Всё взаимодействие с сервисами в Yandex Cloud должно происходить от имени какого-либо аккаунта. В случае с Yandex API Gateway сервисный аккаунт используется для работы с функциями и Yandex Object Storage. Его можно указать как для конкретного расширения, так и для всех расширений разом. Для этого используется параметр верхнего уровня:
x-yc-apigateway:
  service_account: <идентификатор сервисного аккаунта>
Он используется следующим образом:
openapi: 3.0.0
info:
  title: Test API
  version: 1.0.0
x-yc-apigateway:
  service_account: <идентификатор сервисного аккаунта>
Теперь вы знакомы с возможными вариантами настройки сервиса. На следующем занятии закрепим пройденный материал на практике и создадим HTTP API с помощью Cloud Functions и API Gateway.
 
Проверьте себя
С какого параметра должна начинаться спецификация сервиса?
 
Правильный ответ:
  • openapi
Зачем нужно указывать сервисный аккаунт в параметрах скрипта?
 
Правильный ответ:
  • Чтобы обращаться к функциям или Object Storage с авторизацией
Что должен сделать сервис при том или ином типе пути?
 
Правильный ответ:
  • dummy - Выдать статический ответ
  • cloud-functions - Вызвать функцию сервиса Yandex Cloud Functions
  • http - Отправить http-запрос
  • object-storage - Обратиться к сервису Yandex Object Storage

 

Категория: Cloud Services Engineer
Просмотров: 1224

AG. Как настроить Yandex API Gateway

Как настроить Yandex API Gateway

Кратко:

  • Настройка Yandex API Gateway требует написания спецификации и создания экземпляра API-шлюза.
  • Спецификация должна соответствовать требованиям OpenAPI и учитывать специфику сервиса.
  • Работа с сервисом возможна через консоль управления или Yandex Cloud REST API.
  • Базовая спецификация включает информацию о названии и версии API, а также пути и методе вызова.
  • Расширения x-yc-apigateway-integration позволяют интегрировать API-шлюз с другими сервисами.
  • В спецификации можно указать несколько путей и методов для каждого пути.
  • Сервис автоматически добавляет параметр servers для формирования адреса служебного домена.
  • Ведение журнала и мониторинг позволяют проверять правильность настройки и работу сервиса.

Как настроить Yandex API Gateway

На прошлом уроке вы узнали, что такое Yandex API Gateway и как он работает, а сейчас научитесь настраивать этот сервис.
API Gateway использует спецификацию OpenAPI 3.0 для конфигурации вызовов и ответов. Чтобы настроить сервис, нужно написать спецификацию и создать экземпляр API-шлюза. Эта спецификация должна соответствовать требованиям OpenAPI и описанию расширений, а также учитывать специфику сервиса. Все детали взаимодействия с сервисом можно уточнить в документации, а мы сосредоточимся только на самых важных аспектах.
С сервисом можно работать через консоль управления или с помощью Yandex Cloud REST API. Первый способ проще, но Yandex Cloud REST API имеет чуть больше функций и позволяет настраивать сервис из стороннего программного обеспечения. Мы будем использовать консоль управления.
Чтобы создать новый API-шлюз, перейдите на главную страницу каталога, справа вверху нажмите кнопку Создать ресурс и в раскрывшемся списке выберите API-шлюз.
На открывшейся странице вы можете ввести имя и описание шлюза, а затем вставить в поле Спецификация текст спецификации, который указывает сервису, что нужно сделать в том или ином запросе.
image
Детально изучить спецификацию OpenAPI 3.0 вы можете в репозитории проекта на GitHub. Здесь же мы рассмотрим минимально необходимый набор параметров и тегов для работы с API Gateway на примере кода спецификации, который формируется для нового API-шлюза по умолчанию.
Базовая спецификация выглядит следующим образом:
openapi: 3.0.0
info:
  title: <Название API>
  version: <Версия API>
paths:
  <Путь>:
    <Метод>:
      x-yc-apigateway-integration:
        type: <Тип расширения>
Где:
  • Путь — путь строки вызова после домена.
  • Метод — метод вызова (например GET).
  • Тип расширения — один из четырех типов расширений, который указывает на действия при вызове по данному пути:
    • dummy — статический ответ.
    • cloud-functions — вызов функции сервиса Yandex Cloud Functions.
    • http — отправка HTTP-запроса.
    • object-storage — обращение к сервису Yandex Object Storage.
При этом расширение x-yc-apigateway-integration является точкой входа для интеграции API-шлюза с другими сервисами.
Статический ответ может выглядеть так:
openapi: 3.0.0
info:
  title: Test API
  version: 1.0.0
paths:
  /hello:
    get:
      x-yc-apigateway-integration:
        type: dummy
        http_code: 200
        http_headers:
          Content-Type: text/plain
        content:
          text/plain: |
            Hello, World!
В примере выше при вызове метода GET для служебного домена API-шлюз сначала подключает общее расширение x-yc-apigateway-integration, а затем расширение dummy, которое в ответ на обращение выдает статический ответ с заранее определённой текстовой строкой Hello, World!.
У расширения x-yc-apigateway-integration есть дополнительные параметры (http_code, http_headers и т. д.). Их наличие зависит от типа расширения.
В примере выше всего один путь (hello), но вы можете создавать сколько угодно путей. Шаблон спецификации с двумя путями будет выглядеть так:
openapi: 3.0.0
info:
  title: <Название API>
  version: <Версия API>
paths:
  <Путь 1>:
    <Метод>:
      x-yc-apigateway-integration:
        type: <Тип расширения>
  <Путь 2>:
    <Метод>:
      x-yc-apigateway-integration:
        type: <Тип расширения>
Адрес служебного домена в примере выше формируется после того, как вы вставили текст спецификации в одноимённое поле и сохранили изменения. При этом сервис автоматически добавляет в спецификацию параметр servers по следующему шаблону:
servers:
- url: https://<идентификатор вашего APIGateway>.apigw.yandexcloud.net
 
image
Значением URI будет домен, который нужно использовать при обращении к вашему API.
Например, если вы используете простой тестовый пример спецификации, добавляемый по умолчанию, то для проверки ответа можете использовать HTTP-клиент cURL или просто открыть этот адрес в браузере.
В спецификации вы также можете указать и свой домен, но на него нужно заранее подтвердить права в Certificate Manager. Эта функция находится на стадии Preview, доступ к ней необходимо запросить в службе техподдержки. Подробно об использовании собственных доменов с API-шлюзами можно прочитать в документации.

Журналы и мониторинг

Чтобы вы могли проверять правильность настройки и лучше понять работу сервиса, разработчики добавили две функции: ведение журнала и мониторинг.
На странице Логи вы можете увидеть информацию о запросах к путям, которые вы указали в спецификации.
На странице Мониторинг размещён график с количеством обращений к сервису и информация об ошибках.
image
На следующем занятии вы познакомитесь с расширениями OpenAPI, которые позволяют работать с другими сервисами Yandex Cloud.
 
Проверьте себя
Что нужно сделать, чтобы настроить сервис?
 
Правильный ответ:
  • Написать спецификацию
  • Создать экземпляр API-шлюза
Ниже — пример статического ответа. Какие элементы из обязательных в нём пропущены или в них допущена ошибка?
openapi: 3.0.0
info:
  title: Test API
  version: 1.0.0
paths:
  /enter:
    get:
      x-yc-apigateway-integration:
        http_code: 200
        http_headers:
          Content-Type: text/plain
        content:
          text/plain: |
            Enter the world!
    operationId: enter
Правильный ответ:
  • operationId:

 

Категория: Cloud Services Engineer
Просмотров: 2041

AG. Что такое API Gateway

Что такое API Gateway

Кратко:

  • API Gateway - это решение для интеграции микросервисной архитектуры и разрозненных API.
  • Yandex API Gateway - часть serverless-экосистемы Yandex Cloud, предоставляющая функциональность прокси-сервера и масштабируемость.
  • Сервис позволяет описывать API в стандартном виде с помощью спецификации OpenAPI и применять интеграционные решения на основе расширений OpenAPI.
  • API Gateway работает по модели PaaS и гарантирует доступность вашего API в соответствии с SLA.
  • Сервис принимает запросы по HTTPS и использует механизм сервисных аккаунтов для подключения к другим сервисам Yandex Cloud.
  • API-шлюз может обрабатывать запросы пятью разными способами.
  • Тарификация для этого сервиса - 120 рублей за 1 млн запросов в месяц, первые 100 000 запросов в месяц не тарифицируются.

Что такое API Gateway

Представим, что вы разрабатываете интернет-магазин с микросервисной архитектурой. Клиент открывает сайт или приложение вашего магазина и переходит на страницу товара — делает один запрос. Чтобы сформировать ту же карточку товара с набором корректных данных, системе нужно сделать несколько запросов, например:
  • Получить из базы данных название и подробные характеристики товара.
  • Получить из базы данных номинальную стоимость товара.
  • Выяснить, нет ли у клиента персональной скидки на товары этой категории, а затем пересчитать конечную стоимость и показать её в карточке рядом с номинальной.
  • Выяснить, есть ли этот товар на складе или в офлайн-магазинах и в каком количестве.
  • Рассчитать длительность доставки в город, который указал клиент.
Каждый из этих запросов выполняет отдельный микросервис со своим API. Если же вы хотите после оформления заказа и получения оплаты передавать клиенту трекинг почтового отправления, то вам придётся передать всем логистическим компаниям — партнёрам единый API для работы с вашей информационной системой.
Такое решение можно построить с нуля на базе веб-сервера NGINX или с помощью специализированных решений, которые, как правило, ориентированы на определенные стеки технологий и среды выполнения. В дальнейшем вам придется самостоятельно администрировать всю инфраструктуру: настраивать маршрутизатор и балансировку запросов по виртуальным машинам, обеспечивать горизонтальное масштабирование при росте посещаемости и т. д.
Вместо этого вы можете воспользоваться сервисом Yandex API Gateway, который работает по модели PaaS. Сервис предоставит:
  • функциональность прокси-сервера, масштабируемость и отказоустойчивость инфраструктуры;
  • возможность описывать API в стандартном виде с помощью спецификации OpenAPI;
  • возможность применять интеграционные решения на основе расширений OpenAPI.
Давайте разберёмся с базовыми концепциями сервиса.

Знакомство с Yandex API Gateway

В основе этого сервиса лежит классический паттерн программирования: внутреннее представление отделено от способа взаимодействовать с ним через прокси. Мы не афишируем нашу реализацию и отдаём наружу некий контракт.
Yandex API Gateway — важная часть serverless-экосистемы в Yandex Cloud. Он позволяет интегрировать компоненты микросервисного приложения и разрозненные API.
По своей сути Yandex API Gateway является управляемым RESTful API. Он находится между внешним пользователем и сервисами, которые обрабатывают запросы этого пользователя. Его основное преимущество — возможность свести в единую точку взаимодействие пользователей с ресурсами, которые расположены как в Yandex Cloud, так и на других серверах. Допустим, у вас есть три сущности:
  1. Файлы в Object Storage.
  2. Сайт на базе WordPress, развёрнутый на виртуальной машине.
  3. API, который реализован с помощью Cloud Functions.
API Gateway позволит организовать взаимодействие со всеми тремя ресурсами через обращение к одному домену с единым API. Без него вам бы пришлось самостоятельно разворачивать шлюз или обратный прокси-сервер и администрировать его.
Поскольку API Gateway работает по модели PaaS, он гарантирует доступность вашего API в соответствии с SLA. А ещё HTTP/HTTPS-запросы ваших пользователей будут выполнены вне зависимости от их количества.

Логика работы Yandex API Gateway

Сервис принимает запросы по HTTPS через служебный поддомен apigw.yandexcloud.net или через подключение к вашему домену через Certificate Manager, разбирает эти запросы и определяет их путь и параметры. Кроме того, он использует механизм сервисных аккаунтов для подключения к другим сервисам Yandex Cloud.
Созданный API-шлюз может обрабатывать запросы пятью разными способами:
  1. Автоматически формировать статический ответ на запрос. Ответ будет разным в зависимости от параметров запроса.
  2. Вызывать функцию, созданную в сервисе Yandex Cloud Functions, которая передаёт параметры запроса и возвращает результаты вызова в ответе.
  3. Обращаться к сервису Yandex Object Storage, чтобы раздавать статические файлы.
  4. Отправлять запрос на другой URL и формировать ответ как есть.
  5. Вызывать ноду DataSphere, развёрнутую в виде отдельного микросервиса.
Общая схема работы сервиса выглядит следующим образом:
image
Запрос пользователя попадает в API-шлюз, который в соответствии с правилами в спецификации перенаправляет его по другим путям, таким как выполнение облачной функции, получение файла из Object Storage и т. д.
Например, на запрос https://<домен>/GetFileList может быть дан статический ответ со списком файлов, а на запрос https://<домен>/static/<file> — возвращён файл из Yandex Object Storage.

Тарификация

Модель тарификации для этого сервиса — 120 рублей за 1 млн запросов в месяц.* Работает free tier: первые 100 000 запросов в месяц не тарифицируются.
Давайте посчитаем стоимость использования API-шлюза с количеством запросов из примера выше:
120×((2000000–100000)/1000000)=228120×((2000000–100000)/1000000)=228 ₽ в месяц
Для сравнения создадим виртуальную машину (ВМ) с самыми скромными возможностями, чтобы запустить на ней NGINX для терминирования TLS и проксирования запросов. Пусть это будет Ubuntu 20.04 c HDD объёмом 13 ГБ, Intel Ice Lake, 2 vCPU с гарантированной долей 20% и RAM 1 ГБ. Ежемесячная стоимость ВМ с такой конфигурацией составит 1 045,96 ₽.
* Актуальные тарифы могут отличаться от приведенных в примерах выше.
Обратите внимание: функционально сравнение этих двух решений не будет корректным. Отказоустойчивость API-шлюза, работающего на базе NGINX в ВМ, будет предельно низкой, и у вас уйдёт заметно больше времени на настройку маршрутов.
Более подробную информацию вы найдёте в документации.
На следующем уроке мы разберём основы конфигурации Yandex API Gateway.
 
Проверьте себя
Что из себя представляет сервис Yandex API Gateway?
 
Правильный ответ:
  • Прокси-сервер
Что из нижеперечисленного НЕ УМЕЕТ делать Yandex API Gateway?
 
Правильный ответ:
  • Отправлять почтовые сообщения
Какими способами Yandex API Gateway может обработать запрос?
 
Правильный ответ:
  • Обратиться к Yandex Object Storage
  • Вызвать функцию из Yandex Cloud Functions
  • Автоматически сформулировать статический ответ
  • Отправить запрос на другой URL

 

Категория: Cloud Services Engineer
Просмотров: 1068

CF. ПР. Проверка доступности

ПР. Проверка доступности

Кратко:

  • Создание функции для проверки доступности сайта ya.ru и измерения времени ответа.
  • Подключение к управляемой базе данных PostgreSQL через функцию Cloud Functions.
  • Создание таблицы для хранения результатов проверки доступности сайта.
  • Подключение к базе данных PostgreSQL через подключение к функции Cloud Functions.
  • Создание триггера-таймера для проверки доступности сайта с помощью cron-выражения.
  • Удаление триггера-таймера после завершения практической работы.
  • Использование созданного кластера PostgreSQL для последующих практических работ.

Практическая работа. Проверка доступности

На этом практическом занятии вы создадите функцию для проверки доступности сайта ya.ru, которая будет измерять время ответа. Результаты работы функции будут передаваться в базу данных сервиса Yandex Managed Service for PostgreSQL с использованием подключения к управляемой БД из функции. Также вы запустите триггер-таймер, который будет регулярно производить опрос сайта ya.ru.

Шаг 1. Дополнительная роль для сервисного аккаунта

В предыдущих практических работах вы создали сервисный аккаунт с именем service-account-for-cf, назначили ему роли editor и  storage.editor и создали ключ доступа. Чтобы подключаться к управляемым БД из функции, нужно добавить сервисному аккаунту роль serverless.mdbProxies.user.
Для этого выполните следующую команду:
yc resource-manager folder add-access-binding $FOLDER_ID \
  --role serverless.mdbProxies.user \
  --subject serviceAccount:$SERVICE_ACCOUNT_ID

Шаг 2. Создание базы данных

Создание кластера PostgreSQL
Конечно, кластер PostgreSQL можно создать с помощью консоли управления, но в этой практической работе мы используем CLI. Прежде всего, давайте определим подсеть, в которой будет расположен кластер. Разместим кластер в зоне ru-central1-c и с помощью следующей команды узнаем идентификатор(ID) соответствующей подсети:
yc vpc subnet list
Создадим кластер версии PostgreSQL 15 с именем my-pg-database. Установим тип хоста burstable c3-c2-m4 — это самый дешёвый и простой вариант хоста. Из-за невысокой производительности он подходит только для тестовых целей. Используем для хоста жёсткий диск (HDD) размером 10 ГБ.
Сразу создадим пользователя с именем user1 и паролем user1user1, а также базу данных db1. Для удобства администрирования откроем доступ из консоли управления. Используйте опцию websql-access — это позволит выполнять SQL-запросы прямо в консоли управления. Чтобы открыть возможность подключения к PostgreSQL из функции, необходимо подключить опцию serverless-access.
Следующая команда за несколько минут создаст кластер PostgreSQL (не забудьте подставить идентификатор вашей подсети):
yc managed-postgresql cluster create \
  --name my-pg-database \
  --description 'For Serverless' \
  --postgresql-version 15 \
  --environment production \
  --network-name default \
  --resource-preset c3-c2-m4 \
  --host zone-id=ru-central1-c,subnet-id=<идентификатор_подсети> \
  --disk-type network-hdd \
  --disk-size 10 \
  --user name=user1,password=user1user1 \
  --database name=db1,owner=user1 \
  --websql-access \
  --serverless-access
После успешного создания кластера проверьте результат:
yc managed-postgresql cluster list
yc managed-postgresql cluster get <имя или идентификатор кластера>
Создание таблицы для хранения данных
При создании кластера мы использовали опцию websql-access, что открывает нам возможности по исполнению SQL-команд в консоли управления. Воспользуемся этим и сделаем таблицу в созданной нами базе данных. В эту таблицу мы будем складывать результаты выполнения функции. В консоли управления перейдите в каталог, в котором создан кластер PostgreSQL. Откройте сервис Managed Service for PostgreSQL и перейдите в кластер my-pg-database.
В боковом меню перейдите на вкладку SQL. Для базы данных db1введите имя user1 и пароль user1user1, нажмите кнопку Подключиться.
image
В открывшемся окне введите SQL-запрос и исполните его:
CREATE TABLE measurements (
    result integer,
    time float
);
image
Успешное выполнение команды создаст таблицу, куда мы будем складывать результаты.

Шаг 3. Подключение к управляемой БД из функции

Создание подключения
В консоли управления перейдите в каталог, в котором хотите создать подключение. Откройте сервис Cloud Functions. В боковом меню перейдите на вкладку Подключения к БД. Нажмите кнопку Создать подключение.
image
  1. Введите имя, описание подключения и в выпадающем списке выберите тип подключения — PostgreSQL.
  2. Укажите кластер — my-pg-database.
  3. Укажите базу данных — db1.
  4. Введите данные пользователя БД: имя user1 и пароль user1user1.
  5. Нажмите кнопку Создать.
image
Выберите созданное подключение. На вкладке Обзор скопируйте параметры Идентификатор и Точка входа. Они будут использованы в функции на следующем шаге.
image

Шаг 4. Создание функции

Перед созданием функции определите переменные для инициации подключения: CONNECTION_ID — идентификатор подключения, DB_USER — имя пользователя БД, DB_HOST — точка входа. Используйте следующие команды:
echo "export CONNECTION_ID=<CONNECTION_ID>" >> ~/.bashrc && . ~/.bashrc
echo "export DB_USER=<DB_USER>" >> ~/.bashrc && . ~/.bashrc
echo "export DB_HOST=<DB_HOST>" >> ~/.bashrc && . ~/.bashrc
Они будут использованы в функции function-for-postgresql.py. Код функции:
import datetime
import logging
import requests
import os

#Эти библиотеки нужны для работы с PostgreSQL
import psycopg2
import psycopg2.errors

CONNECTION_ID = os.getenv("CONNECTION_ID")
DB_USER = os.getenv("DB_USER")
DB_HOST = os.getenv("DB_HOST")

# Настраиваем функцию для записи информации в журнал функции
# Получаем стандартный логер языка Python
logger = logging.getLogger()
logger.setLevel(logging.INFO)
# Вычитываем переменную VERBOSE_LOG, которую мы указываем в переменных окружения 
verboseLogging = eval(os.environ['VERBOSE_LOG'])  ## Convert to bool

#Функция log, которая запишет текст в журнал выполнения функции, если в переменной окружения VERBOSE_LOG будет значение True
def log(logString):
    if verboseLogging:
        logger.info(logString)

#Запись в базу данных
def save(result, time, context):
    connection = psycopg2.connect(
        database=CONNECTION_ID, # Идентификатор подключения
        user=DB_USER, # Пользователь БД
        password=context.token["access_token"],
        host=DB_HOST, # Точка входа
        port=6432,
        sslmode="require")

    cursor = connection.cursor()    
    postgres_insert_query = """INSERT INTO measurements (result, time) VALUES (%s,%s)"""
    record_to_insert = (result, time)
    cursor.execute(postgres_insert_query, record_to_insert)
    connection.commit()

# Это обработчик. Он будет вызван первым при запуске функции
def entry(event, context):

    #Выводим в журнал значения входных параметров event и context
    log(event)
    log(context)

    # Тут мы запоминаем текущее время, отправляем запрос к ya.ru и вычисляем время выполнения запроса
    try:
        now = datetime.datetime.now()
        #здесь указано два таймаута: 1c для установки связи с сервисом и 3 секунды на получение ответа
        response = requests.get('https://ya.ru', timeout=(1.0000, 3.0000))
        timediff = datetime.datetime.now() - now
        #сохраняем результат запроса
        result = response.status_code
    #если в процессе запроса сработали таймауты, то в результат записываем соответствующие коды
    except requests.exceptions.ReadTimeout:
        result = 601
    except requests.exceptions.ConnectTimeout:
        result = 602
    except requests.exceptions.Timeout:
        result = 603
    log(f'Result: {result} Time: {timediff.total_seconds()}')    
    save(result, timediff.total_seconds(), context)

    #возвращаем результат запроса
    return {
        'statusCode': result,
        'headers': {
            'Content-Type': 'text/plain'
        },
        'isBase64Encoded': False
    }
Перейдем в директорию с кодом функции и создадим нашу функцию function-for-postgresql. При этом сразу зададим все необходимые переменные и сервисный аккаунт:
yc serverless function create \
  --name  function-for-postgresql \
  --description "function for postgresql"

yc serverless function version create \
  --function-name=function-for-postgresql \
  --memory=256m \
  --execution-timeout=5s \
  --runtime=python37 \
  --entrypoint=function-for-postgresql.entry \
  --service-account-id $SERVICE_ACCOUNT_ID \
  --environment VERBOSE_LOG=True \
  --environment CONNECTION_ID=$CONNECTION_ID \
  --environment DB_USER=$DB_USER \
  --environment DB_HOST=$DB_HOST \
  --source-path function-for-postgresql.py
Проверим работоспособность функции:
yc serverless function version list --function-name function-for-postgresql
yc serverless function invoke --name function-for-postgresql
Успешный вызов функции приведёт к измерению времени ответа сайта и формированию записи в базе данных.

Шаг 5. Создание триггера

Создание триггера-таймера
Проверять доступность сайта лучше в автоматическом режиме через равные промежутки времени. Для этой задачи создайте триггер-таймер. Он будет использовать cron-выражения:
yc serverless trigger create timer \
  --name trigger-for-postgresql \
  --invoke-function-name function-for-postgresql \
  --invoke-function-service-account-id $SERVICE_ACCOUNT_ID \
  --cron-expression '* * * * ? *'
Cron-выражение * * * * ? * означает вызов функции function-for-postgresql один раз в минуту. Успешное выполнение функции раз в минуту будет создавать запись в базе данных, в чём вы можете убедиться, просмотрев записи в таблице.
Убедились? Поздравляем: вы успешно создали функцию, которая через заданный промежуток времени выполняется по триггеру, чтобы проверить доступность ya.ru и записать результат проверки в базу данных.
Удаление триггера-таймера
После завершения практической работы не забудьте удалить созданный триггер trigger-for-postgresql, иначе он будет продолжать работать:
yc serverless trigger delete trigger-for-postgresql
Поздравляем, вы успешно закончили вторую тему. Пройдите короткий тест — и мы перейдём к изучению сервиса API Gateway.
Не удаляйте созданный кластер PostgreSQL, он понадобится для следующей практической работы.
 
Проверьте себя
Код Cloud Functions выполняется:
 
Правильный ответ:
  • На виртуальных машинах, но они скрыты от пользователя высокоуровневой абстракцией.
Для чего нужны триггеры:
 
Правильный ответ:
  • Чтобы не писать сложную систему создания и отправки HTTPS-запросов.
  • Чтобы автоматически вызывать функцию по тем или иным событиям.
  • Чтобы получить простую интеграцию с другими сервисами Yandex Cloud.

 

Категория: Cloud Services Engineer
Просмотров: 5789
  1. CF. ПР. Навык Алисы
  2. CF. ПР. Создание триггера от Object Storage
  3. CF. Триггеры, логирование, мониторинг
  4. CF. Как готовить функции к запуску и управлять ими

Страница 6 из 19

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
© Gantry Framework 2016 - 2026
Developed by RocketTheme exclusively
for Gantry 5.
  • Главная
  • Начало
  • Карта
Back to top