HAProxy 配置生成器

生成 HAProxy 负载均衡配置文件,支持 frontend、backend、server、健康检查、ACL 规则等完整结构

📋 全局配置 (Global & Defaults)
🌐 Frontend 配置
🖥️ Backend 服务器列表
🔒 ACL 规则
❤️ 健康检查配置
let servers = [ { name: 'web1', host: '192.168.1.10', port: '80', weight: '100', check: true }, { name: 'web2', host: '192.168.1.11', port: '80', weight: '100', check: true }, ]; let acls = []; function renderServers() { const el = document.getElementById('serverList'); if (servers.length === 0) { el.innerHTML = '
暂无服务器,点击上方按钮添加
'; return; } el.innerHTML = servers.map((s, i) => `
`).join(''); } function addServer() { servers.push({ name: `web${servers.length + 1}`, host: '', port: '80', weight: '100', check: true }); renderServers(); } function removeServer(i) { servers.splice(i, 1); renderServers(); } function renderAcls() { const el = document.getElementById('aclList'); if (acls.length === 0) { el.innerHTML = '
暂无 ACL 规则,点击上方按钮添加
'; return; } el.innerHTML = acls.map((a, i) => `
`).join(''); } function addAcl() { acls.push({ type: 'hdr(host)', pattern: '', backend: '' }); renderAcls(); } function removeAcl(i) { acls.splice(i, 1); renderAcls(); } function toggleHealthOptions() { const t = document.getElementById('healthCheckType').value; document.getElementById('healthUriGroup').style.display = t === 'http' ? '' : 'none'; document.getElementById('healthExpectGroup').style.display = t === 'http' ? '' : 'none'; } function generate() { const mode = document.getElementById('mode').value; const balance = document.getElementById('balance').value; const maxconn = document.getElementById('maxconn').value; const logServer = document.getElementById('logServer').value; const user = document.getElementById('user').value; const group = document.getElementById('group').value; const timeoutConnect = document.getElementById('timeoutConnect').value; const timeoutClient = document.getElementById('timeoutClient').value; const timeoutServer = document.getElementById('timeoutServer').value; const frontendName = document.getElementById('frontendName').value; const bindAddr = document.getElementById('bindAddr').value; const defaultBackend = document.getElementById('defaultBackend').value; let config = ''; // Global section config += `global\n`; config += ` log ${logServer}\n`; config += ` maxconn ${maxconn}\n`; config += ` user ${user}\n`; config += ` group ${group}\n`; config += ` daemon\n\n`; // Defaults section config += `defaults\n`; config += ` log global\n`; config += ` mode ${mode}\n`; config += ` option httplog\n`; config += ` option dontlognull\n`; config += ` timeout connect ${timeoutConnect}ms\n`; config += ` timeout client ${timeoutClient}ms\n`; config += ` timeout server ${timeoutServer}ms\n`; config += ` retries 3\n\n`; // Frontend config += `#---------------------------------------------------------------------\n`; config += `# Frontend: ${frontendName}\n`; config += `#---------------------------------------------------------------------\n`; config += `frontend ${frontendName}\n`; config += ` bind ${bindAddr}\n`; if (mode === 'http') { config += ` option forwardfor except 127.0.0.0/8\n`; } // ACL rules acls.forEach((a, i) => { if (a.pattern && a.backend) { config += ` acl is_acl${i} ${a.type} ${a.pattern}\n`; config += ` use_backend ${a.backend} if is_acl${i}\n`; } }); config += ` default_backend ${defaultBackend}\n\n`; // Backend config += `#---------------------------------------------------------------------\n`; config += `# Backend: ${defaultBackend}\n`; config += `#---------------------------------------------------------------------\n`; config += `backend ${defaultBackend}\n`; config += ` mode ${mode}\n`; config += ` balance ${balance}\n`; config += ` option httpchk GET / HTTP/1.0\\r\\nHost:\\ localhost\n` if mode === 'http' else ''; // Health check options const healthType = document.getElementById('healthCheckType').value; if (healthType !== 'none') { const interval = document.getElementById('healthInterval').value; const fall = document.getElementById('healthFall').value; const rise = document.getElementById('healthRise').value; if (healthType === 'tcp') { config += ` option tcp-check\n`; } else if (healthType === 'http') { const uri = document.getElementById('healthUri').value; const expect = document.getElementById('healthExpect').value; config += ` option http-check expect ${expect}\n`; } else if (healthType === 'ssl') { config += ` option ssl-hello-chk\n`; } config += ` default-server inter ${interval}ms fall ${fall} rise ${rise}\n`; } // Servers servers.forEach(s => { if (!s.host) return; let serverLine = ` server ${s.name} ${s.host}:${s.port} weight ${s.weight}`; if (healthType !== 'none') { serverLine += ' check'; } config += `${serverLine}\n`; }); config += '\n'; // Stats page config += `#---------------------------------------------------------------------\n`; config += `# Statistics Page\n`; config += `#---------------------------------------------------------------------\n`; config += `listen stats\n`; config += ` bind *:8400\n`; config += ` stats enable\n`; config += ` stats uri /haproxy-stats\n`; config += ` stats refresh 10s\n`; config += ` stats auth admin:admin\n`; document.getElementById('resultOutput').textContent = config; document.getElementById('resultCard').style.display = ''; } function copyResult() { const text = document.getElementById('resultOutput').textContent; navigator.clipboard.writeText(text).then(() => { const btn = event.target; btn.textContent = '已复制!'; setTimeout(() => btn.textContent = '复制', 1500); }); } function resetForm() { document.getElementById('maxconn').value = '4096'; document.getElementById('logServer').value = '127.0.0.1 local0'; document.getElementById('user').value = 'haproxy'; document.getElementById('group').value = 'haproxy'; document.getElementById('mode').value = 'http'; document.getElementById('balance').value = 'roundrobin'; document.getElementById('timeoutConnect').value = '5000'; document.getElementById('timeoutClient').value = '30000'; document.getElementById('timeoutServer').value = '30000'; document.getElementById('frontendName').value = 'http_front'; document.getElementById('bindAddr').value = '*:80'; document.getElementById('defaultBackend').value = 'web_backend'; document.getElementById('healthCheckType').value = 'none'; document.getElementById('healthInterval').value = '2000'; document.getElementById('healthFall').value = '3'; document.getElementById('healthRise').value = '2'; document.getElementById('healthUri').value = '/health'; document.getElementById('healthExpect').value = 'status 200'; servers = [ { name: 'web1', host: '192.168.1.10', port: '80', weight: '100', check: true }, { name: 'web2', host: '192.168.1.11', port: '80', weight: '100', check: true }, ]; acls = []; renderServers(); renderAcls(); toggleHealthOptions(); document.getElementById('resultCard').style.display = 'none'; } renderServers(); renderAcls();