Load Balancer Pool Distribution Analyzer

.calc-header { margin-bottom: 30px; padding: 25px; background: linear-gradient(135deg, #FF6B6B 0%, #C92A2A 100%); border-radius: 12px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); color: white; } .calc-header h2 { margin-top: 0; color: white; font-size: 28px; margin-bottom: 10px; } .calc-header p { margin: 10px 0 20px 0; opacity: 0.95; font-size: 15px; } .form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-top: 20px; } .form-grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 15px; margin-top: 15px; } .form-group { display: flex; flex-direction: column; gap: 8px; } .form-group label { font-weight: 600; font-size: 14px; color: white; } .form-group input, .form-group select { padding: 12px; font-size: 15px; border: 2px solid rgba(255,255,255,0.3); border-radius: 6px; background: rgba(255,255,255,0.95); transition: all 0.3s ease; font-family: 'Courier New', monospace; } .form-group input:focus, .form-group select:focus { outline: none; border-color: #4CAF50; background: white; box-shadow: 0 0 0 3px rgba(76, 175, 80, 0.15); } .form-group select { cursor: pointer; font-family: inherit; } .submit-btn { padding: 14px 35px; font-size: 16px; background: #4CAF50; color: white; border: none; border-radius: 6px; cursor: pointer; font-weight: bold; transition: all 0.3s ease; box-shadow: 0 2px 4px rgba(0,0,0,0.2); margin-top: 15px; width: 100%; } .submit-btn:hover { background: #45a049; transform: translateY(-1px); box-shadow: 0 4px 8px rgba(0,0,0,0.3); } .submit-btn:active { background: #3d8b40; transform: translateY(0); } .secondary-btn { padding: 10px 20px; font-size: 14px; background: rgba(255,255,255,0.2); color: white; border: 2px solid rgba(255,255,255,0.5); border-radius: 6px; cursor: pointer; font-weight: bold; transition: all 0.3s ease; } .secondary-btn:hover { background: rgba(255,255,255,0.35); border-color: white; } .danger-btn { padding: 8px 14px; font-size: 13px; background: #e53935; color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: bold; transition: all 0.2s ease; } .danger-btn:hover { background: #c62828; } .result-section { background: white; border: 1px solid #e0e0e0; border-radius: 8px; margin-top: 20px; overflow: hidden; box-shadow: 0 2px 4px rgba(0,0,0,0.05); transition: all 0.3s ease; display: none; } .result-section.show { display: block; } .result-section:hover { box-shadow: 0 4px 8px rgba(0,0,0,0.1); } .section-header { background: linear-gradient(135deg, #4CAF50 0%, #45a049 100%); color: white; padding: 15px 20px; } .section-header h3 { margin: 0; font-size: 18px; display: flex; align-items: center; gap: 10px; } .section-content { padding: 20px; background: #fafafa; } .data-row { display: flex; margin: 12px 0; padding: 10px; background: white; border-radius: 4px; border-left: 3px solid #4CAF50; align-items: center; } .data-label { font-weight: bold; color: #555; min-width: 220px; flex-shrink: 0; font-size: 14px; } .data-value { color: #333; font-family: 'Courier New', monospace; word-break: break-word; font-size: 18px; } .data-value.highlight { color: #4CAF50; font-weight: bold; font-size: 22px; } .data-value.warning { color: #FF6B6B; font-weight: bold; font-size: 22px; } .help-text { margin-top: 15px; font-size: 14px; color: rgba(255,255,255,0.9); background: rgba(0,0,0,0.1); padding: 10px 15px; border-radius: 4px; } .help-text strong { color: white; } /* Member list table */ .member-table { width: 100%; border-collapse: collapse; margin-top: 10px; font-size: 14px; } .member-table th { background: #f0f0f0; padding: 10px 12px; text-align: left; font-weight: 600; color: #444; border-bottom: 2px solid #ddd; } .member-table td { padding: 10px 12px; border-bottom: 1px solid #eee; vertical-align: middle; } .member-table tr:last-child td { border-bottom: none; } .member-table tr:hover td { background: #f9f9f9; } /* Status badge */ .status-badge { display: inline-block; padding: 3px 10px; border-radius: 12px; font-size: 12px; font-weight: bold; text-transform: uppercase; letter-spacing: 0.5px; } .status-badge.up { background: #e8f5e9; color: #2e7d32; border: 1px solid #a5d6a7; } .status-badge.down { background: #ffebee; color: #c62828; border: 1px solid #ef9a9a; } /* Balance score ring */ .balance-score-container { display: flex; align-items: center; gap: 20px; padding: 15px; background: white; border-radius: 8px; border: 1px solid #e0e0e0; margin-bottom: 15px; } .balance-score-ring { width: 80px; height: 80px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 22px; font-weight: bold; color: white; flex-shrink: 0; box-shadow: 0 2px 8px rgba(0,0,0,0.2); } .balance-score-ring.excellent { background: linear-gradient(135deg, #43a047, #1b5e20); } .balance-score-ring.good { background: linear-gradient(135deg, #7cb342, #558b2f); } .balance-score-ring.fair { background: linear-gradient(135deg, #fb8c00, #e65100); } .balance-score-ring.poor { background: linear-gradient(135deg, #e53935, #b71c1c); } .balance-score-info { flex: 1; } .balance-score-info h4 { margin: 0 0 5px 0; font-size: 18px; color: #333; } .balance-score-info p { margin: 0; font-size: 13px; color: #666; line-height: 1.5; } /* Metrics grid */ .metrics-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 20px; } .metric-card { background: white; border: 1px solid #e0e0e0; border-radius: 8px; padding: 15px; text-align: center; border-top: 3px solid #4CAF50; } .metric-card .metric-value { font-size: 22px; font-weight: bold; color: #333; font-family: 'Courier New', monospace; } .metric-card .metric-label { font-size: 12px; color: #888; margin-top: 4px; } /* Chart container */ .chart-wrapper { background: white; border: 1px solid #e0e0e0; border-radius: 8px; padding: 20px; margin-bottom: 20px; } .chart-wrapper h4 { margin: 0 0 15px 0; color: #444; font-size: 15px; font-weight: 600; } /* Algorithm explanation */ .algo-explanation { background: #fff8e1; border: 1px solid #ffe082; border-radius: 6px; padding: 12px 15px; font-size: 13px; color: #5d4037; line-height: 1.6; margin-top: 10px; } .algo-explanation strong { color: #3e2723; } /* Hash ring visualization */ .ring-wrapper { display: flex; align-items: flex-start; gap: 20px; } #hashRingCanvas { border: 1px solid #e0e0e0; border-radius: 50%; display: block; flex-shrink: 0; } .ring-legend { flex: 1; } .ring-legend-item { display: flex; align-items: center; gap: 10px; padding: 6px 0; font-size: 13px; border-bottom: 1px solid #f0f0f0; } .ring-legend-dot { width: 14px; height: 14px; border-radius: 50%; flex-shrink: 0; } /* Redistribution info */ .redistribution-row { display: flex; align-items: center; gap: 10px; padding: 8px 12px; background: white; border-radius: 4px; border-left: 3px solid #FF6B6B; margin-bottom: 6px; font-size: 14px; } .redistribution-row .arrow { color: #FF6B6B; font-size: 18px; flex-shrink: 0; } .redistribution-row .move-label { color: #555; flex: 1; } .redistribution-row .move-count { font-family: 'Courier New', monospace; font-weight: bold; color: #333; } /* Slider styling */ .slider-group { display: flex; flex-direction: column; gap: 8px; margin-top: 5px; } .slider-group label { font-weight: 600; font-size: 14px; color: white; display: flex; justify-content: space-between; } .slider-group label span { font-family: 'Courier New', monospace; background: rgba(0,0,0,0.2); padding: 2px 8px; border-radius: 4px; font-size: 13px; } input[type="range"] { width: 100%; accent-color: #4CAF50; height: 6px; cursor: pointer; } /* Controls area inside header */ .header-controls { margin-top: 20px; } .control-group-label { font-weight: 600; font-size: 13px; color: rgba(255,255,255,0.8); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 8px; margin-top: 18px; } .add-member-row { display: flex; gap: 8px; align-items: flex-end; flex-wrap: wrap; } .add-member-row .form-group { flex: 1; min-width: 120px; } /* Failure simulation section */ .failure-section { background: rgba(0,0,0,0.1); border-radius: 8px; padding: 15px; margin-top: 18px; } .failure-section .control-group-label { margin-top: 0; } .failure-row { display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; } .failure-row .form-group { flex: 1; min-width: 140px; } .failure-btn-group { display: flex; gap: 8px; } /* Responsive design */ @media (max-width: 768px) { .form-grid, .form-grid-3 { grid-template-columns: 1fr; } .metrics-grid { grid-template-columns: 1fr 1fr; } .data-row { flex-direction: column; align-items: flex-start; } .data-label { margin-bottom: 4px; min-width: auto; } .ring-wrapper { flex-direction: column; } #hashRingCanvas { width: 220px !important; height: 220px !important; align-self: center; } .balance-score-container { flex-direction: column; text-align: center; } .add-member-row { flex-direction: column; } .add-member-row .form-group { min-width: auto; width: 100%; } .failure-row { flex-direction: column; } } @media (max-width: 480px) { .calc-header h2 { font-size: 22px; } .metrics-grid { grid-template-columns: 1fr; } } CDN Chart.js
========== ЗАГОЛОВОК / ЕЛЕМЕНТИ КЕРУВАННЯ ==========

Аналізатор розподілу пулу балансувальника навантаження

Змоделюйте, як різні алгоритми балансування навантаження розподіляють трафік між учасниками пулу. Змоделюйте сценарії відмови та порівняйте ефективність перерозподілу.

Алгоритм і кількість сеансів
Повзунок підрахунку сеансів
Обсяг трафіку
Керування учасниками пулу
Члени пулу
Симуляція відмови
Симуляція сценарію відмови
Як це працює:IP-адреси клієнтів беруться з підмережі /16 (10.0.0.0/16). Для хешування на основі джерела кожна унікальна IP-адреса клієнта детерміновано відображається на члена. Round robin ігнорує IP-адресу клієнта та розподіляє послідовно. Weighted використовує пропорційне випадкове призначення. Послідовне хешування розміщує клієнтів і учасників у віртуальному кільці.
========== ТАБЛИЦЯ ЧЛЕНІВ ==========

Члени пулу

заповнений JS
ID IP:Порт вага Статус Дії
========== РЕЗУЛЬТАТИ РОЗПОЗИЦІЇ ==========

Результати розподілу

Оцінка балансу + пояснення алгоритму
Метрична сітка
Гістограма

Розподіл сеансів на учасника

Рядки деталей члена
========== ПОМИЛКА ПЕРЕРОЗПОДІЛУ ==========

Аналіз перерозподілу відмов

========== ВІЗУАЛІЗАЦІЯ HESH RING ==========

Послідовне хеш-кільце

Читання кільця:Кожен учасник розміщується в кількох точках навколо кільця (віртуальні вузли). IP-адреса клієнта хешується до позиції в кільці, а потім надсилається запит до найближчого члена за годинниковою стрілкою. Додавання або видалення члена впливає лише на арку дзвонити як власник — мінімізуючи переривання сеансу.
========== ДОПОМОГА / КОНЦЕПЦІЇ ==========

Довідник по алгоритму

Кругова система
Сеанси призначаються послідовно: учасник 1, 2, 3, ..., N, 1, 2, ... Кожен учасник отримує рівно 1/N усіх запитів. Ігнорує потужність сервера та клієнтську приналежність. Простий і передбачуваний, але зазнає серйозних збоїв на різнорідному обладнанні.
Хеш IP-адреси джерела
Хеш IP-адреси клієнта за модулем кількості учасників вибирає серверну частину. Той самий клієнт завжди досягає того самого члена — корисно для додатків із збереженням стану. Додавання або видалення учасник змінюєтьсявсезіставлення клієнта (N змінено на (N-1)/N усіх сеансів).
Зважений
Кожен учасник отримує частку, пропорційну його вазі відносно загальної ваги басейн. Учасник із вагою=4 отримує в 4 рази більше сеансів, ніж учасник з вагою=1. Використовується для моделювання гетерогенна потужність серверної частини (наприклад, віртуальна машина проти сервера без використання).
Послідовне хешування
Учасники та клієнти відображаються на круговому кільці за допомогою хешування. Кожен клієнт йде до найближчого члена за годинниковою стрілкою на кільці. Віртуальні вузли (репліки на учасника) поліпшити рівномірність розподілу. Коли учасник виходить з ладу, лише його сесії переходять до наступний учасник кільця — 1/N сеансів порушено проти 100% для хешування за модулем.