malc0mn / haproxy-config-builder
HAProxy 配置文件构建器和处理器。
Requires
- php: >=5.4.0
Requires (Dev)
- mikey179/vfsstream: ~1
- phpunit/phpunit: >=7.0
- symfony/var-dumper: ^3.4
This package is not auto-updated.
Last update: 2024-09-19 16:50:43 UTC
README
使用 composer 安装
打开 shell,cd 到您的项目目录,然后输入
composer require malc0mn/haproxy-config-builder
或编辑 composer.json 并添加
{
"require": {
"malc0mn/haproxy-config-builder": "~1.0"
}
}
使用示例
从头创建
require 'vendor/autoload.php'; use HAProxy\Config\Comment; use HAProxy\Config\Proxy\Backend; use HAProxy\Config\Proxy\Frontend; use HAProxy\Config\Proxy\Listen; use HAProxy\Config\Userlist; use HAProxy\Config\Config; $comment = <<<TEXT Simple configuration for an HTTP proxy listening on port 80 on all interfaces and forwarding requests to a single backend "servers" with a single server "server1" listening on 127.0.0.1:8000 TEXT; $config = Config::create() ->addComment( new Comment($comment) ) ->setDebug() ->setDaemon() ->addGlobal('maxconn', 256) ->addDefaults('mode', 'http') ->addDefaults('timeout', ['connect', '5000ms']) ->addDefaults('timeout', ['client', '50000ms']) ->addDefaults('timeout', ['server', '50000ms']) ->addUserlist( Userlist::create('developers') ->addUser('eddy', '$6$mlskxjmqlkcnmlcjsmdl', ['editor', 'admin']) ->addGroup('editor', []) ) ->addFrontend( Frontend::create('http-in') ->bind('*', 80) ->addParameter('default_backend', 'servers') ->addAcl('login_page', ['url_beg', '/login']) ) ->addBackend( Backend::create('servers') ->addServer('server1', '127.0.0.1', 8000, ['maxconn', 32]) ) ->addListen( Listen::create('ssh') ->addServer('ssh-host', '*', 22, 'maxconn 3') ) ; echo (string)$config;
从文件读取
require 'vendor/autoload.php'; use HAProxy\Config\Config; $configFromFile = Config::fromFile('/etc/haproxy/haproxy.conf'); var_export($configFromFile);
输出排序
代理块内的关键词排序
默认情况下,构建器的输出将按照您添加参数的顺序打印。这并不总是所需的,尤其是在处理您希望在设置 use_backend 调用之前出现在输出中的 ACL 时。
要解决这个问题,您可以使用 setParameterOrder() 方法来指示所需的打印顺序。示例
<?php require 'vendor/autoload.php'; use HAProxy\Config\Proxy\Frontend; $frontend = Frontend::create('www_frontend') ->addParameter('mode', 'http') ->addParameter('default_backend', 'www_backend') ->bind('*', 80) ->addAcl('is_https', 'hdr(X-Forwarded-Proto) -i https') ->addAcl('is_host_com', 'hdr(Host) -i example.com') ->addUseBackend('host_com', 'if is_host_com') ->addParameter('option', 'forwardfor') ; echo (string)$frontend; /* frontend www_frontend mode http default_backend www_backend bind *:80 acl is_https hdr(X-Forwarded-Proto) -i https acl is_host_com hdr(Host) -i example.com use_backend host_com if is_host_com option forwardfor */ $frontend->setParameterOrder(['bind', 'mode', 'option', 'acl', 'use_backend', 'default_backend']); echo (string)$frontend; /* frontend www_frontend bind *:80 mode http option forwardfor acl is_https hdr(X-Forwarded-Proto) -i https acl is_host_com hdr(Host) -i example.com use_backend host_com if is_host_com default_backend www_backend */ // Whitespace control: $frontend->setParameterOrder([ 'bind' => false, 'mode' => false, 'option' => true, // Add trailing whitespace! 'acl' => true, // Add trailing whitespace! 'use_backend' => true, // Add trailing whitespace! 'default_backend', ]); echo (string)$frontend; /* frontend www_frontend bind *:80 mode http option forwardfor acl is_https hdr(X-Forwarded-Proto) -i https acl is_host_com hdr(Host) -i example.com use_backend host_com if is_host_com default_backend www_backend */
配置文件中代理块的排序
代理块将根据其给定的优先级渲染,但有一些限制
global将始终首先渲染(第 1 位)。defaults将始终第 2 位渲染。resolvers将始终第 3 位渲染。userlist将始终第 4 位渲染。- 尝试在
defaults上设置打印优先级将引发异常。
因此,您只能控制 backend、frontend 和 listen 代理块的打印优先级。默认优先级设置为 1000。您可以通过在所需的代理块上调用 setPrintPriority() 方法来更改优先级:较小的整数表示更高的优先级!
require 'vendor/autoload.php'; use HAProxy\Config\Comment; use HAProxy\Config\Proxy\Backend; use HAProxy\Config\Proxy\Frontend; use HAProxy\Config\Proxy\Listen; use HAProxy\Config\Userlist; use HAProxy\Config\Config; $comment = <<<TEXT Simple configuration for an HTTP proxy listening on port 80 on all interfaces and forwarding requests to a single backend "servers" with a single server "server1" listening on 127.0.0.1:8000 TEXT; $config = Config::create() ->addComment( new Comment($comment) ) ->setDebug() ->setDaemon() ->addGlobal('maxconn', 256) ->addDefaults('mode', 'http') ->addDefaults('timeout', ['connect', '5000ms']) ->addDefaults('timeout', ['client', '50000ms']) ->addDefaults('timeout', ['server', '50000ms']) ->addUserlist( Userlist::create('developers') ->addUser('eddy', '$6$mlskxjmqlkcnmlcjsmdl', ['editor', 'admin']) ->addGroup('editor', []) ) ->addBackend( Backend::create('servers') ->addServer('server1', '127.0.0.1', 8000, ['maxconn', 32]) ->setPrintPriority(1002) ) ->addListen( Listen::create('ssh') ->addServer('ssh-host', '*', 22, 'maxconn 3') ) ->addFrontend( Frontend::create('http-in') ->bind('*', 80) ->addParameter('default_backend', 'servers') ->addAcl('login_page', ['url_beg', '/login']) ->setPrintPriority(1001) ) ; echo (string)$config; /* # Simple configuration for an HTTP proxy listening on port 80 on all # interfaces and forwarding requests to a single backend "servers" with a # single server "server1" listening on 127.0.0.1:8000 global maxconn 256 debug daemon defaults mode http timeout connect 5000ms timeout client 50000ms timeout server 50000ms userlist developers group editor user eddy password $6$mlskxjmqlkcnmlcjsmdl groups editor,admin listen ssh server ssh-host *:22 maxconn 3 frontend http-in bind *:80 default_backend servers acl login_page url_beg /login backend servers server server1 127.0.0.1:8000 maxconn 32 */
接下来做什么?
一旦您有了配置,您可以使用各种辅助方法来编程式地修改或更新配置。或者您可以使用这些辅助方法有条件地添加或删除设置...
require 'vendor/autoload.php'; use HAProxy\Config\Config; $config = Config::fromFile('/etc/haproxy/haproxy.conf'); if ($config->frontendExists('www') && !$config->backendExists('www')) { $config->removeFrontend('www'); } if ($config->listenExists('ssh')) { // Do stuff here. }
查看类以了解您可以利用什么。查看测试将让您非常了解您可以使用所有可用的方法做什么。
更复杂的内容
如果您需要更复杂的规则,需要多个 use_backend 调用到 同一 后端,则可以使用 标记后端。
考虑以下 HAProxy 前端代理块
frontend www_frontend
bind *:8080
mode http
http-request set-header X-Original-Path %[path]
acl is_host_website hdr(host) -i website.example.com
acl is_host_api hdr(host) -i api.example.com
acl is_path_admin hdr_beg(X-Original-Path) -i /admin
acl is_path_api hdr_beg(X-Original-Path) -i /api
# Path mappings MUST come first AND in separate use_backend statements.
use_backend website if is_host_website is_path_admin
use_backend api if is_host_webste is_path_api
# Regular host mappings.
use_backend website if is_host_website
use_backend api if is_host_api
此示例使用路径映射将流量重定向到不同的后端。应该很明显,您不能写入此内容来实现相同的功能
frontend www_frontend
bind *:8080
mode http
http-request set-header X-Original-Path %[path]
acl is_host_website hdr(host) -i website.example.com
acl is_host_api hdr(host) -i api.example.com
acl is_path_admin hdr_beg(X-Original-Path) -i /admin
acl is_path_api hdr_beg(X-Original-Path) -i /api
use_backend website if is_host_website is_path_admin || is_host_website
use_backend api if is_host_webste is_path_api || is_host_api
上述示例永远不会将您重定向到 API 后端,当调用 website.example.com/api url 时,因为第一个 use_backend 语句将
- 看到主机 是
website.example.com且路径 不是/admin,因此它将继续下一个条件 - 看到主机 是
website.example.com并将其重定向到website后端。
要使用此库重新创建第一个正确示例,您可以使用 标记后端
$frontend = Frontend::create('www_frontend') ->bind('*', 8080) ->addParameter('mode', 'http') ->addParameter('http-request', 'set-header X-Original-Path %[path]') ->addAcl('is_host_website', 'hdr(host) -i website.example.com') ->addAcl('is_host_api', 'hdr(host) -i api.example.com') ->addAcl('is_path_admin', 'hdr_beg(X-Original-Path) -i /admin') ->addAcl('is_path_api', 'hdr_beg(X-Original-Path) -i /api') // Here come the 'tagged' backends. ->addUseBackendWithConditions( 'website', ['is_host_website', 'is_path_admin'], 'if', // This is the condition, 'if' is the default. 'path_acl' // This is the tag. ) ->addUseBackendWithConditions( 'api', ['is_host_website', 'is_path_api'], 'if', // This is the condition, 'if' is the default. 'path_acl' // This is the tag. ) // The 'regular' backends. ->addUseBackendWithConditions('website', ['is_host_website']) ->addUseBackendWithConditions('api', ['is_host_api']) ; echo (string)$frontend; /* frontend www_frontend bind *:8080 mode http http-request set-header X-Original-Path %[path] acl is_host_website hdr(host) -i website.example.com acl is_host_api hdr(host) -i api.example.com acl is_path_admin hdr_beg(X-Original-Path) -i /admin acl is_path_api hdr_beg(X-Original-Path) -i /api use_backend website if is_host_website is_path_admin use_backend api if is_host_website is_path_api use_backend website if is_host_website use_backend api if is_host_api */
致谢
所使用的方法基于 romanpitak 的 Nginx 配置处理器。