EchoSeniorExperience

Какие production-риски есть у Echo (Go framework): blocking code, connection pooling, config, auth, observability, deploy или graceful shutdown?

Production-риски Echo: блокирующий код в хендлерах, отсутствие таймаутов на сервере, утечки соединений из-за неправильного пулинга БД, слабая конфигурация TLS/auth, отсутствие структурированных логов и трейсинга, некорректный graceful shutdown.

Production-риски Echo (Go framework)

1. Блокирующий код в хендлерах

Go-рутины Echo обслуживают запросы конкурентно, но блокирующий вызов (синхронный HTTP-запрос, тяжёлые вычисления без горутин) «подвешивает» воркер. Решение — выносить долгие операции в отдельные горутины с context-отменой:

func heavyHandler(c echo.Context) error {
	ctx := c.Request().Context()
	resultCh := make(chan string, 1)
	go func() {
		resultCh <- doHeavyWork(ctx)
	}()
	select {
	case res := <-resultCh:
		return c.JSON(http.StatusOK, res)
	case <-ctx.Done():
		return echo.ErrRequestTimeout
	}
}

2. Отсутствие таймаутов сервера

Echo оборачивает стандартный net/http.Server. Без явных таймаутов «медленные клиенты» держат соединение вечно:

e := echo.New()
s := &http.Server{
	Addr:         ":8080",
	ReadTimeout:  5 * time.Second,
	WriteTimeout: 10 * time.Second,
	IdleTimeout:  120 * time.Second,
	Handler:      e,
}
if err := s.ListenAndServe(); err != http.ErrServerClosed {
	log.Fatal(err)
}

3. Connection Pooling (database/sql)

По умолчанию sql.DB создаёт неограниченное число соединений. Обязательно задавайте лимиты:

db, _ := sql.Open("pgx", dsn)
db.SetMaxOpenConns(25)
db.SetMaxIdleConns(10)
db.SetConnMaxLifetime(5 * time.Minute)

4. Конфигурация и секреты

Нельзя хранить секреты в коде или репозитории. Используйте переменные окружения + библиотеку github.com/spf13/viper или github.com/kelseyhightower/envconfig. В production переключайтесь на Vault / AWS Secrets Manager.

5. Auth и JWT

Стандартный мидлвар echojwt проверяет подпись, но не проверяет отзыв токена. Добавляйте blacklist в Redis или используйте короткоживущие access-токены (15 мин) + refresh-токены:

import echojwt "github.com/labstack/echo-jwt/v4"

e.Use(echojwt.WithConfig(echojwt.Config{
	SigningKey:  []byte(os.Getenv("JWT_SECRET")),
	TokenLookup: "header:Authorization:Bearer ",
}))

6. Observability

Echo не поставляет метрики из коробки. Подключайте echo-contrib/prometheus и otelecho (OpenTelemetry):

import (
	"github.com/labstack/echo-contrib/echoprometheus"
	"go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho"
)

e.Use(otelecho.Middleware("my-service"))
e.Use(echoprometheus.NewMiddleware("myapp"))
e.GET("/metrics", echoprometheus.NewHandler())

7. Graceful Shutdown

Без graceful shutdown при перезапуске обрываются активные запросы. Корректная реализация:

quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := e.Shutdown(ctx); err != nil {
	e.Logger.Fatal(err)
}

Подводные камни

  • Вызов e.Start() вместо кастомного http.Server — теряете контроль над таймаутами и TLS-конфигурацией.
  • Паника в хендлере без recover-мидлвара кладёт весь процесс; всегда добавляйте e.Use(middleware.Recover()).
  • Передача echo.Context в горутину — контекст становится невалидным после завершения хендлера; копируйте нужные данные до запуска горутины.
  • Логирование через e.Logger (встроенный) не структурировано — в ELK/Loki теряете возможность фильтровать по полям; замените на zerolog или zap.
  • Отсутствие rate-limiting: Echo не имеет встроенного rate-limiter'а; добавляйте middleware.RateLimiter или внешний nginx-лимит.
  • Небезопасный CORS: middleware.CORS() без настройки разрешает все origins — явно задавайте AllowOrigins.
  • Миграции БД, запущенные при старте сервиса (AutoMigrate), блокируют таблицы на production; используйте отдельный init-контейнер или golang-migrate.
  • TLS-терминация внутри Echo без настройки минимальной версии TLS и cipher suites открывает сервис для downgrade-атак.

What hurts your answer

  • Говорить только о запуске Echo (Go framework), но не об эксплуатации
  • Не упоминать observability, обновления, безопасность и rollback
  • Описывать риски абстрактно, без способов их снижать

What they're listening for

  • Видит production-риски Echo (Go framework)
  • Говорит про monitoring, rollout, rollback и безопасность
  • Умеет ранжировать риски по вероятности и влиянию

Related topics