Перейти к основному содержимому

Как поставить зависимости в Yandex Cloud Serverless Functions из Maven

· 4 мин. чтения

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"
}