We detected you are likely not from a Russian-speaking region. Would you like to switch to the international version of the site?

  Назад к списку статей

Разработка и деплой микросервисов на Go и Rust в Termux с поддержкой gRPC, protobuf и автоматическим масштабированием

Termux — мощная среда для разработки на Android, позволяющая запускать компиляторы, инструменты сборки и сетевые сервисы прямо на устройстве. В этой статье мы рассмотрим практический подход к разработке и деплою микросервисов на Go и Rust в Termux, с поддержкой gRPC и protobuf, а также с идеей автоматического масштабирования на уровне процесса/пула воркеров и оркестрации за пределами самого устройства.

Материал ориентирован на разработчиков, которым важно быстро прототипировать и затем переносить сервисы в более “серверный” контур.

Архитектура решения

Типичный микросервис на gRPC состоит из:

  • IDL — описание контрактов в proto (сообщения, сервисы, методы)
  • Сервер — реализация обработчиков gRPC
  • Клиент — потребитель API (другой сервис или тестовый стенд)
  • Транспорт — HTTP/2 поверх gRPC
  • Слой сборки — генерация кода из protobuf
  • Деплой — запуск и управление процессами
  • Масштабирование — увеличение числа инстансов или воркеров

В Termux мы используем локальную сеть и запуск сервисов на устройстве. Для распределённого масштабирования обычно нужен внешний оркестратор (например, Kubernetes), а на устройстве — удобный аналог: запуск нескольких экземпляров сервиса и балансировка запросов на стороне “внешнего” компонента или простого локального балансировщика.

Подготовка Termux

Убедимся, что пакетный менеджер и базовые зависимости обновлены.

pkg update && pkg upgrade -y

Далее установим базовый набор: компиляторы, утилиты, git.

pkg install -y git curl unzip tar ca-certificates clang make wget pkg-config

Для сборки Rust может потребоваться стандартная toolchain — в большинстве случаев Termux-установка справится с этим через rustup или prebuilt.

Для протоколов и генерации кода нам пригодятся protobuf-инструменты и версии генераторов.

Установка Go, Rust и protobuf toolchain

В Termux есть разные варианты установки. Приведём практичный путь: используем установку инструментов из репозиториев/официальных сборок там, где это доступно.

Go

Если Go доступен через пакетный менеджер Termux, можно начать с него.

pkg install -y golang

Проверим:

go version

Rust

Установим Rust через rustup (универсальный подход для актуальных версий).

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

После установки перезайдите в текущую сессию или выполните подгрузку:

source $HOME/.cargo/env

Проверка:

rustc --version && cargo --version

protobuf и генераторы

Для генерации кода из protobuf на Go и Rust обычно нужны:

  • protoc (компилятор .proto)
  • protoc-gen-go (генерация Go-кода)
  • protoc-gen-go-grpc (gRPC для Go)
  • protoc-gen-rust (protobuf-код для Rust) и tonic-build (генерация gRPC-обвязки)

Сначала поставим protoc, если он доступен:

pkg install -y protobuf

Проверим:

protoc --version

Теперь установим генераторы для Go:

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

Убедимся, что каталог с бинарниками Go в PATH. Часто это $HOME/go/bin:

export PATH="$PATH:$HOME/go/bin"

Проверка:

protoc-gen-go --version || true

Для Rust генерация gRPC обычно делается через tonic-build внутри сборочного скрипта, а не отдельными глобальными бинарниками (хотя protoc всё равно нужен).

Проект: общий proto-контракт

Создадим рабочую директорию и структуру:

mkdir -p grpc-termux/go-service grpc-termux/rust-service grpc-termux/proto

Определим контракт в grpc-termux/proto/echo.proto:

syntax = "proto3";

package echo;

option go_package = "echo/echopb;echopb";

service EchoService {
  rpc Echo (EchoRequest) returns (EchoReply) {}
}

message EchoRequest {
  string message = 1;
}

message EchoReply {
  string message = 1;
}

Задача протокола — простой echo, чтобы отладить связку gRPC + генерацию.

Реализация сервиса на Go

Создадим Go-модуль:

cd grpc-termux/go-service
go mod init grpc-termux/go-service || go mod init go-service

Соберём зависимости:

go get google.golang.org/grpc@latest
go get google.golang.org/protobuf@latest

Добавим генерацию protobuf в рамках проекта.

Вариант для простоты: сгенерировать в каталог ./echopb заранее.

mkdir -p echopb
protoc -I ../proto --go_out=. --go-grpc_out=. ../proto/echo.proto

Важно: параметры генерации зависят от версии protoc-gen-go и расположения опций option go_package.

Далее реализуем сервер в main.go:

package main

import (
  "context"
  "log"
  "net"
  "os"
  "google.golang.org/grpc"

  echopb "grpc-termux/go-service/echopb/echo"
)

type server struct {
  echopb.UnimplementedEchoServiceServer
}

func (s server) Echo(ctx context.Context, req echopb.EchoRequest) (echopb.EchoReply, error) {
  return &echopb.EchoReply{Message: req.Message}, nil
}

func main() {
  addr := os.Getenv("GRPC_ADDR")
  if addr == "" {
    addr = ":50051"
  }

  lis, err := net.Listen("tcp", addr)
  if err != nil {
    log.Fatalf("listen: %v", err)
  }

  grpcServer := grpc.NewServer()
  echopb.RegisterEchoServiceServer(grpcServer, &server{})

  log.Printf("Go EchoService listening on %s", addr)
  if err := grpcServer.Serve(lis); err != nil {
    log.Fatalf("serve: %v", err)
  }
}

Замечание по импортам: в зависимости от того, как именно сгенерировался пакет Go, путь может потребовать корректировки. На практике вы быстро подстроите import под фактическую структуру каталогов в echopb.

Запуск:

GRPC_ADDR=":50051" go run .

Реализация сервиса на Rust (tonic)

Создадим Rust-проект:

cd ../rust-service
cargo new --bin rust-echo

Перейдём в директорию проекта:

cd rust-echo

Добавим зависимости в Cargo.toml:

[dependencies]
tokio = { version = "1", features = ["full"] }
tonic = { version = "0.12", features = ["transport"] }
prost = "0.12"
prost-types = "0.12"

[build-dependencies]
tonic-build = "0.12"

Настроим сборку protobuf в build.rs:

use tonic_build::configure;

fn main() {
    configure()
        .build_server(true)
        .out_dir("src/echopb")
        .compile(&["../proto/echo.proto"], &["../proto"])
        .unwrap();
}

Подготовим src/main.rs:

pub mod echopb {
    include!("echopb/echo.rs");
}

use echopb::echo_service_server::{EchoService, EchoServiceServer};
use echopb::{EchoReply, EchoRequest};

use tonic::{transport::Server, Request, Response, Status};

#[derive(Default)]
pub struct MyEcho;

#[tonic::async_trait]
impl EchoService for MyEcho {
    async fn echo(&self, request: Request<EchoRequest>)
        -> Result<Response<EchoReply>, Status> {
        let msg = request.into_inner().message;
        Ok(Response::new(EchoReply { message: msg }))
    }
}

#[tokio::main]
async fn main() -> Result<<(), Box<dyn std::error::Error>>> {
    let addr = std::env::var("GRPC_ADDR").unwrap_or_else(|_| ":50052".to_string());
    let addr = addr.parse()?;

    let svc = EchoServiceServer::new(MyEcho::default());

    println!("Rust EchoService listening on {}", addr);

    Server::builder()
        .add_service(svc)
        .serve(addr)
        .await?;

    Ok(())
}

Запуск:

GRPC_ADDR="0.0.0.0:50052" cargo run

Порты разведены, чтобы параллельно протестировать оба сервиса.

Проверка работы (gRPC curl-лайк подход или клиент)

Для gRPC в “чистом виде” нет универсального curl сценария, но можно использовать:

  • тестовый gRPC клиент (например, grpcurl)
  • или небольшой клиент на Go/Rust

Если нужен быстрый тест, лучше собрать маленький клиент. В рамках статьи покажем простейший подход: отдельный Go-клиент для Go-сервиса.

Сделаем файл grpc-termux/go-service/client.go:

package main

import (
  "context"
  "log"
  "os"
  "time"

  "google.golang.org/grpc"
  echopb "grpc-termux/go-service/echopb/echo"
)

func main() {
  addr := os.Getenv("GRPC_TARGET")
  if addr == "" {
    addr = "127.0.0.1:50051"
  }

  conn, err := grpc.Dial(addr, grpc.WithInsecure(), grpc.WithBlock())
  if err != nil {
    log.Fatalf("dial: %v", err)
  }
  defer conn.Close()

  c := echopb.NewEchoServiceClient(conn)

  ctx, cancel := context.WithTimeout(context.Background(), 3time.Second)
  defer cancel()

  resp, err := c.Echo(ctx, &echopb.EchoRequest{Message: "hello from Termux"})
  if err != nil {
    log.Fatalf("echo: %v", err)
  }
  log.Printf("response: %s", resp.GetMessage())
}

Выполнить:

GRPC_TARGET="127.0.0.1:50051" go run client.go

Аналогично можно сделать Rust-клиент, чтобы проверить Rust-сервис на 50052.

Деплой на Termux: как сделать “службу”, а не разовый запуск

В Android/Termux запуск микросервисов — это процесс в пользовательской среде. Для удобного деплоя в рамках устройства используют следующие практики:

  • запуск через скрипт entrypoint с переменными окружения
  • журналирование в консоль и сохранение логов
  • запуск нескольких инстансов на разных портах
  • балансировка на уровне простого роутера/прокси

Скрипт запуска Go-сервиса, например run-go.sh:

#!/data/data/com.termux/files/usr/bin/sh
set -e

export GRPC_ADDR="${GRPC_ADDR:-0.0.0.0:50051}"
cd "$(dirname "$0")"
exec go run .

Сделайте исполняемым:

chmod +x run-go.sh
./run-go.sh

Для Rust аналогично.

gRPC и protobuf: генерация как часть CI-процесса

Чтобы деплой был воспроизводимым, генерацию protobuf лучше делать при сборке:

  • в Go — запуск protoc и генераторов перед go build
  • в Rust — build.rs (уже встроено в cargo)

Пример для Go: добавить в сборочный скрипт шаг генерации.

#!/data/data/com.termux/files/usr/bin/sh
set -e

cd "$(dirname "$0")/.." 
protoc -I ./proto --go_out=./go-service --go-grpc_out=./go-service ./proto/echo.proto
cd ./go-service
go build ./...

Так вы исключаете ситуацию, когда код протокола “подтянут” вручную и забыли о несовпадениях версий.

Автоматическое масштабирование на практике: подходы для Termux

Словосочетание “автоматическое масштабирование” обычно ассоциируется с autoscaling в кластере (например, HPA/Cluster Autoscaler). В Termux на устройстве полноценная кластерная инфраструктура ограничена, но вы можете реализовать принцип — масштабирование числа инстансов сервиса под нагрузку или под очередь запросов.

Масштабирование через пул инстансов (scale-out по порту)

Суть:

  • запускаем N инстансов одного сервиса на разных портах
  • перед ними ставим простой балансировщик/роутер
  • автоматизация N — отдельный контроллер (скрипт), который увеличивает/уменьшает число процессов

В качестве контроллера обычно используют внешний сервер. Однако на практике для прототипа на Termux можно сделать простую схему:

  • оценивать нагрузку (например, по метрикам времени ответа или по числу активных задач)
  • при превышении порога — запускать новый инстанс
  • при снижении — завершать часть инстансов

Технически на Android ресурсы ограничены, поэтому шкалирование разумно ограничить, например максимум 2–4 инстансами.

Локальная сеть и роль VPN (только для организации сети)

Если вам нужно, чтобы устройства в одной среде могли обращаться к сервисам Termux, используйте создание локальной сети (например, при помощи VPN, предназначенного для объединения устройств в одну сеть). Это делается не для обхода блокировок, а для удобства адресации и тестирования.

Балансировка: минимальный роутинг

gRPC требует поддержки HTTP/2. Поэтому “самодельная” балансировка должна быть аккуратной. Для прототипа чаще всего используют:

  • встроенный reverse proxy, поддерживающий gRPC (в “настоящем” деплой-контуре)
  • либо переносите балансировку в внешний контур

На уровне Termux вы можете ограничиться масштабированием несколькими инстансами и ручной или скриптовой маршрутизацией (например, тестировать round-robin через отдельный клиент/шлюз). Для production-логики правильнее использовать внешний балансировщик.

Как деплоить в более “серверный” контур из Termux

Termux удобен для сборки. Дальше артефакты переносите в окружение, где возможен нормальный оркестратор (docker/kubernetes/VM). Практика:

  • компилируете Go/Rust в Termux
  • упаковываете бинарники
  • передаёте в CI/CD
  • разворачиваете в кластере с autoscaling

Для Rust и Go вы получите воспроизводимые артефакты, а autoscaling обеспечит инфраструктура.

Схема деплоя “под ключ” (рекомендованный цикл)

  1. Разработка в Termux: протоколы, серверы, клиенты
  2. Генерация protobuf в сборке (Go: генерация шагом; Rust: build.rs)
  3. Тестирование локально (localhost и локальная сеть)
  4. Сборка релизов (go build / cargo build --release)
  5. Публикация (CI/CD) и развертывание в целевом окружении
  6. Автоматическое масштабирование через оркестратор (HPA/metrics)

Так вы сохраняете скорость прототипирования Termux и получаете промышленный деплой.

Заключение

Termux позволяет быстро и удобно разрабатывать микросервисы на Go и Rust с gRPC и protobuf: вы определяете контракты в .proto, генерируете код, поднимаете серверы и проверяете вызовы. А идею автоматического масштабирования реализуете в два этапа: сначала — масштабирование инстансов/пулов для прототипа, затем — перенос в инфраструктуру, где autoscaling выполняется корректно и безопасно.

Если вы хотите собрать рабочий пайплайн разработки и деплоя “от proto до масштабируемого сервиса” под ваш контур, команда РыбинскЛАБ готова помочь: консультации по архитектуре, настройка сборок, gRPC/protobuf-генерация, подготовка к CI/CD и проектирование инфраструктуры масштабирования.

* Текст статьи подготовлен и структурирован с использованием технологий искусственного интеллекта. Проверен и доработан перед публикацией.

Нужна помощь с настройкой Termux, Linux и серверов?

Я оказываю ИТ-услуги: настройка серверов, автоматизация, безопасность, помощь с Linux и инфраструктурой. Материалы сайта — только в ознакомительных и образовательных целях.

Связаться со мной
Поддержать проект