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

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

Разработка и запуск микросервисов на Go в Termux с gRPC, Protobuf и автоматической генерацией клиентского кода

Пошагово разрабатываем микросервисы на Go в Termux: поднимаем gRPC-сервер, описываем API в Protobuf, автоматически генерируем клиентский код и запускаем сервисы в локальной сети.

Termux — отличный инструмент для разработки и тестирования сервисов прямо с мобильного устройства. В этой статье мы соберём минимальную, но полноценную связку: gRPC-сервер на Go, описание API через Protobuf и автоматическую генерацию клиентского кода. В результате вы сможете быстро разворачивать микросервисы, обновлять контракты и не вручную править клиентские вызовы.

Фокус статьи — практический: командами в Termux, воспроизводимый сценарий генерации и запуск нескольких компонентов в локальной сети (без привязки к обходу блокировок).

Архитектура примера: контракт и клиент

Сделаем два микросервиса (для демонстрации связей):

  • user-service — gRPC-сервер, реализует методы работы с пользователями (например, получение списка).
  • client — клиент, который генерируем автоматически из .proto файлов и вызывает user-service.

Параллельно покажем шаблон, как масштабировать под несколько сервисов: добавляете протокол — обновляете генерацию — пересобираете клиент/сервер.

Подготовка окружения в Termux

Перед началом убедитесь, что у вас установлены актуальные пакеты. Обновим репозитории и поставим базовые утилиты. Для Go и генерации кода пригодятся git, curl, unzip и инструменты сборки.

pkg update -y
pkg upgrade -y
pkg install -y git curl unzip clang make tar jq

Установка Go в Termux

Есть несколько способов поставить Go. Один из удобных — через официальные бинарники. Ниже — типовой сценарий: скачиваем архив, распаковываем и добавляем путь в $PATH. Команды могут отличаться по версии; выбирайте актуальную стабильную версию Go.

# Пример: скачиваем Go (версию подставьте актуальную)
GO_VERSION=1.22.5
cd /sdcard
curl -L -o go.tar.gz https://go.dev/dl/go${GO_VERSION}.linux-arm64.tar.gz
rm -rf /data/data/com.termux/files/usr/local/go
mkdir -p /data/data/com.termux/files/usr/local
 tar -xzf go.tar.gz -C /data/data/com.termux/files/usr/local

# Настройка PATH (если ещё не сделано)
# Добавьте в конец ~/.bashrc или ~/.zshrc строки:
# export PATH="$PATH:/data/data/com.termux/files/usr/local/go/bin"

echo 'export PATH="$PATH:/data/data/com.termux/files/usr/local/go/bin"' >> ~/.bashrc
source ~/.bashrc

# Проверка
go version

Если у вас другой ABI (arm/arm64), подберите соответствующий дистрибутив Go для вашей архитектуры.

Поднимаем структуру проекта

Создадим рабочую папку. В ней будет:

  • proto/ — файлы .proto
  • user-service/ — сервер на Go
  • client/ — клиент на Go (генерируется частично)
  • scripts/ — скрипт генерации
mkdir -p termux-grpc-example/{proto,user-service,client,scripts}
cd termux-grpc-example

Описание API в Protobuf

Создадим протокол сервиса UserService. Например, метод ListUsers, который возвращает список пользователей.

cat > proto/user.proto <<'EOF'
syntax = "proto3";

package user.v1;
option go_package = "termux-grpc-example/gen/user/v1;userv1";

message User {
  string id = 1;
  string name = 2;
}

message ListUsersRequest {
  int32 limit = 1;
}

message ListUsersResponse {
  repeated User users = 1;
}

service UserService {
  rpc ListUsers(ListUsersRequest) returns (ListUsersResponse);
}
EOF

Ключевой момент — option go_package. Он задаёт, куда будут попадать сгенерированные Go-файлы. Это упростит дальнейшую сборку.

Установка protoc и плагинов для генерации Go-кода

Для генерации gRPC и Protobuf под Go нужны:

  • protoc
  • protoc-gen-go
  • protoc-gen-go-grpc

В Termux можно поставить protoc и плагины через загрузку и go install.

# protoc (пример для linux-arm64; при необходимости поменяйте архитектуру)
PROTOC_VERSION=27.2
cd /sdcard
curl -L -o protoc.zip https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-aarch_64.zip
unzip -o protoc.zip -d /data/data/com.termux/files/usr

# Проверка
/data/data/com.termux/files/usr/bin/protoc --version || protoc --version

# Плагины (установятся в GOPATH/bin)
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

# Убедитесь, что GOPATH/bin в PATH
echo 'export PATH="$PATH:$(go env GOPATH)/bin"' >> ~/.bashrc
source ~/.bashrc

# Проверка
which protoc-gen-go
which protoc-gen-go-grpc

Автоматическая генерация клиентского кода

Чтобы клиентский код не обновлялся вручную, сделаем скрипт генерации. Он будет:

  • вызывать protoc
  • генерировать стандартные структуры Protobuf
  • генерировать интерфейсы/код для gRPC
  • размещать результат в заранее согласованной директории gen/

Обычно клиент и сервер используют одни и те же сгенерированные типы.

cat > scripts/generate.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT_DIR"

mkdir -p gen

# Генерация Go кода из proto
protoc \
  --proto_path="$ROOT_DIR/proto" \
  --go_out="$ROOT_DIR" \
  --go_opt=module=termux-grpc-example \
  --go-grpc_out="$ROOT_DIR" \
  --go-grpc_opt=module=termux-grpc-example \
  "$ROOT_DIR/proto/user.proto"

echo "Generation complete. Output in ./gen (as per option go_package)."
EOF

chmod +x scripts/generate.sh

# Запуск генерации
./scripts/generate.sh

# Посмотреть что сгенерировалось
find gen -maxdepth 5 -type f -name '.go' | head

Примечание: конкретная структура папок в gen/ зависит от значения option go_package. Важно, чтобы Go-пакеты соответствовали import путям в ваших проектах.

Реализация gRPC-сервера user-service на Go

Теперь создадим сервер. Он будет реализовывать интерфейс UserService и возвращать фиктивные данные.

cd user-service

# Инициализация модуля Go
# Имя модуля можно сделать одинаковым для простоты примера
cat > go.mod <<'EOF'
module termux-grpc-example/user-service

go 1.22

require (
  google.golang.org/grpc v1.66.0
  google.golang.org/protobuf v1.34.2
)

replace termux-grpc-example => ..
EOF

mkdir -p internal
cat > internal/server.go <<'EOF'
package internal

import (
  "context"
  "fmt"

  userv1 "termux-grpc-example/gen/user/v1"
)

type Server struct {
  userv1.UnimplementedUserServiceServer
}

func (s Server) ListUsers(ctx context.Context, req userv1.ListUsersRequest) (userv1.ListUsersResponse, error) {
  limit := int(req.GetLimit())
  if limit <= 0 {
    limit = 5
  }

  users := make([]userv1.User, 0, limit)
  for i := 0; i < limit; i++ {
    users = append(users, &userv1.User{
      Id:   fmt.Sprintf("u%03d", i+1),
      Name: fmt.Sprintf("User %d", i+1),
    })
  }

  return &userv1.ListUsersResponse{Users: users}, nil
}
EOF

cat > main.go <<'EOF'
package main

import (
  "log"
  "net"

  "google.golang.org/grpc"

  "termux-grpc-example/user-service/internal"
  userv1 "termux-grpc-example/gen/user/v1"
)

func main() {
  // Для локальной разработки на телефоне удобно слушать на 0.0.0.0
  addr := ":50051"
  lis, err := net.Listen("tcp", addr)
  if err != nil {
    log.Fatalf("listen: %v", err)
  }

  grpcServer := grpc.NewServer()
  userv1.RegisterUserServiceServer(grpcServer, &internal.Server{})

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

# Подтянуть зависимости
go mod tidy

# Сборка/запуск
cd ..
cd user-service
# В отдельном окне Terminal запустите:
# go run .

# (Обычно это шаг, который вы повторяете после правок)

go run .
EOF

Остановить сервис можно нажатием Ctrl+C.

Реализация клиента с использованием сгенерированного кода

Клиент будет использовать сгенерированные структуры и stub для вызовов. Сгенерированный код приходит из тех же .proto, поэтому после изменения контракта достаточно снова запустить генерацию.

cd ../client

cat > go.mod <<'EOF'
module termux-grpc-example/client

go 1.22

require (
  google.golang.org/grpc v1.66.0
  google.golang.org/protobuf v1.34.2
)

replace termux-grpc-example => ..
EOF

cat > main.go <<'EOF'
package main

import (
  "context"
  "log"
  "time"

  "google.golang.org/grpc"
  userv1 "termux-grpc-example/gen/user/v1"
)

func main() {
  // На практике IP берите из вашей локальной сети.
  // Для простоты: предполагаем, что клиент и сервер запущены на одном устройстве.
  // Тогда используйте 127.0.0.1.
  // Если между устройствами — подставьте IP телефона/хоста в локальной сети.
  target := "127.0.0.1:50051"

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

  c := userv1.NewUserServiceClient(conn)

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

  resp, err := c.ListUsers(ctx, &userv1.ListUsersRequest{Limit: 3})
  if err != nil {
    log.Fatalf("ListUsers: %v", err)
  }

  for _, u := range resp.GetUsers() {
    log.Printf("%s: %s", u.GetId(), u.GetName())
  }
}
EOF

go mod tidy

# Запуск клиента (в отдельном терминале, пока сервер работает)
go run .

Если сервер и клиент на разных устройствах: вместо 127.0.0.1 укажите IP того устройства, где работает user-service. Убедитесь, что порт 50051 доступен в вашей локальной сети.

Запуск микросервисов в локальной сети (опционально)

Если вы хотите проверять взаимодействие между несколькими устройствами в одной локальной сети, используйте инфраструктуру вашей сети (Wi‑Fi и т.п.). При необходимости можно организовать локальную сеть через VPN-средства, но строго для объединения устройств в локальный контур разработки.

Примерно ваши действия выглядят так:

  • сервер слушает :50051 (или 0.0.0.0:50051)
  • клиент указывает target как IP сервера в локальной сети
  • проверяете, что firewall/настройки сети не блокируют соединение

В случае проблем начните с проверки: сервер доступен с устройства клиента на уровне TCP (хотя gRPC — поверх TCP).

Изменение контракта: как не сломать клиента

Один из ключевых плюсов Protobuf + генерации — снижение риска ручных несоответствий. Процесс изменения обычно такой:

  1. обновляете proto/user.proto
  2. перегенерируете код командой ./scripts/generate.sh
  3. пересобираете/перезапускаете сервер и клиента

Например, после изменения протокола выполните:

cd /sdcard/termux-grpc-example
./scripts/generate.sh

# затем перезапустите
# (в разных терминалах)
# cd user-service && go run .
# cd client && go run .

Продвижение к микросервисам: практические рекомендации

  • Разделяйте протоколы: для каждого сервиса держите отдельные .proto или папки.
  • Соглашения по версиям: используйте namespace вида user.v1.
  • Единая генерация: держите генерацию в одном скрипте (как показано в scripts/generate.sh), чтобы команда разработки делала одно и то же.
  • Наблюдаемость: добавляйте логирование в сервер и печатайте информацию о входящих запросах.

Заключение

Мы собрали практичный пример разработки микросервисов на Go в Termux: описали API в Protobuf, настроили генерацию клиентского и серверного кода для gRPC, реализовали user-service и запустили клиента, который вызывает методы через сгенерированные stub’ы. Такой подход ускоряет итерации и уменьшает вероятность ошибок при изменении контракта.

Если хотите, РыбинскЛАБ поможет довести проект до промышленного уровня: структура модулей, автоматизация сборки/генерации, Docker-ориентированный workflow, CI для репорта контрактов и стабильная схема версионирования. Обращайтесь в РыбинскЛАБ — поможем внедрить gRPC/Protobuf микросервисы под ваши задачи.

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

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

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

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