Улучшения в кластере. Кластер формируется динамически, без единой точки отказа (каждая нода подключается ко всем трём через connect_nodes/0)

This commit is contained in:
2026-04-24 20:32:37 +03:00
parent 48d8ba7a2c
commit 6bb29174a5
4 changed files with 78 additions and 134 deletions

View File

@@ -1,137 +1,115 @@
# docker/docker-compose.yml
services: services:
# ================== Кластер EventHub ==================
eventhub-node1: eventhub-node1:
build: build:
context: .. context: ..
dockerfile: docker/Dockerfile dockerfile: docker/Dockerfile
container_name: eventhub-node1 hostname: eventhub-node1.local
ports:
- "8080:8080"
- "8081:8081"
- "8445:8445"
- "8446:8446"
environment: environment:
- NODE_NAME=eventhub-node1@eventhub-node1 - NODE_NAME=eventhub-node1@eventhub-node1.local
- HTTP_PORT=8080
- WS_PORT=8081
- ADMIN_HTTP_PORT=8445
- ADMIN_WS_PORT=8446
- MNESIA_DIR=/app/data
- RELEASE_COOKIE=${RELEASE_COOKIE} - RELEASE_COOKIE=${RELEASE_COOKIE}
- JWT_SECRET=${JWT_SECRET} - JWT_SECRET=${JWT_SECRET}
volumes: - JOIN_NODES=eventhub-node1@eventhub-node1.local,eventhub-node2@eventhub-node2.local,eventhub-node3@eventhub-node3.local
- eventhub-node1-data:/app/data
networks: networks:
- eventhub-net - eventhub-net
volumes:
- eventhub-node1-data:/app/data
ports:
- "8080:8080" # REST API
- "8081:8081" # WebSocket
- "8445:8445" # Admin REST
- "8446:8446" # Admin WebSocket
restart: unless-stopped restart: unless-stopped
eventhub-node2: eventhub-node2:
build: build:
context: .. context: ..
dockerfile: docker/Dockerfile dockerfile: docker/Dockerfile
container_name: eventhub-node2 hostname: eventhub-node2.local
environment:
- NODE_NAME=eventhub-node2@eventhub-node2.local
- RELEASE_COOKIE=${RELEASE_COOKIE}
- JWT_SECRET=${JWT_SECRET}
- JOIN_NODES=eventhub-node1@eventhub-node1.local,eventhub-node2@eventhub-node2.local,eventhub-node3@eventhub-node3.local
networks:
- eventhub-net
volumes:
- eventhub-node2-data:/app/data
ports: ports:
- "8082:8080" - "8082:8080"
- "8083:8081" - "8083:8081"
- "8447:8445" - "9445:8445"
- "8448:8446" - "9446:8446"
environment:
- NODE_NAME=eventhub-node2@eventhub-node2
- HTTP_PORT=8080
- WS_PORT=8081
- ADMIN_HTTP_PORT=8445
- ADMIN_WS_PORT=8446
- MNESIA_DIR=/app/data
- RELEASE_COOKIE=${RELEASE_COOKIE}
- JWT_SECRET=${JWT_SECRET}
- JOIN_NODES=eventhub-node1@eventhub-node1
volumes:
- eventhub-node2-data:/app/data
networks:
- eventhub-net
depends_on:
- eventhub-node1
restart: unless-stopped restart: unless-stopped
eventhub-node3: eventhub-node3:
build: build:
context: .. context: ..
dockerfile: docker/Dockerfile dockerfile: docker/Dockerfile
container_name: eventhub-node3 hostname: eventhub-node3.local
environment:
- NODE_NAME=eventhub-node3@eventhub-node3.local
- RELEASE_COOKIE=${RELEASE_COOKIE}
- JWT_SECRET=${JWT_SECRET}
- JOIN_NODES=eventhub-node1@eventhub-node1.local,eventhub-node2@eventhub-node2.local,eventhub-node3@eventhub-node3.local
networks:
- eventhub-net
volumes:
- eventhub-node3-data:/app/data
ports: ports:
- "8084:8080" - "8084:8080"
- "8085:8081" - "8085:8081"
- "8449:8445" - "11445:8445"
- "8450:8446" - "11446:8446"
environment:
- NODE_NAME=eventhub-node3@eventhub-node3
- HTTP_PORT=8080
- WS_PORT=8081
- ADMIN_HTTP_PORT=8445
- ADMIN_WS_PORT=8446
- MNESIA_DIR=/app/data
- RELEASE_COOKIE=${RELEASE_COOKIE}
- JWT_SECRET=${JWT_SECRET}
- JOIN_NODES=eventhub-node1@eventhub-node1
volumes:
- eventhub-node3-data:/app/data
networks:
- eventhub-net
depends_on:
- eventhub-node1
restart: unless-stopped
observer_web:
build:
context: ..
dockerfile: docker/ObserverWeb.Dockerfile
container_name: observer_web
ports:
- "4000:4000"
environment:
- RELEASE_COOKIE=${RELEASE_COOKIE}
networks:
- eventhub-net
restart: unless-stopped restart: unless-stopped
# ================== Мониторинг ==================
prometheus: prometheus:
image: prom/prometheus:latest image: prom/prometheus:latest
container_name: prometheus
volumes: volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus - prometheus-data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
ports:
- "9090:9090"
networks: networks:
- eventhub-net - eventhub-net
ports:
- "9090:9090"
restart: unless-stopped restart: unless-stopped
grafana: grafana:
image: grafana/grafana:latest image: grafana/grafana:latest
container_name: grafana
depends_on:
- prometheus
ports:
- "3000:3000"
environment: environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD} - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD}
volumes: volumes:
- grafana-data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning - ./grafana/provisioning:/etc/grafana/provisioning
- grafana-data:/var/lib/grafana
networks: networks:
- eventhub-net - eventhub-net
ports:
- "3000:3000"
restart: unless-stopped restart: unless-stopped
# ================== Инструмент отладки ==================
observer_web:
build:
context: ..
dockerfile: docker/ObserverWeb.Dockerfile
environment:
- RELEASE_COOKIE=${RELEASE_COOKIE}
networks:
- eventhub-net
ports:
- "4000:4000"
restart: unless-stopped
# ================== Сети и тома ==================
networks:
eventhub-net:
driver: bridge
volumes: volumes:
eventhub-node1-data: eventhub-node1-data:
eventhub-node2-data: eventhub-node2-data:
eventhub-node3-data: eventhub-node3-data:
prometheus-data: prometheus-data:
grafana-data: grafana-data:
networks:
eventhub-net:
driver: bridge

View File

@@ -1,49 +0,0 @@
-module(admin_app).
-behaviour(application).
-export([start/2, stop/1]).
start(_StartType, _StartArgs) ->
application:ensure_all_started(cowboy),
start_admin_http(),
{ok, self()}.
stop(_State) ->
ok.
start_admin_http() ->
Port = application:get_env(eventhub, admin_http_port, 8445),
Dispatch = cowboy_router:compile([
{'_', [
{"/admin/health", admin_handler_health, []},
{"/admin/stats", admin_handler_stats, []},
{"/admin/users", admin_handler_users, []},
{"/admin/users/:id", admin_handler_user_by_id, []},
{"/admin/calendars", admin_handler_calendars, []},
{"/admin/calendars/:id", admin_handler_calendar_by_id, []},
{"/admin/events", admin_handler_events, []},
{"/admin/events/:id", admin_handler_event_by_id, []},
{"/admin/reports", handler_reports, []},
{"/admin/reports/:id", handler_report_by_id, []},
{"/admin/tickets", handler_tickets, []},
{"/admin/tickets/:id", handler_ticket_by_id, []},
{"/admin/tickets/stats", handler_ticket_stats, []},
{"/admin/subscriptions", handler_admin_subscriptions, []},
{"/admin/banned-words", handler_banned_words, []}
]}
]),
Middlewares = [
cowboy_router,
cowboy_handler
],
Env = #{dispatch => Dispatch},
cowboy:start_clear(admin_http, [{port, Port}], #{
env => Env,
middlewares => Middlewares
}),
io:format("Admin HTTP server started on port ~p~n", [Port]).

View File

@@ -1,3 +1,3 @@
-sname ${NODE_NAME} -name ${NODE_NAME}
-setcookie ${RELEASE_COOKIE} -setcookie ${RELEASE_COOKIE}
-kernel inet_dist_use_interface {0,0,0,0} -kernel inet_dist_use_interface {0,0,0,0}

View File

@@ -12,6 +12,7 @@ start(_StartType, _StartArgs) ->
{ok, Pid} -> {ok, Pid} ->
ok = infra_mnesia:init_tables(), ok = infra_mnesia:init_tables(),
ok = infra_mnesia:wait_for_tables(), ok = infra_mnesia:wait_for_tables(),
connect_nodes(),
start_http(), start_http(),
start_admin_http(), start_admin_http(),
% Запускаем сборщик метрик Prometheus % Запускаем сборщик метрик Prometheus
@@ -126,4 +127,18 @@ start_admin_http() ->
env => #{dispatch => AdminWsDispatch} env => #{dispatch => AdminWsDispatch}
}), }),
io:format("WebSocket started on ports 8081 (user) and 8446 (admin)~n"). io:format("WebSocket started on ports 8081 (user) and 8446 (admin)~n").
connect_nodes() ->
case os:getenv("JOIN_NODES") of
false -> ok;
NodesStr ->
Nodes = [list_to_atom(string:trim(N)) || N <- string:tokens(NodesStr, ",")],
lists:foreach(fun(Node) ->
case net_kernel:connect_node(Node) of
true -> io:format("Connected to ~s~n", [Node]);
false -> io:format("ERROR: Failed to connect to ~s~n", [Node]);
ignored -> ok
end
end, Nodes)
end.