Trình phân tích phân phối nhóm cân bằng tải

.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 của Chart.js
========== TIÊU ĐỀ / KIỂM SOÁT ==========

Trình phân tích phân phối nhóm cân bằng tải

Mô phỏng cách các thuật toán cân bằng tải khác nhau phân phối lưu lượng truy cập giữa các thành viên trong nhóm. Lập mô hình các kịch bản thất bại và so sánh hiệu quả phân phối lại.

Thuật toán & số phiên
Thanh trượt đếm phiên
Lưu lượng giao thông
Quản lý thành viên nhóm
Thành viên nhóm
Mô phỏng lỗi
Mô phỏng kịch bản thất bại
Nó hoạt động như thế nào:IP máy khách được lấy mẫu từ mạng con /16 (10.0.0.0/16). Đối với băm dựa trên nguồn, mỗi IP khách hàng duy nhất được ánh xạ xác định tới một thành viên. Vòng tròn bỏ qua IP của khách hàng và phân phối tuần tự. Sử dụng có trọng số tỷ lệ thuận sự phân công ngẫu nhiên. Việc băm nhất quán đặt cả khách hàng và thành viên vào một vòng ảo.
========== BẢNG THÀNH VIÊN ===========

Thành viên nhóm

được phổ biến bởi JS
NHẬN DẠNG IP:Cổng Cân nặng Trạng thái hành động
========== KẾT QUẢ PHÂN PHỐI ==========

Kết quả phân phối

Điểm cân bằng + giải thích thuật toán
Lưới số liệu
Biểu đồ thanh

Phân phối phiên cho mỗi thành viên

Hàng chi tiết thành viên
========== PHÂN PHỐI LẠI THẤT BẠI ==========

Phân tích phân phối lại thất bại

========== HIỂN THỊ VÒNG Băm ==========

Vòng băm nhất quán

Đọc chiếc nhẫn:Mỗi thành viên được đặt ở nhiều điểm xung quanh vòng (các nút ảo). IP của khách hàng được băm vào một vị trí trên vòng, sau đó yêu cầu sẽ được gửi đến thành viên gần nhất theo chiều kim đồng hồ. Việc thêm hoặc bớt một thành viên chỉ ảnh hưởng đến cung của đổ chuông mà nó sở hữu — giảm thiểu sự gián đoạn phiên.
========== GIÚP ĐỠ / KHÁI NIỆM ==========

Tham khảo thuật toán

Vòng Robin
Các phiên được phân công tuần tự: thành viên 1, 2, 3, ..., N, 1, 2, ... Mỗi thành viên nhận được chính xác 1/N tất cả các yêu cầu. Bỏ qua dung lượng máy chủ và mối quan hệ của khách hàng. Đơn giản và có thể dự đoán được nhưng lại thất bại nặng nề trên phần cứng không đồng nhất.
Mã băm IP nguồn
Băm của mô-đun IP máy khách, số lượng thành viên sẽ chọn phần phụ trợ. Cùng một khách hàng luôn tiếp cận cùng một thành viên - hữu ích cho các ứng dụng có trạng thái. Thêm hoặc xóa thay đổi thành viêntất cảánh xạ máy khách (N thay đổi thành (N-1)/N của tất cả các phiên).
Có trọng số
Mỗi thành viên nhận được một phần tỷ lệ thuận với trọng lượng của mình so với tổng trọng lượng bể bơi. Một thành viên có trọng lượng = 4 nhận được gấp 4 lần số phiên so với trọng lượng = 1 thành viên. Dùng để làm mẫu khả năng phụ trợ không đồng nhất (ví dụ: VM so với máy chủ kim loại trần).
Băm nhất quán
Cả thành viên và khách hàng đều được ánh xạ vào một vòng tròn thông qua hàm băm. Mỗi khách hàng đi đến thành viên gần nhất theo chiều kim đồng hồ trên võ đài. Các nút ảo (bản sao cho mỗi thành viên) cải thiện tính đồng nhất phân phối. Khi một thành viên thất bại, chỉ có các phiên của nó chuyển sang thành viên tiếp theo trên võ đài — 1/N phiên bị xáo trộn so với 100% đối với băm modulo.