Как поставить зависимости в Yandex Cloud Serverless Functions из Maven
Maven Central 26 июня 2025 года ввел ограничение на количество запросов к репозиторию. Они заблокировали 1% IP-адресов, которые по их словам, давали 83% трафика. Их мотивы понятны, но если это сломало вам деплой серверлесс-функций, написанных на Java, то есть способ обойти это ограничение. Если вы получаете во время сборки следующее сообщение:
Your IP: X.X.X.X has hit the rate limit with Maven Central. Too many requests.
Find out how to address this at https://www.sonatype.com/blog/maven-central-and-the-tragedy-of-the-commons
То это значит, что вы попали под это ограничение. Вместо того чтобы полагаться на билдер в облаке, которому нужно будет скачать зависимости, сделать это локально и принести их вместе с кодом функции.
Как это сделать
В принципе, это несложно. И в документации описано как это сделать. Но на мой вкус, это описание немного суховато, поэтому я постараюсь дать более подробные шаги.
1. Создадим простой проект
Создадим простой проект на Java с поддержкой Maven. Для этого можно использовать любой инструмент, который вам нравится. Я буду использовать IntelliJ IDEA. Создайте новый проект, выберите Maven и Java, укажите имя проекта и нажмите "Finish".
2. Добавим хендлер и зависимости
В файле src/main/java/ru/nikolaymatrosov/Handler.java
добавьте следующий код:
package ru.nikolaymatrosov;
import yandex.cloud.sdk.functions.Context;
import yandex.cloud.sdk.functions.YcFunction;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
public class Handler implements YcFunction<Integer, String> {
@Override
public String handle(Integer i, Context c) {
System.out.println("stdout: Привет, Мир!");
return String.valueOf(i);
}
}
В файле pom.xml
добавьте зависимости для Yandex Cloud SDK:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ru.nikolaymatrosov</groupId>
<artifactId>sls-local-maven</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.yandex.cloud</groupId>
<artifactId>java-sdk-serverless</artifactId>
<version>2.6.4</version>
</dependency>
</dependencies>
</project>
3. Скачаем зависимости
Теперь нам нужно скачать зависимости, чтобы не полагаться на Maven Central. Для этого откройте терминал в корне проекта и выполните команду:
mvn -f ./pom.xml dependency:copy-dependencies -DoutputDirectory=.
После выполнения этой команды в корне проекта появится java-sdk-serverless-2.6.4.jar
.
4. Деплой функции при помощи Terraform
Теперь мы можем задеплоить функцию в Yandex Cloud. Для этого создадим файл terraform.tf
в папке tf
со следующим содержимым:
terraform {
required_providers {
yandex = {
source = "yandex-cloud/yandex"
}
}
required_version = ">= 0.13"
}
provider "yandex" {
cloud_id = var.cloud_id
folder_id = var.folder_id
zone = var.zone
}
В файле variables.tf
определим переменные:
variable "cloud_id" {
type = string
}
variable "folder_id" {
type = string
}
variable "zone" {
type = string
default = "ru-central1-a"
}
В файле main.tf
создадим функцию:
data "archive_file" "function_files" {
output_path = "./function.zip"
source_dir = "../"
type = "zip"
excludes = [
"pom.xml", # исключаем pom.xml, чтобы не триггерить сборку в Yandex Cloud
"tf",
".mvn",
".git",
".idea",
".gitignore",
]
}
resource "yandex_function" "hello_function" {
name = "hello-world"
user_hash = data.archive_file.function_files.output_sha256
runtime = "java21"
entrypoint = "ru.nikolaymatrosov.Handler"
memory = "128"
execution_timeout = "10"
content {
zip_filename = data.archive_file.function_files.output_path
}
}
// IAM binding for making function public
resource "yandex_function_iam_binding" "test_function_binding" {
function_id = yandex_function.hello_function.id
role = "functions.functionInvoker"
members = ["system:allUsers"]
}
5. Инициализация и деплой
Теперь инициализируем Terraform и применим конфигурацию:
export YC_TOKEN=`yc iam create-token`
terraform init
terraform apply -var="cloud_id=b1g..." -var="folder_id=b1g..." -auto-approve
После успешного выполнения команды вы получите ID функции, который можно использовать для вызова функции.
6. Вызов функции
Теперь мы можем вызвать функцию, используя curl
:
FUNCTION_ID=$(terraform output -raw function_id)
curl "https://functions.yandexcloud.net/$FUNCTION_ID?integration=raw" \
--request POST \
--data '42'
Вы должны увидеть ответ 42
, что означает, что функция успешно обработала запрос.
7. Много зависимостей
Если у вас много зависимостей, то архив может не пролезть в ограничение 3.5Мб на прямую загрузку. В этом случае можно
дополнить main.tf
следующим образом:
resource "random_uuid" "suffix" {}
resource "yandex_storage_bucket" "code" {
bucket = "code-${random_uuid.suffix.result}"
}
resource "yandex_storage_object" "code" {
bucket = yandex_storage_bucket.code.bucket
key = "function.zip"
source = data.archive_file.function_files.output_path
}
resource "yandex_function" "hello_function" {
name = "hello-world"
user_hash = data.archive_file.function_files.output_sha256
runtime = "java21"
entrypoint = "ru.nikolaymatrosov.Handler"
memory = "128"
execution_timeout = "10"
package {
bucket_name = yandex_storage_bucket.code.bucket
object_name = yandex_storage_object.code.key
}
}
Создадим бакет в Yandex Object Storage и загрузим туда архив с функцией. После этого функция будет использовать этот архив при создании функции. Это позволяет обойти ограничение на размер архива при прямой загрузке.
В terraform.tf
добавьте провайдер random
для генерации уникального имени бакета:
terraform {
required_providers {
yandex = {
source = "yandex-cloud/yandex"
}
random = {
source = "hashicorp/random"
}
}
required_version = ">= 0.13"
}