feat(split): data-plane (публичный SQS API) и control-plane (админка/метрики/UI на localhost) — Шаг 2

This commit is contained in:
Repinoid
2026-10-10 16:00:57 +03:00
parent a66b908689
commit a26e6da8b7
2 changed files with 82 additions and 39 deletions
+33 -11
View File
@@ -29,12 +29,14 @@ func main() {
var configFile string
var adminToken string
var port string
var controlPort string
var debug bool
var loglevel string
flag.StringVar(&configFile, "config", "", "config file location")
flag.StringVar(&adminToken, "admin-token", "", "admin API bearer token")
flag.StringVar(&port, "port", "4100", "listen port")
flag.StringVar(&port, "port", "4100", "data-plane listen port")
flag.StringVar(&controlPort, "control-port", "4101", "control-plane listen port (localhost only: admin/metrics/ui)")
flag.BoolVar(&debug, "debug", false, "set debug log level")
flag.StringVar(&loglevel, "loglevel", "info", "log level (info, debug, warn, error)")
flag.Parse()
@@ -130,8 +132,10 @@ func main() {
// Billing: подключение к PostgreSQL для учёта использования.
// Если BILLING_PG_HOST не задан — billing отключён, SQS работает без него.
billing.Init()
// Роутер с tenant auth и admin API
r := router.New(tenantStore, adminToken)
// Разбиение data-plane/control-plane (Шаг 2):
// data-plane — публичный SQS API; control-plane — админка/метрики/UI (только localhost).
dataRouter := router.NewDataPlane(tenantStore)
controlRouter := router.NewControlPlane(tenantStore, adminToken)
// PeriodicTasks — visibility timeout, DLQ, deduplication
quit := make(chan bool)
@@ -148,20 +152,35 @@ func main() {
// - IdleTimeout 90с — keep-alive; больше интервала ретраев клиентских SDK.
// - MaxHeaderBytes 8192 — защита от гигантских заголовков
// (платформа режет >16KB, наш лимит строже).
srv := &http.Server{
dataSrv := &http.Server{
Addr: "0.0.0.0:" + port,
Handler: r,
Handler: dataRouter,
ReadHeaderTimeout: 10 * time.Second,
WriteTimeout: 35 * time.Second,
IdleTimeout: 90 * time.Second,
MaxHeaderBytes: 8192,
}
// control-plane слушает ТОЛЬКО localhost — админка/метрики/UI не должны быть публичными.
controlSrv := &http.Server{
Addr: "127.0.0.1:" + controlPort,
Handler: controlRouter,
ReadHeaderTimeout: 10 * time.Second,
WriteTimeout: 35 * time.Second,
IdleTimeout: 90 * time.Second,
MaxHeaderBytes: 8192,
}
// Запуск в горутине для graceful shutdown
serverErr := make(chan error, 1)
// Запуск в горутинах для graceful shutdown
serverErr := make(chan error, 2)
go func() {
log.Infof("shared-sqs listening on 0.0.0.0:%s", port)
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Infof("shared-sqs data-plane listening on 0.0.0.0:%s", port)
if err := dataSrv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
serverErr <- err
}
}()
go func() {
log.Infof("shared-sqs control-plane listening on 127.0.0.1:%s", controlPort)
if err := controlSrv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
serverErr <- err
}
}()
@@ -186,8 +205,11 @@ func main() {
// Дать 10 секунд на завершение текущих HTTP запросов
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
log.Errorf("Server shutdown error: %v", err)
if err := dataSrv.Shutdown(ctx); err != nil {
log.Errorf("Data-plane shutdown error: %v", err)
}
if err := controlSrv.Shutdown(ctx); err != nil {
log.Errorf("Control-plane shutdown error: %v", err)
}
log.Info("shared-sqs stopped")
}