Введение
Яндекс Облако предоставляет возможность разворачивания .NET приложений разными способами, типичным из которых является docker контейнеры, развернутые на созданных вычислительных ресурсах, что подразумевают оплату за выделенные процессоры и память. Более экономный вариант предоставляют serverless сервисы Cloud Functions и Serverless Containers, где оплата идет по фактически потребленным ресурсам, масштабирование осуществляется самим облаком. Контейнеры это хороший вариант разработки, но более простым и легковесным является Cloud Functions.
Инструменты
Visual Studio предоставляет возможность создавать любые Web приложения, но разворачиваться они должны на хостах, которые открывают порты для взаимодействия с пользователями. Вариант для Cloud Functions это создать модуль, который имеет предопределенную точку входа. Метод-обработчик должен быть публичным, иметь имя FunctionHandler и один входной параметр. Но хотелось бы создавать полноценные Web Api, где под капотом midlware и вся мощь внедрения зависимостей созданное MS. Такого инструмента у Яндекс нет, но это есть у Amazon. AWS SDK для .NET дает возможность создавать и переносить существующие Web приложения на облако, и интегрируется с Visual Studio, чем мы просто и воспользуемся. Данная технология дает возможность запускать и отлаживать локально средствами Visual Studio.
Шаблоны проектов AWS
Компоненты
AWS SDK реализует IHostBuilder, но при запуске заменяет сервис IServer пустой заглушкой, потому хост при запуске не открывает порты и т.д. но цепочка обработки midleware работает. Точка входа и сигнатура вызова не совпадает с Яндекс, но это не проблема, open source дает возможность доделать проект, и вот сразу появляется наш AWS SDK с поддержкой Яндекс.
Разработка
Скачаем и локально установим nuget packet Amazon.Lambda.Yandex.0.0.1.nupkg, который мы создали, запустив команду nuget add с параметрами локального репозитория, который можно посмотреть в настройках VS.
Создадим на Visual Studio проект Web Api :
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace WebApplication
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapGet("/", () => "Welcome to running ASP.NET Core Minimal API");
endpoints.MapGet("/test", () => "Welcome to Yandex");
});
}
}
}
using Amazon.Lambda.AspNetCoreServer;
using Microsoft.AspNetCore.Hosting;
namespace WebApplication
{
public class YandexFunction : YandexGatewayProxyFunction
{
protected override void Init(IWebHostBuilder builder)
{
builder.UseStartup<Startup>();
}
}
}
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using WebApplication.Model;
namespace WebApplication.Controllers
{
[ApiController]
[Route("api/test")]
public class ApiController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public ApiController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
}
}
Развертывание
Яндекс наверно оптимизировал и урезал среду исполнения net6, потому придется делать сборку Self-contained, иначе загрузчик ругается на отсутствие библиотек ядра, потом удалим системные библиотеки.
Делаем локальное разворачивание Publish, ставим параметры:
linuх-x64
net6.0
Self-contained
Trim unused code
Удаляем System.*.dll и файлы *.so кроме System.Diagnostics.*.dll System.IO.*.dll System.Text.*.dll
Упакуем в .zip, грузим в облако.
Точка входа: WebApplication.YandexFunction
Создаем для функции отдельный Yandex API Gateway:
openapi: 3.0.0
info:
title: Sample Web API
version: 1.0.0
servers:
- url: https://....apigw.yandexcloud.net
paths:
/test:
get:
summary: Get Test
operationId: gettest10
tags:
- example
x-yc-apigateway-integration:
type: cloud_functions
function_id: ...
payload_format_version: "1.0"
tag: "$latest"
responses:
'200':
description: Ok
/api/{param+}:
x-yc-apigateway-any-method:
summary: Get Controllers
parameters:
- name: param
in: path
required: true
schema:
type: string
operationId: getcontrollers
tags:
- example
x-yc-apigateway-integration:
type: cloud_functions
function_id: ...
payload_format_version: "1.0"
tag: "$latest"
responses:
'200':
description: Ok
Наше приложение готово и доступно в интернете по адресу шлюза.
Ссылки на исходники:
nuget пакет для VisualStudio